diff --git a/libvips/colour/sRGB2scRGB.c b/libvips/colour/sRGB2scRGB.c index 0b0e877e..7840bc2b 100644 --- a/libvips/colour/sRGB2scRGB.c +++ b/libvips/colour/sRGB2scRGB.c @@ -73,6 +73,24 @@ typedef VipsOperationClass VipssRGB2scRGBClass; G_DEFINE_TYPE( VipssRGB2scRGB, vips_sRGB2scRGB, VIPS_TYPE_OPERATION ); +/* Convert an 8-bit pixel. + */ +static void +vips_sRGB2scRGB_pel_rgb_8( float * restrict q, + VipsPel * restrict p ) +{ + const int r = p[0]; + const int g = p[1]; + const int b = p[2]; + + float R, G, B; + vips_col_sRGB2scRGB_8( r, g, b, &R, &G, &B ); + + q[0] = R; + q[1] = G; + q[2] = B; +} + /* Convert a buffer of 8-bit pixels. */ static void @@ -81,28 +99,51 @@ vips_sRGB2scRGB_line_8( float * restrict q, VipsPel * restrict p, { int i, j; - for( i = 0; i < width; i++ ) { - int r = p[0]; - int g = p[1]; - int b = p[2]; - - float R, G, B; - - p += 3; - - vips_col_sRGB2scRGB_8( r, g, b, &R, &G, &B ); - - q[0] = R; - q[1] = G; - q[2] = B; - - q += 3; - - for( j = 0; j < extra_bands; j++ ) - q[j] = p[j]; - p += extra_bands; - q += extra_bands; + if( extra_bands == 0 ) { + for( i = 0; i < width; i++ ) { + vips_sRGB2scRGB_pel_rgb_8(q, p); + p += 3; + q += 3; + } } + else if( extra_bands == 1 ) { + for( i = 0; i < width; i++ ) { + vips_sRGB2scRGB_pel_rgb_8(q, p); + q[3] = p[3]; + p += 4; + q += 4; + } + } + else { + for( i = 0; i < width; i++ ) { + vips_sRGB2scRGB_pel_rgb_8(q, p); + p += 3; + q += 3; + + for( j = 0; j < extra_bands; j++ ) + q[j] = p[j]; + p += extra_bands; + q += extra_bands; + } + } +} + +/* Convert a 16-bit pixel. + */ +static void +vips_sRGB2scRGB_pel_rgb_16( float * restrict q, + unsigned short * restrict p ) +{ + const int r = p[0]; + const int g = p[1]; + const int b = p[2]; + + float R, G, B; + vips_col_sRGB2scRGB_16( r, g, b, &R, &G, &B ); + + q[0] = R; + q[1] = G; + q[2] = B; } /* Convert a buffer of 16-bit pixels. @@ -113,27 +154,32 @@ vips_sRGB2scRGB_line_16( float * restrict q, unsigned short * restrict p, { int i, j; - for( i = 0; i < width; i++ ) { - int r = p[0]; - int g = p[1]; - int b = p[2]; + if( extra_bands == 0 ) { + for( i = 0; i < width; i++ ) { + vips_sRGB2scRGB_pel_rgb_16(q, p); + p += 3; + q += 3; + } + } + else if( extra_bands == 1 ) { + for( i = 0; i < width; i++ ) { + vips_sRGB2scRGB_pel_rgb_16(q, p); + q[3] = p[3] / 256.0; + p += 4; + q += 4; + } + } + else { + for( i = 0; i < width; i++ ) { + vips_sRGB2scRGB_pel_rgb_16(q, p); + p += 3; + q += 3; - float R, G, B; - - p += 3; - - vips_col_sRGB2scRGB_16( r, g, b, &R, &G, &B ); - - q[0] = R; - q[1] = G; - q[2] = B; - - q += 3; - - for( j = 0; j < extra_bands; j++ ) - q[j] = p[j] / 256.0; - p += extra_bands; - q += extra_bands; + for( j = 0; j < extra_bands; j++ ) + q[j] = p[j] / 256.0; + p += extra_bands; + q += extra_bands; + } } } @@ -152,17 +198,25 @@ vips_sRGB2scRGB_gen( VipsRegion *or, VIPS_GATE_START( "vips_sRGB2scRGB_gen: work" ); - for( y = 0; y < r->height; y++ ) { - VipsPel *p = VIPS_REGION_ADDR( ir, r->left, r->top + y ); - float *q = (float *) - VIPS_REGION_ADDR( or, r->left, r->top + y ); + if( in->BandFmt == VIPS_FORMAT_UCHAR ) { + for( y = 0; y < r->height; y++ ) { + VipsPel *p = VIPS_REGION_ADDR( ir, r->left, r->top + y ); + float *q = (float *) + VIPS_REGION_ADDR( or, r->left, r->top + y ); - if( in->BandFmt == VIPS_FORMAT_UCHAR ) vips_sRGB2scRGB_line_8( q, p, in->Bands - 3, r->width ); - else + } + } + else { + for( y = 0; y < r->height; y++ ) { + VipsPel *p = VIPS_REGION_ADDR( ir, r->left, r->top + y ); + float *q = (float *) + VIPS_REGION_ADDR( or, r->left, r->top + y ); + vips_sRGB2scRGB_line_16( q, (unsigned short *) p, in->Bands - 3, r->width ); + } } VIPS_GATE_STOP( "vips_sRGB2scRGB_gen: work" );