diff --git a/libvips/colour/LCh2Lab.c b/libvips/colour/LCh2Lab.c index 9f615cd3..861874a3 100644 --- a/libvips/colour/LCh2Lab.c +++ b/libvips/colour/LCh2Lab.c @@ -57,6 +57,22 @@ typedef VipsColourTransformClass VipsLCh2LabClass; G_DEFINE_TYPE( VipsLCh2Lab, vips_LCh2Lab, VIPS_TYPE_COLOUR_TRANSFORM ); +/** + * vips_col_Ch2ab: + * @C: Chroma + * @h: Hue angle (degrees) + * @a: return CIE a* value + * @b: return CIE b* value + * + * Calculate ab from Ch, h in degrees. + */ +void +vips_col_Ch2ab( float C, float h, float *a, float *b ) +{ + *a = C * cos( VIPS_RAD( h ) ); + *b = C * sin( VIPS_RAD( h ) ); +} + /* Process a buffer of data. */ static void @@ -75,8 +91,7 @@ vips_LCh2Lab_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) p += 3; - a = C * cos( VIPS_RAD( h ) ); - b = C * sin( VIPS_RAD( h ) ); + vips_col_Ch2ab( C, h, &a, &b ); q[0] = L; q[1] = a; @@ -86,35 +101,6 @@ vips_LCh2Lab_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) } } -/** - * vips_col_Ch2ab: - * @C: Chroma - * @h: Hue angle (degrees) - * @a: return CIE a* value - * @b: return CIE b* value - * - * Calculate ab from Ch, h in degrees. - */ -void -vips_col_Ch2ab( float C, float h, float *a, float *b ) -{ - float in[3]; - float out[3]; - float *x; - - /* could be anything, we don't use this value, but we must supply one - * or static analyzers will complain. - */ - in[0] = 50.0; - - in[1] = C; - in[2] = h; - x = &in[0]; - vips_LCh2Lab_line( NULL, (VipsPel *) out, (VipsPel **) &x, 1 ); - *a = out[1]; - *b = out[2]; -} - static void vips_LCh2Lab_class_init( VipsLCh2LabClass *class ) { diff --git a/libvips/colour/Lab2XYZ.c b/libvips/colour/Lab2XYZ.c index 5e229e41..2d65d2e6 100644 --- a/libvips/colour/Lab2XYZ.c +++ b/libvips/colour/Lab2XYZ.c @@ -80,6 +80,34 @@ typedef VipsColourTransformClass VipsLab2XYZClass; G_DEFINE_TYPE( VipsLab2XYZ, vips_Lab2XYZ, VIPS_TYPE_COLOUR_TRANSFORM ); +static void +vips_col_Lab2XYZ_helper( VipsLab2XYZ *Lab2XYZ, + float L, float a, float b, float *X, float *Y, float *Z ) +{ + double cby, tmp; + + if( L < 8.0 ) { + *Y = (L * Lab2XYZ->Y0) / 903.3; + cby = 7.787 * (*Y / Lab2XYZ->Y0) + 16.0 / 116.0; + } + else { + cby = (L + 16.0) / 116.0; + *Y = Lab2XYZ->Y0 * cby * cby * cby; + } + + tmp = a / 500.0 + cby; + if( tmp < 0.2069 ) + *X = Lab2XYZ->X0 * (tmp - 0.13793) / 7.787; + else + *X = Lab2XYZ->X0 * tmp * tmp * tmp; + + tmp = cby - b / 200.0; + if( tmp < 0.2069 ) + *Z = Lab2XYZ->Z0 * (tmp - 0.13793) / 7.787; + else + *Z = Lab2XYZ->Z0 * tmp * tmp * tmp; +} + /* Process a buffer of data. */ static void @@ -97,33 +125,13 @@ vips_Lab2XYZ_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) for( x = 0; x < width; x++ ) { float L, a, b; float X, Y, Z; - double cby, tmp; L = p[0]; a = p[1]; b = p[2]; p += 3; - if( L < 8.0 ) { - Y = (L * Lab2XYZ->Y0) / 903.3; - cby = 7.787 * (Y / Lab2XYZ->Y0) + 16.0 / 116.0; - } - else { - cby = (L + 16.0) / 116.0; - Y = Lab2XYZ->Y0 * cby * cby * cby; - } - - tmp = a / 500.0 + cby; - if( tmp < 0.2069 ) - X = Lab2XYZ->X0 * (tmp - 0.13793) / 7.787; - else - X = Lab2XYZ->X0 * tmp * tmp * tmp; - - tmp = cby - b / 200.0; - if( tmp < 0.2069 ) - Z = Lab2XYZ->Z0 * (tmp - 0.13793) / 7.787; - else - Z = Lab2XYZ->Z0 * tmp * tmp * tmp; + vips_col_Lab2XYZ_helper( Lab2XYZ, L, a, b, &X, &Y, &Z ); /* Write. */ @@ -234,23 +242,11 @@ vips_Lab2XYZ( VipsImage *in, VipsImage **out, ... ) */ void vips_col_Lab2XYZ( float L, float a, float b, float *X, float *Y, float *Z ) -{ - float in[3]; - float *x; - float out[3]; +{ VipsLab2XYZ Lab2XYZ; - in[0] = L; - in[1] = a; - in[2] = b; - x = in; Lab2XYZ.X0 = VIPS_D65_X0; Lab2XYZ.Y0 = VIPS_D65_Y0; Lab2XYZ.Z0 = VIPS_D65_Z0; - vips_Lab2XYZ_line( (VipsColour *) &Lab2XYZ, - (VipsPel *) out, (VipsPel **) &x, 1 ); - *X = out[0]; - *Y = out[1]; - *Z = out[2]; + vips_col_Lab2XYZ_helper( &Lab2XYZ, L, a, b, X, Y, Z ); } - diff --git a/libvips/colour/XYZ2Lab.c b/libvips/colour/XYZ2Lab.c index f7a959c0..4770364a 100644 --- a/libvips/colour/XYZ2Lab.c +++ b/libvips/colour/XYZ2Lab.c @@ -107,49 +107,67 @@ table_init( void *client ) return( NULL ); } +static void +vips_col_XYZ2Lab_helper( VipsXYZ2Lab *XYZ2Lab, + float X, float Y, float Z, float *L, float *a, float *b ) +{ + static GOnce once = G_ONCE_INIT; + + VIPS_ONCE( &once, table_init, NULL ); + + float nX, nY, nZ; + int i; + float f; + float cbx, cby, cbz; + + nX = QUANT_ELEMENTS * X / XYZ2Lab->X0; + nY = QUANT_ELEMENTS * Y / XYZ2Lab->Y0; + nZ = QUANT_ELEMENTS * Z / XYZ2Lab->Z0; + + /* CLIP is much faster than FCLIP, and we want an int result. + */ + i = VIPS_CLIP( 0, (int) nX, QUANT_ELEMENTS - 2 ); + f = nX - i; + cbx = cbrt_table[i] + f * (cbrt_table[i + 1] - cbrt_table[i]); + + i = VIPS_CLIP( 0, (int) nY, QUANT_ELEMENTS - 2 ); + f = nY - i; + cby = cbrt_table[i] + f * (cbrt_table[i + 1] - cbrt_table[i]); + + i = VIPS_CLIP( 0, (int) nZ, QUANT_ELEMENTS - 2 ); + f = nZ - i; + cbz = cbrt_table[i] + f * (cbrt_table[i + 1] - cbrt_table[i]); + + *L = 116.0 * cby - 16.0; + *a = 500.0 * (cbx - cby); + *b = 200.0 * (cby - cbz); +} + /* Process a buffer of data. */ static void vips_XYZ2Lab_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) { - static GOnce once = G_ONCE_INIT; - VipsXYZ2Lab *XYZ2Lab = (VipsXYZ2Lab *) colour; float *p = (float *) in[0]; float *q = (float *) out; int x; - VIPS_ONCE( &once, table_init, NULL ); - for( x = 0; x < width; x++ ) { - float nX, nY, nZ; - int i; - float f; - float cbx, cby, cbz; + float X, Y, Z; + float L, a, b; - nX = QUANT_ELEMENTS * p[0] / XYZ2Lab->X0; - nY = QUANT_ELEMENTS * p[1] / XYZ2Lab->Y0; - nZ = QUANT_ELEMENTS * p[2] / XYZ2Lab->Z0; + X = p[0]; + Y = p[1]; + Z = p[2]; p += 3; - /* CLIP is much faster than FCLIP, and we want an int result. - */ - i = VIPS_CLIP( 0, (int) nX, QUANT_ELEMENTS - 2 ); - f = nX - i; - cbx = cbrt_table[i] + f * (cbrt_table[i + 1] - cbrt_table[i]); + vips_col_XYZ2Lab_helper( XYZ2Lab, X, Y, Z, &L, &a, &b ); - i = VIPS_CLIP( 0, (int) nY, QUANT_ELEMENTS - 2 ); - f = nY - i; - cby = cbrt_table[i] + f * (cbrt_table[i + 1] - cbrt_table[i]); - - i = VIPS_CLIP( 0, (int) nZ, QUANT_ELEMENTS - 2 ); - f = nZ - i; - cbz = cbrt_table[i] + f * (cbrt_table[i + 1] - cbrt_table[i]); - - q[0] = 116.0 * cby - 16.0; - q[1] = 500.0 * (cbx - cby); - q[2] = 200.0 * (cby - cbz); + q[0] = L; + q[1] = a; + q[2] = b; q += 3; } } @@ -169,24 +187,13 @@ vips_XYZ2Lab_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) */ void vips_col_XYZ2Lab( float X, float Y, float Z, float *L, float *a, float *b ) -{ - float in[3]; - float out[3]; - float *x; +{ VipsXYZ2Lab XYZ2Lab; - in[0] = X; - in[1] = Y; - in[2] = Z; - x = in; XYZ2Lab.X0 = VIPS_D65_X0; XYZ2Lab.Y0 = VIPS_D65_Y0; XYZ2Lab.Z0 = VIPS_D65_Z0; - vips_XYZ2Lab_line( (VipsColour *) &XYZ2Lab, - (VipsPel *) out, (VipsPel **) &x, 1 ); - *L = out[0]; - *a = out[1]; - *b = out[2]; + vips_col_XYZ2Lab_helper( &XYZ2Lab, X, Y, Z, L, a, b ); } static int @@ -273,4 +280,3 @@ vips_XYZ2Lab( VipsImage *in, VipsImage **out, ... ) return( result ); } - diff --git a/libvips/foreign/jp2ksave.c b/libvips/foreign/jp2ksave.c index 62420b1b..bb749ac9 100644 --- a/libvips/foreign/jp2ksave.c +++ b/libvips/foreign/jp2ksave.c @@ -828,16 +828,16 @@ vips_foreign_save_jp2k_build( VipsObject *object ) jp2k->parameters.cp_tdx = jp2k->tile_width; jp2k->parameters.cp_tdy = jp2k->tile_height; - /* Makes three band images smaller, somehow. + /* Makes many-band, non-subsampled images smaller, somehow. */ - jp2k->parameters.tcp_mct = save->ready->Bands >= 3 ? 1 : 0; + jp2k->parameters.tcp_mct = save->ready->Bands >= 3 && !jp2k->subsample; /* Number of layers to write. Smallest layer is c. 2^5 on the smallest * axis. */ jp2k->parameters.numresolution = VIPS_MAX( 1, log( VIPS_MIN( save->ready->Xsize, save->ready->Ysize ) ) / - log( 2 ) - 4 ); + log( 2 ) - 5 ); #ifdef DEBUG printf( "vips_foreign_save_jp2k_build: numresolutions = %d\n", jp2k->parameters.numresolution );