From b15f07e3acfdff3191505bda2ab279c95241f945 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 18 Oct 2011 14:29:35 +0100 Subject: [PATCH] update exif orientation on jpeg write test the value of the 'exif-Orientation' tag and update exif on jpeg write --- ChangeLog | 1 + libvips/format/im_jpeg2vips.c | 3 +- libvips/format/im_vips2jpeg.c | 84 +++++++++++++++++++++++++++++++++-- libvips/iofuncs/header.c | 6 +-- 4 files changed, 86 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 031685e5..8abeeb34 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 12/10/11 started 7.26.6 - NOCACHE was not being set correctly on OS X causing performance problems with large files +- update Orientation exif tag on jpeg write 12/10/11 started 7.26.5 - jpeg read/write copies over XMP data diff --git a/libvips/format/im_jpeg2vips.c b/libvips/format/im_jpeg2vips.c index 3da27c66..3f572bbb 100644 --- a/libvips/format/im_jpeg2vips.c +++ b/libvips/format/im_jpeg2vips.c @@ -271,9 +271,10 @@ attach_exif_entry( ExifEntry *entry, IMAGE *im ) vips_buf_init_static( &value, value_text, 256 ); vips_buf_appendf( &name, "exif-%s", exif_tag_get_title( entry->tag ) ); - vips_buf_appendf( &value, "%s (%s, %d bytes)", + vips_buf_appendf( &value, "%s (%s, %lu componets, %d bytes)", exif_entry_get_value( entry, exif_value, 256 ), exif_format_get_name( entry->format ), + entry->components, entry->size ); /* Can't do anything sensible with the error return. diff --git a/libvips/format/im_vips2jpeg.c b/libvips/format/im_vips2jpeg.c index abf8eb9a..fac2e763 100644 --- a/libvips/format/im_vips2jpeg.c +++ b/libvips/format/im_vips2jpeg.c @@ -42,6 +42,8 @@ * - oop CMYK write was not inverting, thanks Ole * 12/10/2011 * - write XMP data + * 18/10/2011 + * - update Orientation as well */ /* @@ -72,8 +74,8 @@ /* #define DEBUG_VERBOSE -#define DEBUG */ +#define DEBUG #ifdef HAVE_CONFIG_H #include @@ -314,10 +316,16 @@ write_tag( ExifData *ed, ExifTag tag, ExifFormat f, write_fn fn, void *data ) ExifEntry *entry; entry = exif_entry_new(); + + /* tag must be set before calling exif_content_add_entry. + */ + entry->tag = tag; + exif_content_add_entry( ed->ifd[0], entry ); exif_entry_initialize( entry, tag ); - fn( entry, bo, data ); exif_entry_unref( entry ); + + fn( entry, bo, data ); } return( 0 ); @@ -356,6 +364,62 @@ set_exif_resolution( ExifData *ed, IMAGE *im ) return( 0 ); } + +static void * +update_orientation_cb( VipsImage *in, const char *name, GValue *value, void *a ) +{ + /* Sadly these strings are subject to i18n by libexif. We should + * attach EXIF data as binary and leave interpretaion to the UI argh. + */ + static const char *orientations[] = { + "", + "Top-left", "Top-right", "Bottom-right", + "Bottom-left", "Left-top", "Right-top", + "Right-bottom", "Left-bottom", + NULL + }; + + ExifData *ed = (ExifData *) a; + + int i; + ExifShort orientation; + + if( vips_isprefix( "exif-Orientation", name ) ) { + const char *string; + + if( !(string = vips_ref_string_get( value )) ) { + vips_warn( "im_jpeg2vips", + "%s", _( "exif-Orientation is not a string" ) ); + return( NULL ); + } + + orientation = 0; + for( i = 0; orientations[i]; i++ ) + if( strlen( orientations[i] ) > 0 && + vips_isprefix( orientations[i], string ) ) { + orientation = i; + break; + } + if( orientation == 0 ) { + vips_warn( "im_jpeg2vips", + "%s", _( "unknown JPEG orientation" ) ); + return( NULL ); + } + + if( write_tag( ed, EXIF_TAG_ORIENTATION, EXIF_FORMAT_SHORT, + write_short, &orientation ) ) { + vips_warn( "im_jpeg2vips", + "%s", _( "error setting JPEG orientation" ) ); + return( NULL ); + } + +#ifdef DEBUG + printf( "im_vips2jpeg: updated orientation\n" ); +#endif /*DEBUG*/ + } + + return( NULL ); +} #endif /*HAVE_EXIF*/ static int @@ -378,9 +442,23 @@ write_exif( Write *write ) if( !(ed = exif_data_new_from_data( data, data_length )) ) return( -1 ); } - else + else { ed = exif_data_new(); + exif_data_set_option( ed, + EXIF_DATA_OPTION_FOLLOW_SPECIFICATION ); + exif_data_set_data_type( ed, EXIF_DATA_TYPE_COMPRESSED ); + exif_data_set_byte_order( ed, EXIF_BYTE_ORDER_INTEL ); + + /* Create the mandatory EXIF fields with default data. + */ + exif_data_fix( ed ); + } + + /* Update EXIF orientation from VIPS. + */ + (void) vips_image_map( write->in, update_orientation_cb, ed ); + /* Update EXIF resolution from VIPS. */ if( set_exif_resolution( ed, write->in ) ) { diff --git a/libvips/iofuncs/header.c b/libvips/iofuncs/header.c index e9aacdf0..e8ede8b3 100644 --- a/libvips/iofuncs/header.c +++ b/libvips/iofuncs/header.c @@ -112,7 +112,7 @@ * Various convenience functions (eg. vips_image_set_int()) let you easily * attach * simple types like - * numbers, strings and memory blocks to images. Use vips_header_map() to loop + * numbers, strings and memory blocks to images. Use vips_image_map() to loop * over an image's fields, including all metadata. * * Items of metadata are identified by strings. Some strings are reserved, for @@ -479,8 +479,6 @@ vips_image_init_fields( VipsImage *image, static void * meta_cp_field( VipsMeta *meta, VipsImage *dst ) { - VipsMeta *meta_copy; - #ifdef DEBUG { char *str_value; @@ -494,7 +492,7 @@ meta_cp_field( VipsMeta *meta, VipsImage *dst ) /* No way to return error here, sadly. */ - meta_copy = meta_new( dst, meta->field, &meta->value ); + (void) meta_new( dst, meta->field, &meta->value ); #ifdef DEBUG meta_sanity( dst );