diff --git a/ChangeLog b/ChangeLog index 53c51641..25d74457 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,7 @@ - better --help output for vips driver prog - vipsthumbnail -o allows absolute file names - much better exif handling for jpg images (thanks Gary) +- preserve jpeg app13 (photoshop ipct) 14/11/12 started 7.30.6 - capture tiff warnings earlier diff --git a/TODO b/TODO index 30feeac5..665ed0c5 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,3 @@ -- look into preserving IPTC data - - check libtool version number, should be binary-compat with 7.30 - quadratic doesn't work for order 3 diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 071dcdee..609604eb 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -50,6 +50,9 @@ * 16/11/12 * - tag exif fields with their ifd * - attach rationals as a/b, don't convert to double + * 21/11/12 + * - don't insist exif must have data + * - attach IPCT data (app13), thanks Gary */ /* @@ -79,9 +82,9 @@ */ /* - */ #define DEBUG_VERBOSE #define DEBUG + */ #ifdef HAVE_CONFIG_H #include @@ -666,6 +669,34 @@ read_xmp( VipsImage *im, void *data, size_t data_length ) return( 0 ); } +static int +read_ipct( VipsImage *im, void *data, size_t data_length ) +{ + char *data_copy; + + /* Only use the first one. + */ + if( vips_image_get_typeof( im, VIPS_META_IPCT_NAME ) ) { +#ifdef DEBUG + printf( "read_ipct: second IPCT block, ignoring\n" ); +#endif /*DEBUG*/ + + return( 0 ); + } + +#ifdef DEBUG + printf( "read_ipct: attaching %zd bytes of IPCT\n", data_length ); +#endif /*DEBUG*/ + + if( !(data_copy = vips_malloc( NULL, data_length )) ) + return( -1 ); + memcpy( data_copy, data, data_length ); + vips_image_set_blob( im, VIPS_META_IPCT_NAME, + (VipsCallbackFn) vips_free, data_copy, data_length ); + + return( 0 ); +} + /* Number of app2 sections we can capture. Each one can be 64k, so 6400k should * be enough for anyone (haha). */ @@ -780,8 +811,6 @@ read_jpeg_header( ReadJpeg *jpeg, VipsImage *out ) for( p = cinfo->marker_list; p; p = p->next ) { #ifdef DEBUG { - int i; - printf( "read_jpeg_header: seen %d bytes of APP%d\n", p->data_length, p->marker - JPEG_APP0 ); @@ -828,6 +857,15 @@ read_jpeg_header( ReadJpeg *jpeg, VipsImage *out ) } break; + case JPEG_APP0 + 13: + /* Possible IPCT data block. + */ + if( p->data_length > 5 && + vips_isprefix( "Photo", (char *) p->data ) && + read_ipct( out, p->data, p->data_length ) ) + return( -1 ); + break; + default: break; } @@ -987,10 +1025,12 @@ vips__jpeg_read_file( const char *filename, VipsImage *out, return( -1 ); } - /* Need to read in APP1 (EXIF metadata) and APP2 (ICC profile). + /* Need to read in APP1 (EXIF metadata), APP2 (ICC profile), APP13 + * (photoshop IPCT). */ jpeg_save_markers( &jpeg->cinfo, JPEG_APP0 + 1, 0xffff ); jpeg_save_markers( &jpeg->cinfo, JPEG_APP0 + 2, 0xffff ); + jpeg_save_markers( &jpeg->cinfo, JPEG_APP0 + 13, 0xffff ); /* Convert! */ diff --git a/libvips/foreign/vips2jpeg.c b/libvips/foreign/vips2jpeg.c index 54fbb519..f8576972 100644 --- a/libvips/foreign/vips2jpeg.c +++ b/libvips/foreign/vips2jpeg.c @@ -54,6 +54,8 @@ * - read ifds from exif fields * - optionally parse rationals as a/b * - update exif image dimensions + * 21/11/12 + * - attach IPCT data (app13), thanks Gary */ /* @@ -705,8 +707,6 @@ write_xmp( Write *write ) unsigned char *data; size_t data_length; - /* No libexif ... just copy the embedded EXIF over. - */ if( vips_image_get_typeof( write->in, VIPS_META_XMP_NAME ) ) { if( vips_image_get_blob( write->in, VIPS_META_XMP_NAME, (void *) &data, &data_length ) ) @@ -724,6 +724,29 @@ write_xmp( Write *write ) return( 0 ); } +static int +write_ipct( Write *write ) +{ + unsigned char *data; + size_t data_length; + + if( vips_image_get_typeof( write->in, VIPS_META_IPCT_NAME ) ) { + if( vips_image_get_blob( write->in, VIPS_META_IPCT_NAME, + (void *) &data, &data_length ) ) + return( -1 ); + +#ifdef DEBUG + printf( "write_ipct: attaching %zd bytes of IPCT\n", + data_length ); +#endif /*DEBUG*/ + + jpeg_write_marker( &write->cinfo, JPEG_APP0 + 13, + data, data_length ); + } + + return( 0 ); +} + /* ICC writer from lcms, slight tweaks. */ @@ -919,10 +942,9 @@ write_vips( Write *write, int qfac, const char *profile ) /* Write any APP markers we need. */ - if( write_exif( write ) ) - return( -1 ); - - if( write_xmp( write ) ) + if( write_exif( write ) || + write_xmp( write ) || + write_ipct( write ) ) return( -1 ); /* A profile supplied as an argument overrides an embedded profile. diff --git a/libvips/include/vips/header.h b/libvips/include/vips/header.h index c658c069..53d9bb81 100644 --- a/libvips/include/vips/header.h +++ b/libvips/include/vips/header.h @@ -51,6 +51,13 @@ extern "C" { */ #define VIPS_META_XMP_NAME "xmp-data" +/** + * VIPS_META_IPCT_NAME: + * + * The name that JPEG read and write operations use for the image's IPCT data. + */ +#define VIPS_META_IPCT_NAME "ipct-data" + /** * VIPS_META_ICC_NAME: *