Skip to content

Commit

Permalink
preserve jpeg ipct data
Browse files Browse the repository at this point in the history
now copies over ipct data from app13, thanks Gary
  • Loading branch information
jcupitt committed Nov 21, 2012
1 parent 65b4056 commit c3ef2be
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 12 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 0 additions & 2 deletions TODO
Original file line number Diff line number Diff line change
@@ -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
Expand Down
48 changes: 44 additions & 4 deletions libvips/foreign/jpeg2vips.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/

/*
Expand Down Expand Up @@ -79,9 +82,9 @@
*/

/*
*/
#define DEBUG_VERBOSE
#define DEBUG
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
Expand Down Expand Up @@ -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).
*/
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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!
*/
Expand Down
34 changes: 28 additions & 6 deletions libvips/foreign/vips2jpeg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/

/*
Expand Down Expand Up @@ -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 ) )
Expand All @@ -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.
*/

Expand Down Expand Up @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions libvips/include/vips/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
*
Expand Down

0 comments on commit c3ef2be

Please sign in to comment.