diff --git a/libvips/conversion/premultiply.c b/libvips/conversion/premultiply.c index 0560237e..11e7466d 100644 --- a/libvips/conversion/premultiply.c +++ b/libvips/conversion/premultiply.c @@ -281,7 +281,7 @@ vips_premultiply_init( VipsPremultiply *premultiply ) * alpha = clip( 0, in[in.bands - 1], @max_alpha ); * norm = alpha / @max_alpha; * out = [in[0] * norm, ..., in[in.bands - 1] * norm, alpha]; - * |] + * ]| * * So for an N-band image, the first N - 1 bands are multiplied by the clipped * and normalised final band, the final band is clipped. diff --git a/libvips/conversion/unpremultiply.c b/libvips/conversion/unpremultiply.c index 28e998a3..6105d1e5 100644 --- a/libvips/conversion/unpremultiply.c +++ b/libvips/conversion/unpremultiply.c @@ -296,7 +296,7 @@ vips_unpremultiply_init( VipsUnpremultiply *unpremultiply ) * out = [0, ..., 0, alpha]; * else * out = [in[0] / norm, ..., in[in.bands - 1] / norm, alpha]; - * |] + * ]| * * So for an N-band image, the first N - 1 bands are divided by the clipped * and normalised final band, the final band is clipped. diff --git a/libvips/foreign/openslide2vips.c b/libvips/foreign/openslide2vips.c index 42165ada..4df9e2b1 100644 --- a/libvips/foreign/openslide2vips.c +++ b/libvips/foreign/openslide2vips.c @@ -409,15 +409,15 @@ vips__openslide_read_header( const char *filename, VipsImage *out, * compatibility with older vipses. */ static void -argb2rgba( uint32_t *buf, int n, uint32_t bg ) +argb2rgba( uint32_t * restrict buf, int n, uint32_t bg ) { int i; for( i = 0; i < n; i++ ) { - uint32_t *p = buf + i; + uint32_t * restrict p = buf + i; uint32_t x = *p; uint8_t a = x >> 24; - VipsPel *out = (VipsPel *) p; + VipsPel * restrict out = (VipsPel *) p; if( a == 255 ) *p = GUINT32_TO_BE( (x << 8) | 255 ); diff --git a/libvips/foreign/pdfload.c b/libvips/foreign/pdfload.c index 04414c3c..bb29af83 100644 --- a/libvips/foreign/pdfload.c +++ b/libvips/foreign/pdfload.c @@ -234,7 +234,7 @@ vips_foreign_load_pdf_generate( VipsRegion *or, cairo_surface_t *surface; cairo_t *cr; - int x, y; + int y; /* printf( "vips_foreign_load_pdf_generate: " @@ -266,19 +266,12 @@ vips_foreign_load_pdf_generate( VipsRegion *or, cairo_destroy( cr ); - /* Cairo makes BRGA, we must byteswap. We might not need to on SPARC, - * but I have no way of testing this :( + /* Cairo makes pre-multipled BRGA, we must byteswap and unpremultiply. */ - for( y = 0; y < r->height; y++ ) { - VipsPel * restrict q; - - q = VIPS_REGION_ADDR( or, r->left, r->top + y ); - for( x = 0; x < r->width; x++ ) { - VIPS_SWAP( VipsPel, q[0], q[2] ); - - q += 4; - } - } + for( y = 0; y < r->height; y++ ) + vips__cairo2rgba( + (guint32 *) VIPS_REGION_ADDR( or, r->left, r->top + y ), + r->width ); return( 0 ); } diff --git a/libvips/foreign/svgload.c b/libvips/foreign/svgload.c index 67229efa..f814c114 100644 --- a/libvips/foreign/svgload.c +++ b/libvips/foreign/svgload.c @@ -149,6 +149,34 @@ vips_foreign_load_svg_header( VipsForeignLoad *load ) return( 0 ); } +/* Convert from ARGB to RGBA and undo premultiplication. + */ +void +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; + + 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; + } + } +} + static int vips_foreign_load_svg_generate( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) @@ -159,7 +187,7 @@ vips_foreign_load_svg_generate( VipsRegion *or, cairo_surface_t *surface; cairo_t *cr; - int x, y; + int y; /* rsvg won't always paint the background. */ @@ -188,19 +216,12 @@ vips_foreign_load_svg_generate( VipsRegion *or, cairo_destroy( cr ); - /* Cairo makes BRGA, we must byteswap. We might not need to on SPARC, - * but I have no way of testing this :( + /* Cairo makes pre-multipled BRGA, we must byteswap and unpremultiply. */ - for( y = 0; y < r->height; y++ ) { - VipsPel * restrict q; - - q = VIPS_REGION_ADDR( or, r->left, r->top + y ); - for( x = 0; x < r->width; x++ ) { - VIPS_SWAP( VipsPel, q[0], q[2] ); - - q += 4; - } - } + for( y = 0; y < r->height; y++ ) + vips__cairo2rgba( + (guint32 *) VIPS_REGION_ADDR( or, r->left, r->top + y ), + r->width ); return( 0 ); } diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index 31bc6123..9ce71efc 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -231,6 +231,8 @@ int vips__byteswap_bool( VipsImage *in, VipsImage **out, gboolean swap ); char *vips__make_xml_metadata( const char *domain, VipsImage *image ); +void vips__cairo2rgba( guint32 *buf, int n ); + #ifdef __cplusplus } #endif /*__cplusplus*/