add @profile option to pngsave

tiff and jpeg save both have a @profile option, this patch adds one to png as
well, see

https://github.com/jcupitt/libvips/issues/180
This commit is contained in:
John Cupitt 2014-09-18 09:38:12 +01:00
parent e4461ae1f9
commit 14a8c5ad47
5 changed files with 56 additions and 16 deletions

View File

@ -5,6 +5,7 @@
- fix vipsthumbnail with both input cmyk and output rgb profiles specified - fix vipsthumbnail with both input cmyk and output rgb profiles specified
- vipsthumbnail retries with specified input profile if embedded profile is - vipsthumbnail retries with specified input profile if embedded profile is
broken broken
- add @profile option to pngsave, matching tiff and jpeg
8/9/14 started 7.40.8 8/9/14 started 7.40.8
- fix configure on rhel6 [Lovell] - fix configure on rhel6 [Lovell]

View File

@ -2498,6 +2498,7 @@ vips_pngload_buffer( void *buf, size_t len, VipsImage **out, ... )
* *
* @compression: compression level * @compression: compression level
* @interlace: interlace image * @interlace: interlace image
* @profile: ICC profile to embed
* *
* Write a VIPS image to a file as PNG. * 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 * than an interlaced PNG can be up to 7 times slower to write than a
* non-interlaced image. * 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 * contains an ICC profile named VIPS_META_ICC_NAME ("icc-profile-data"), the
* profile from the VIPS header will be attached. * profile from the VIPS header will be attached.
* *
@ -2544,6 +2550,7 @@ vips_pngsave( VipsImage *in, const char *filename, ... )
* *
* @compression: compression level * @compression: compression level
* @interlace: interlace image * @interlace: interlace image
* @profile: ICC profile to embed
* *
* As vips_pngsave(), but save to a memory buffer. * As vips_pngsave(), but save to a memory buffer.
* *

View File

@ -58,6 +58,7 @@ typedef struct _VipsForeignSavePng {
int compression; int compression;
gboolean interlace; gboolean interlace;
char *profile;
} VipsForeignSavePng; } VipsForeignSavePng;
typedef VipsForeignSaveClass VipsForeignSavePngClass; typedef VipsForeignSaveClass VipsForeignSavePngClass;
@ -115,6 +116,14 @@ vips_foreign_save_png_class_init( VipsForeignSavePngClass *class )
VIPS_ARGUMENT_OPTIONAL_INPUT, VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSavePng, interlace ), G_STRUCT_OFFSET( VipsForeignSavePng, interlace ),
FALSE ); FALSE );
VIPS_ARG_STRING( class, "profile", 11,
_( "Profile" ),
_( "ICC profile to embed" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSavePng, profile ),
NULL );
} }
static void static void
@ -146,7 +155,7 @@ vips_foreign_save_png_file_build( VipsObject *object )
return( -1 ); return( -1 );
if( vips__png_write( save->ready, png_file->filename, if( vips__png_write( save->ready, png_file->filename,
png->compression, png->interlace ) ) png->compression, png->interlace, png->profile ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );
@ -204,7 +213,7 @@ vips_foreign_save_png_buffer_build( VipsObject *object )
return( -1 ); return( -1 );
if( vips__png_write_buf( save->ready, &obuf, &olen, if( vips__png_write_buf( save->ready, &obuf, &olen,
png->compression, png->interlace ) ) png->compression, png->interlace, png->profile ) )
return( -1 ); return( -1 );
area = vips_area_new_blob( (VipsCallbackFn) vips_free, obuf, olen ); area = vips_area_new_blob( (VipsCallbackFn) vips_free, obuf, olen );

View File

@ -783,7 +783,7 @@ write_png_block( VipsRegion *region, Rect *area, void *a )
/* Write a VIPS image to PNG. /* Write a VIPS image to PNG.
*/ */
static int 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; VipsImage *in = write->in;
@ -854,21 +854,42 @@ write_vips( Write *write, int compress, int interlace )
/* Set ICC Profile. /* Set ICC Profile.
*/ */
if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) { if( profile ) {
void *profile; if( strcmp( profile, "none" ) != 0 ) {
size_t profile_length; 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, if( vips_image_get_blob( in, VIPS_META_ICC_NAME,
&profile, &profile_length ) ) &data, &length ) )
return( -1 ); return( -1 );
#ifdef DEBUG #ifdef DEBUG
printf( "write_vips: attaching %zd bytes of ICC profile\n", printf( "write_vips: attaching %zd bytes of ICC profile\n",
profile_length ); length );
#endif /*DEBUG*/ #endif /*DEBUG*/
png_set_iCCP( write->pPng, write->pInfo, "icc", 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 ); png_write_info( write->pPng, write->pInfo );
@ -902,7 +923,7 @@ write_vips( Write *write, int compress, int interlace )
int int
vips__png_write( VipsImage *in, const char *filename, vips__png_write( VipsImage *in, const char *filename,
int compress, int interlace ) int compress, int interlace, const char *profile )
{ {
Write *write; Write *write;
@ -921,7 +942,7 @@ vips__png_write( VipsImage *in, const char *filename,
/* Convert it! /* Convert it!
*/ */
if( write_vips( write, compress, interlace ) ) { if( write_vips( write, compress, interlace, profile ) ) {
vips_error( "vips2png", vips_error( "vips2png",
_( "unable to write \"%s\"" ), filename ); _( "unable to write \"%s\"" ), filename );
@ -1007,7 +1028,8 @@ user_write_data( png_structp png_ptr, png_bytep data, png_size_t length )
int int
vips__png_write_buf( VipsImage *in, 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; WriteBuf *wbuf;
Write *write; Write *write;
@ -1023,7 +1045,7 @@ vips__png_write_buf( VipsImage *in,
/* Convert it! /* Convert it!
*/ */
if( write_vips( write, compression, interlace ) ) { if( write_vips( write, compression, interlace, profile ) ) {
write_buf_free( wbuf ); write_buf_free( wbuf );
vips_error( "vips2png", vips_error( "vips2png",
"%s", _( "unable to write to buffer" ) ); "%s", _( "unable to write to buffer" ) );

View File

@ -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_header_buffer( char *buffer, size_t length, VipsImage *out );
int vips__png_write( VipsImage *in, const char *filename, 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, 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 #ifdef __cplusplus
} }