diff --git a/ChangeLog b/ChangeLog index cbc0e4fa..7f1a4ab2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,8 @@ - dzsave supports zip output > 4gb, thanks benjamin - add support for HSV colourspace [Jonas Øgaard] - skip oversized markers in jpeg write +- jpeg exif tags saved as name rather than title +- can now set any jpeg exif tag, not just modify existing tags 7/5/15 started 8.0.3 - dzsave and tif pyr write could fail for some image dimensions, thanks Jonas diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index faaaf89a..29baae8d 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -67,6 +67,8 @@ * 26/2/15 * - close the jpeg read down early for a header read ... this saves an * fd during jpg read, handy for large numbers of input images + * 15/7/15 + * - save exif tags using @name, not @title ... @title is subject to i18n */ /* @@ -492,7 +494,7 @@ attach_exif_entry( ExifEntry *entry, VipsExif *ve ) vips_buf_appendf( &name, "exif-ifd%d-%s", exif_entry_get_ifd( entry ), - exif_tag_get_title( entry->tag ) ); + exif_tag_get_name( entry->tag ) ); vips_exif_to_s( ve->ed, entry, &value ); /* Can't do anything sensible with the error return. diff --git a/libvips/foreign/vips2jpeg.c b/libvips/foreign/vips2jpeg.c index 04beb702..51eb6a30 100644 --- a/libvips/foreign/vips2jpeg.c +++ b/libvips/foreign/vips2jpeg.c @@ -67,6 +67,9 @@ * - support "none" as a resolution unit * 8/7/15 * - omit oversized jpeg markers + * 15/7/15 + * - exif tags use @name, not @title +* - set arbitrary exif tags from metadata */ /* @@ -111,6 +114,7 @@ #include #include #include +#include #include #include @@ -580,49 +584,66 @@ vips_exif_from_s( ExifData *ed, ExifEntry *entry, const char *value ) } } -typedef struct _VipsExif { - VipsImage *image; - ExifData *ed; - ExifContent *content; -} VipsExif; - -static void -vips_exif_update_entry( ExifEntry *entry, VipsExif *ve ) +static void +vips_exif_set_entry( ExifData *ed, ExifEntry *entry, + unsigned long component, void *data ) { - char name[256]; - const char *value; + const char *string = (const char *) data; - vips_snprintf( name, 256, "exif-ifd%d-%s", - exif_entry_get_ifd( entry ), - exif_tag_get_title( entry->tag ) ); - if( vips_image_get_typeof( ve->image, name ) ) { - (void) vips_image_get_string( ve->image, name, &value ); - vips_exif_from_s( ve->ed, entry, value ); - } - else - exif_content_remove_entry( ve->content, entry ); + vips_exif_from_s( ed, entry, string ); } -static void -vips_exif_update_content( ExifContent *content, VipsExif *ve ) +static void * +vips_exif_image_field( VipsImage *image, + const char *field, GValue *value, void *data ) { - ve->content = content; - exif_content_foreach_entry( content, - (ExifContentForeachEntryFunc) vips_exif_update_entry, ve ); + ExifData *ed = (ExifData *) data; + + const char *string; + int ifd; + const char *p; + ExifTag tag; + + if( !vips_isprefix( "exif-ifd", field ) ) + return( NULL ); + + /* value must be a string. + */ + if( vips_image_get_string( image, field, &string ) ) { + vips_warn( "VipsJpeg", _( "bad exif meta \"%s\"" ), field ); + return( NULL ); + } + + p = field + strlen( "exif-ifd" ); + ifd = atoi( p ); + + for( ; isdigit( *p ); p++ ) + ; + if( *p != '-' ) { + vips_warn( "VipsJpeg", _( "bad exif meta \"%s\"" ), field ); + return( NULL ); + } + + if( !(tag = exif_tag_from_name( p + 1 )) ) { + vips_warn( "VipsJpeg", _( "bad exif meta \"%s\"" ), field ); + return( NULL ); + } + + VIPS_DEBUG_MSG( "vips_exif_image_field: %s = %s\n", p + 1, string ); + write_tag( ed, ifd, tag, vips_exif_set_entry, (void *) string ); + + return( NULL ); } static void vips_exif_update( ExifData *ed, VipsImage *image ) { - VipsExif ve; - VIPS_DEBUG_MSG( "vips_exif_update: \n" ); - ve.image = image; - ve.ed = ed; - exif_data_foreach_content( ed, - (ExifDataForeachContentFunc) vips_exif_update_content, &ve ); + vips_image_map( image, + vips_exif_image_field, ed ); } + #endif /*HAVE_EXIF*/ static int