diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 43d9cb4b..980f1635 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -328,6 +328,32 @@ attach_blob( VipsImage *im, const char *field, void *data, int data_length ) return( 0 ); } +/* data is the XMP string ... it'll have something like + * "http://ns.adobe.com/xap/1.0/" at the front, then a null character, then + * the real XMP. + */ +static int +attach_xmp_blob( VipsImage *im, void *data, int data_length ) +{ + char *p = (char *) data; + int i; + + if( !vips_isprefix( "http", p ) ) + return( 0 ); + + /* Search for a null char within the first few characters. 80 + * should be plenty for a basic URL. + */ + for( i = 0; i < 80; i++ ) + if( !p[i] ) + break; + if( p[i] ) + return( 0 ); + + return( attach_blob( im, VIPS_META_XMP_NAME, + p + i + 1, data_length - i - 1 ) ); +} + /* Number of app2 sections we can capture. Each one can be 64k, so 6400k should * be enough for anyone (haha). */ @@ -490,7 +516,7 @@ read_jpeg_header( ReadJpeg *jpeg, VipsImage *out ) if( p->data_length > 4 && vips_isprefix( "http", (char *) p->data ) && - attach_blob( out, VIPS_META_XMP_NAME, + attach_xmp_blob( out, p->data, p->data_length ) ) return( -1 ); diff --git a/libvips/foreign/vips2jpeg.c b/libvips/foreign/vips2jpeg.c index 5b8ee613..9fa45ee3 100644 --- a/libvips/foreign/vips2jpeg.c +++ b/libvips/foreign/vips2jpeg.c @@ -260,7 +260,39 @@ write_blob( Write *write, const char *field, int app ) #endif /*DEBUG*/ jpeg_write_marker( &write->cinfo, app, - data, data_length ); } } + data, data_length ); + } + } + + return( 0 ); +} + +#define XML_URL "http://ns.adobe.com/xap/1.0/" + +static int +write_xmp( Write *write ) +{ + unsigned char *data; + size_t data_length; + char *p; + + if( !vips_image_get_typeof( write->in, VIPS_META_XMP_NAME ) ) + return( 0 ); + if( vips_image_get_blob( write->in, VIPS_META_XMP_NAME, + (void *) &data, &data_length ) ) + return( -1 ); + + /* We need to add the magic XML URL to the start, then a null + * character, then the data. + */ + p = g_malloc( data_length + strlen( XML_URL ) + 1 ); + strcpy( p, XML_URL ); + memcpy( p + strlen( XML_URL ) + 1, data, data_length ); + + jpeg_write_marker( &write->cinfo, JPEG_APP0 + 1, + (unsigned char *) p, data_length + strlen( XML_URL ) + 1 ); + + g_free( p ); return( 0 ); } @@ -593,8 +625,7 @@ write_vips( Write *write, int qfac, const char *profile, */ if( !strip ) { if( write_exif( write ) || - write_blob( write, - VIPS_META_XMP_NAME, JPEG_APP0 + 1 ) || + write_xmp( write ) || write_blob( write, VIPS_META_IPTC_NAME, JPEG_APP0 + 13 ) ) return( -1 );