From 53e86e71f4b483be485b4455587d7bd5125b9627 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 12 Nov 2013 17:18:41 +0000 Subject: [PATCH] fix up XYZ PCS and vipsthumbnail fix import and export scaling, get vipsthumbnail to use it in --linear mode --- ChangeLog | 1 + TODO | 8 -------- libvips/colour/icc_transform.c | 26 ++++++++++++++++++++------ tools/vipsthumbnail.c | 7 +++---- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 872a24b8..5c31aadc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -19,6 +19,7 @@ - rename vips_gammacorrect() as vips_gamma(), now takes 1 / exp - vips_gamma() works for any format - add --linear mode to vipsthumbnail +- support XYZ as a PCS for vips_icc_import() and vips_icc_export() 18/10/13 started 7.36.3 - fix compiler warnings in ubuntu 13.10 diff --git a/TODO b/TODO index 3df16873..a4fec7fd 100644 --- a/TODO +++ b/TODO @@ -2,14 +2,6 @@ - vipsthumbnail can use vips_conv() now and get rid of the INTMASK -- vips_icc_import() could offer XYZ as well as LAB? it'd save two conversions - in vipsthumbnail - - vips_icc_export() would need to be able to accept both types as well - - at the moment, icc_export() assumes LAB, it needs a vips_colourspace() on - the input to do an automatic transform for you see vips_dE00() etc. - - jpegsave needs a --strip option - jpegsave needs chroma subsampling controls, see: diff --git a/libvips/colour/icc_transform.c b/libvips/colour/icc_transform.c index 7ef62b5e..8c14cfab 100644 --- a/libvips/colour/icc_transform.c +++ b/libvips/colour/icc_transform.c @@ -24,6 +24,8 @@ * - redo as a class * 14/5/13 * - import and export would segv on very wide images + * 12/11/13 + * - support XYZ as an alternative PCS */ /* @@ -512,15 +514,19 @@ decode_lab( guint16 *fixed, float *lab, int n ) } } +#define X_FAC (VIPS_D50_X0 * 32768 / (VIPS_D65_X0 * 100)) +#define Y_FAC (VIPS_D50_Y0 * 32768 / (VIPS_D65_Y0 * 100)) +#define Z_FAC (VIPS_D50_Z0 * 32768 / (VIPS_D65_Z0 * 100)) + static void decode_xyz( guint16 *fixed, float *xyz, int n ) { int i; for( i = 0; i < n; i++ ) { - xyz[0] = (double) fixed[0] / 652.800; - xyz[1] = (double) fixed[1] / 652.800; - xyz[2] = (double) fixed[2] / 652.800; + xyz[0] = (double) fixed[0] / X_FAC; + xyz[1] = (double) fixed[1] / Y_FAC; + xyz[2] = (double) fixed[2] / Z_FAC; xyz += 3; fixed += 3; @@ -623,6 +629,14 @@ vips_icc_export_build( VipsObject *object ) VipsIcc *icc = (VipsIcc *) object; VipsIccExport *export = (VipsIccExport *) object; + /* If icc->pcs hasn't been set and this image is tagged as XYZ, swap + * to XYZ pcs. This will save a XYZ->LAB conversion when we chain up. + */ + if( !vips_object_argument_isset( object, "pcs" ) && + code->in && + code->in->Type == VIPS_INTERPRETATION_XYZ ) + icc->pcs = VIPS_INTERPRETATION_XYZ; + if( icc->pcs == VIPS_PCS_LAB ) { #ifdef HAVE_LCMS2 cmsCIExyY white; @@ -741,9 +755,9 @@ encode_xyz( float *xyz, guint16 *fixed, int n ) if( Z > MAX_ENCODEABLE_XYZ ) Z = MAX_ENCODEABLE_XYZ; - fixed[0] = X * 652.800 + 0.5; - fixed[1] = Y * 652.800 + 0.5; - fixed[2] = Z * 652.800 + 0.5; + fixed[0] = X * X_FAC + 0.5; + fixed[1] = Y * Y_FAC + 0.5; + fixed[2] = Z * Z_FAC + 0.5; xyz += 3; fixed += 3; diff --git a/tools/vipsthumbnail.c b/tools/vipsthumbnail.c index 05920fe6..a2f75b60 100644 --- a/tools/vipsthumbnail.c +++ b/tools/vipsthumbnail.c @@ -349,6 +349,7 @@ thumbnail_shrink( VipsObject *thumbnail, VipsImage *in, if( vips_icc_import( in, &t[1], "input_profile", import_profile, "embedded", TRUE, + "pcs", VIPS_PCS_XYZ, NULL ) ) return( NULL ); @@ -419,10 +420,8 @@ thumbnail_shrink( VipsObject *thumbnail, VipsImage *in, vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) { vips_info( "vipsthumbnail", "exporting to device space with a profile" ); - if( vips_colourspace( in, &t[6], - VIPS_INTERPRETATION_LAB, NULL ) || - vips_icc_export( t[6], &t[7], - "output_profile", export_profile, + if( vips_icc_export( in, &t[7], + "output_profile", export_profile, NULL ) ) return( NULL ); in = t[7];