drop incompatible profiles from save

libpng has started throwing hard errors if the profile does not match
the image -- this can happen all the time with perofiles inherited from
images that have been processed.

Test profiles before save and drop them (with a warning) if they are
incompatible with the image.
This commit is contained in:
John Cupitt 2018-04-01 10:32:48 +01:00
parent 85615a7fbd
commit e686614f2c
5 changed files with 59 additions and 1 deletions

View File

@ -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à

View File

@ -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 <vips/vips.h>
@ -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*/
/**

View File

@ -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 );

View File

@ -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 )

View File

@ -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));