improve BGRA -> RGBA conversion

This commit is contained in:
John Cupitt 2020-10-16 18:53:45 +01:00
parent 50288c5f18
commit 93f67a2bdf
2 changed files with 35 additions and 26 deletions

View File

@ -35,7 +35,7 @@
#include <vips/vips.h> #include <vips/vips.h>
#include <vips/internal.h> #include <vips/internal.h>
/* Convert from ARGB to RGBA and undo premultiplication. /* Convert from Cairo's BGRA to RGBA and undo premultiplication.
* *
* See also openslide's argb2rgba(). * See also openslide's argb2rgba().
*/ */
@ -45,22 +45,26 @@ vips__cairo2rgba( guint32 * restrict buf, int n )
int i; int i;
for( i = 0; i < n; i++ ) { for( i = 0; i < n; i++ ) {
guint32 * restrict p = buf + i; guint32 bgra = GUINT32_FROM_BE( buf[i] );
guint32 x = *p; guint8 a = bgra & 0xff;
guint8 a = x >> 24;
VipsPel * restrict out = (VipsPel *) p;
if( a == 255 ) guint32 rgba;
*p = GUINT32_TO_BE( (x << 8) | 255 );
else if( a == 0 ) if( a == 0 ||
*p = GUINT32_TO_BE( x << 8 ); a == 255 )
else { rgba =
/* Undo premultiplication. (bgra & 0x00ff00ff) |
*/ (bgra & 0x0000ff00) << 16 |
out[0] = 255 * ((x >> 16) & 255) / a; (bgra & 0xff000000) >> 16;
out[1] = 255 * ((x >> 8) & 255) / a; else
out[2] = 255 * (x & 255) / a; /* Undo premultiplication.
out[3] = a; */
} 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 );
} }
} }

View File

@ -43,7 +43,6 @@
/* TODO /* TODO
* *
* - speed up BRGA -> RGBA conversion
* - what about filename encodings? * - what about filename encodings?
* - need to test on Windows * - need to test on Windows
*/ */
@ -569,19 +568,25 @@ vips_foreign_load_pdf_generate( VipsRegion *or,
i += 1; i += 1;
} }
/* PDFium writes BRGA, we must swap. /* PDFium writes BGRA, we must swap.
*
* FIXME ... this is slow, try using vips__cairo2rgba()? Do we need to
* unpremultiply as well?
*/ */
for( y = 0; y < r->height; y++ ) { for( y = 0; y < r->height; y++ ) {
VipsPel *p; guint32 * restrict p =
(guint32 *) VIPS_REGION_ADDR( or, r->left, r->top + y );
int x; int x;
p = VIPS_REGION_ADDR( or, r->left, r->top + y );
for( x = 0; x < r->width; x++ ) { for( x = 0; x < r->width; x++ ) {
VIPS_SWAP( VipsPel, p[0], p[2] ); guint32 bgra = GUINT32_FROM_BE( p[x] );
p += 4;
guint rgba;
rgba =
(bgra & 0x00ff00ff) |
(bgra & 0x0000ff00) << 16 |
(bgra & 0xff000000) >> 16;
p[x] = GUINT32_TO_BE( rgba );
} }
} }