diff --git a/ChangeLog b/ChangeLog index ccef284f..4cb84f82 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ - fix vipsthumbnail with both input cmyk and output rgb profiles specified - vipsthumbnail retries with specified input profile if embedded profile is broken +- add @profile option to pngsave, matching tiff and jpeg 8/9/14 started 7.40.8 - fix configure on rhel6 [Lovell] diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 3e4f3a22..d39b12b3 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2498,6 +2498,7 @@ vips_pngload_buffer( void *buf, size_t len, VipsImage **out, ... ) * * @compression: compression level * @interlace: interlace image + * @profile: ICC profile to embed * * Write a VIPS image to a file as PNG. * @@ -2508,7 +2509,12 @@ vips_pngload_buffer( void *buf, size_t len, VipsImage **out, ... ) * than an interlaced PNG can be up to 7 times slower to write than a * non-interlaced image. * - * If the VIPS header + * Use @profile to give the filename of a profile to be embedded in the PNG. + * This does not affect the pixels which are written, just the way + * they are tagged. You can use the special string "none" to mean + * "don't attach a profile". + * + * If @profile is specified and the VIPS header * contains an ICC profile named VIPS_META_ICC_NAME ("icc-profile-data"), the * profile from the VIPS header will be attached. * @@ -2544,6 +2550,7 @@ vips_pngsave( VipsImage *in, const char *filename, ... ) * * @compression: compression level * @interlace: interlace image + * @profile: ICC profile to embed * * As vips_pngsave(), but save to a memory buffer. * diff --git a/libvips/foreign/pngsave.c b/libvips/foreign/pngsave.c index 50465ac8..27e52fa7 100644 --- a/libvips/foreign/pngsave.c +++ b/libvips/foreign/pngsave.c @@ -58,6 +58,7 @@ typedef struct _VipsForeignSavePng { int compression; gboolean interlace; + char *profile; } VipsForeignSavePng; typedef VipsForeignSaveClass VipsForeignSavePngClass; @@ -115,6 +116,14 @@ vips_foreign_save_png_class_init( VipsForeignSavePngClass *class ) VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET( VipsForeignSavePng, interlace ), FALSE ); + + VIPS_ARG_STRING( class, "profile", 11, + _( "Profile" ), + _( "ICC profile to embed" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignSavePng, profile ), + NULL ); + } static void @@ -146,7 +155,7 @@ vips_foreign_save_png_file_build( VipsObject *object ) return( -1 ); if( vips__png_write( save->ready, png_file->filename, - png->compression, png->interlace ) ) + png->compression, png->interlace, png->profile ) ) return( -1 ); return( 0 ); @@ -204,7 +213,7 @@ vips_foreign_save_png_buffer_build( VipsObject *object ) return( -1 ); if( vips__png_write_buf( save->ready, &obuf, &olen, - png->compression, png->interlace ) ) + png->compression, png->interlace, png->profile ) ) return( -1 ); area = vips_area_new_blob( (VipsCallbackFn) vips_free, obuf, olen ); diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index 66f7e396..14ba7b8c 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -783,7 +783,7 @@ write_png_block( VipsRegion *region, Rect *area, void *a ) /* Write a VIPS image to PNG. */ static int -write_vips( Write *write, int compress, int interlace ) +write_vips( Write *write, int compress, int interlace, const char *profile ) { VipsImage *in = write->in; @@ -854,21 +854,42 @@ write_vips( Write *write, int compress, int interlace ) /* Set ICC Profile. */ - if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) { - void *profile; - size_t profile_length; + if( profile ) { + if( strcmp( profile, "none" ) != 0 ) { + void *data; + unsigned int length; + + if( !(data = + vips__file_read_name( profile, VIPS_ICC_DIR, + &length )) ) + return( -1 ); + +#ifdef DEBUG + printf( "write_vips: " + "attaching %d bytes of ICC profile\n", + length ); +#endif /*DEBUG*/ + + png_set_iCCP( write->pPng, write->pInfo, "icc", + PNG_COMPRESSION_TYPE_BASE, + data, length ); + } + } + else 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, - &profile, &profile_length ) ) + &data, &length ) ) return( -1 ); #ifdef DEBUG printf( "write_vips: attaching %zd bytes of ICC profile\n", - profile_length ); + length ); #endif /*DEBUG*/ png_set_iCCP( write->pPng, write->pInfo, "icc", - PNG_COMPRESSION_TYPE_BASE, profile, profile_length ); + PNG_COMPRESSION_TYPE_BASE, data, length ); } png_write_info( write->pPng, write->pInfo ); @@ -902,7 +923,7 @@ write_vips( Write *write, int compress, int interlace ) int vips__png_write( VipsImage *in, const char *filename, - int compress, int interlace ) + int compress, int interlace, const char *profile ) { Write *write; @@ -921,7 +942,7 @@ vips__png_write( VipsImage *in, const char *filename, /* Convert it! */ - if( write_vips( write, compress, interlace ) ) { + if( write_vips( write, compress, interlace, profile ) ) { vips_error( "vips2png", _( "unable to write \"%s\"" ), filename ); @@ -1007,7 +1028,8 @@ user_write_data( png_structp png_ptr, png_bytep data, png_size_t length ) int vips__png_write_buf( VipsImage *in, - void **obuf, size_t *olen, int compression, int interlace ) + void **obuf, size_t *olen, int compression, int interlace, + const char *profile ) { WriteBuf *wbuf; Write *write; @@ -1023,7 +1045,7 @@ vips__png_write_buf( VipsImage *in, /* Convert it! */ - if( write_vips( write, compression, interlace ) ) { + if( write_vips( write, compression, interlace, profile ) ) { write_buf_free( wbuf ); vips_error( "vips2png", "%s", _( "unable to write to buffer" ) ); diff --git a/libvips/foreign/vipspng.h b/libvips/foreign/vipspng.h index 0bcd6467..feb1eddd 100644 --- a/libvips/foreign/vipspng.h +++ b/libvips/foreign/vipspng.h @@ -46,9 +46,10 @@ int vips__png_read_buffer( char *buffer, size_t length, VipsImage *out, int vips__png_header_buffer( char *buffer, size_t length, VipsImage *out ); int vips__png_write( VipsImage *in, const char *filename, - int compress, int interlace ); + int compress, int interlace, const char *profile ); int vips__png_write_buf( VipsImage *in, - void **obuf, size_t *olen, int compression, int interlace ); + void **obuf, size_t *olen, int compression, int interlace, + const char *profile ); #ifdef __cplusplus }