diff --git a/ChangeLog b/ChangeLog index 2f015aed..ff184274 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,7 @@ - add vips_rotate() ... a convenience method for vips_similarity() - svgload was missing is_a [lovell] - better header sniffing for small files +- drop incompatible ICC profiles before save 12/3/18 started 8.6.4 - better fitting of fonts with overhanging edges, thanks AdriĆ  diff --git a/libvips/colour/icc_transform.c b/libvips/colour/icc_transform.c index 7b9d0d53..67053214 100644 --- a/libvips/colour/icc_transform.c +++ b/libvips/colour/icc_transform.c @@ -1226,6 +1226,36 @@ vips_icc_ac2rc( VipsImage *in, VipsImage **out, const char *profile_filename ) return( 0 ); } +/* TRUE if a profile is compatible with an image. + */ +gboolean +vips_icc_is_compatible_profile( VipsImage *image, + void *data, size_t data_length ) +{ + cmsHPROFILE profile; + + if( !(profile = cmsOpenProfileFromMem( data, data_length )) ) { + g_warning( "%s", _( "corrupt profile" ) ); + return( FALSE ); + } + + if( vips_image_expected_bands( image ) != + vips_icc_profile_needs_bands( profile ) ) { + VIPS_FREEF( cmsCloseProfile, profile ); + g_warning( "%s", + _( "profile incompatible with image" ) ); + return( FALSE ); + } + if( vips_image_expected_sig( image ) != cmsGetColorSpace( profile ) ) { + VIPS_FREEF( cmsCloseProfile, profile ); + g_warning( "%s", + _( "profile colourspace differs from image" ) ); + return( FALSE ); + } + + return( TRUE ); +} + #else /*!HAVE_LCMS2*/ #include @@ -1245,6 +1275,13 @@ vips_icc_ac2rc( VipsImage *in, VipsImage **out, const char *profile_filename ) return( -1 ); } +gboolean +vips_icc_is_compatible_profile( VipsImage *image, + void *data, size_t data_length ) +{ + return( TRUE ); +} + #endif /*HAVE_LCMS*/ /** diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 61c87e03..f32302b9 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -22,6 +22,8 @@ * - META_SEQ support moved here * 5/3/18 * - block _start if one start fails, see #893 + * 1/4/18 + * - drop incompatible ICC profiles before save */ /* @@ -1504,6 +1506,21 @@ vips__foreign_convert_saveable( VipsImage *in, VipsImage **ready, in = out; } + /* Some format libraries, like libpng, will throw a hard error if the + * profile is inappropriate for this image type. With profiles inherited + * from a source image, this can happen all the time, so we + * want to just drop the profile in this case. + */ + if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) { + void *data; + size_t length; + + if( !vips_image_get_blob( in, VIPS_META_ICC_NAME, + &data, &length ) && + !vips_icc_is_compatible_profile( in, data, length ) ) + vips_image_remove( in, VIPS_META_ICC_NAME ); + } + *ready = in; return( 0 ); diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index b645da3a..a7aaf963 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -992,7 +992,8 @@ write_vips( Write *write, /* If we're an intel byte order CPU and this is a 16bit image, we need * to swap bytes. */ - if( bit_depth > 8 && !vips_amiMSBfirst() ) + if( bit_depth > 8 && + !vips_amiMSBfirst() ) png_set_swap( write->pPng ); if( interlace ) diff --git a/libvips/include/vips/colour.h b/libvips/include/vips/colour.h index 77404b9c..7978d325 100644 --- a/libvips/include/vips/colour.h +++ b/libvips/include/vips/colour.h @@ -177,6 +177,8 @@ int vips_icc_export( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); int vips_icc_ac2rc( VipsImage *in, VipsImage **out, const char *profile_filename ); +gboolean vips_icc_is_compatible_profile( VipsImage *image, + void *data, size_t data_length ); int vips_dE76( VipsImage *left, VipsImage *right, VipsImage **out, ... ) __attribute__((sentinel));