diff --git a/libvips/foreign/cairo.c b/libvips/foreign/cairo.c index b242ab49..e922cbbe 100644 --- a/libvips/foreign/cairo.c +++ b/libvips/foreign/cairo.c @@ -35,7 +35,7 @@ #include #include -/* Convert from ARGB to RGBA and undo premultiplication. +/* Convert from Cairo's BGRA to RGBA and undo premultiplication. * * See also openslide's argb2rgba(). */ @@ -45,22 +45,26 @@ vips__cairo2rgba( guint32 * restrict buf, int n ) int i; for( i = 0; i < n; i++ ) { - guint32 * restrict p = buf + i; - guint32 x = *p; - guint8 a = x >> 24; - VipsPel * restrict out = (VipsPel *) p; + guint32 bgra = GUINT32_FROM_BE( buf[i] ); + guint8 a = bgra & 0xff; - if( a == 255 ) - *p = GUINT32_TO_BE( (x << 8) | 255 ); - else if( a == 0 ) - *p = GUINT32_TO_BE( x << 8 ); - else { - /* Undo premultiplication. - */ - out[0] = 255 * ((x >> 16) & 255) / a; - out[1] = 255 * ((x >> 8) & 255) / a; - out[2] = 255 * (x & 255) / a; - out[3] = a; - } + guint32 rgba; + + if( a == 0 || + a == 255 ) + rgba = + (bgra & 0x00ff00ff) | + (bgra & 0x0000ff00) << 16 | + (bgra & 0xff000000) >> 16; + else + /* Undo premultiplication. + */ + rgba = + ((255 * ((bgra >> 8) & 0xff) / a) << 24) | + ((255 * ((bgra >> 16) & 0xff) / a) << 16) | + ((255 * ((bgra >> 24) & 0xff) / a) << 8) | + a; + + buf[i] = GUINT32_TO_BE( rgba ); } } diff --git a/libvips/foreign/pdfiumload.c b/libvips/foreign/pdfiumload.c index d0b46463..038552bf 100644 --- a/libvips/foreign/pdfiumload.c +++ b/libvips/foreign/pdfiumload.c @@ -43,7 +43,6 @@ /* TODO * - * - speed up BRGA -> RGBA conversion * - what about filename encodings? * - need to test on Windows */ @@ -569,19 +568,25 @@ vips_foreign_load_pdf_generate( VipsRegion *or, i += 1; } - /* PDFium writes BRGA, we must swap. - * - * FIXME ... this is slow, try using vips__cairo2rgba()? Do we need to - * unpremultiply as well? + /* PDFium writes BGRA, we must swap. */ for( y = 0; y < r->height; y++ ) { - VipsPel *p; + guint32 * restrict p = + (guint32 *) VIPS_REGION_ADDR( or, r->left, r->top + y ); + int x; - p = VIPS_REGION_ADDR( or, r->left, r->top + y ); for( x = 0; x < r->width; x++ ) { - VIPS_SWAP( VipsPel, p[0], p[2] ); - p += 4; + guint32 bgra = GUINT32_FROM_BE( p[x] ); + + guint rgba; + + rgba = + (bgra & 0x00ff00ff) | + (bgra & 0x0000ff00) << 16 | + (bgra & 0xff000000) >> 16; + + p[x] = GUINT32_TO_BE( rgba ); } }