diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 79d120a2..b1d82165 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -76,6 +76,9 @@ * - switch to new orientation tag * 11/7/16 * - new --fail handling + * 07/09/16 + * - Don't use the exif resolution if x_resolution / y_resolution / + * resolution_unit is missing */ /* @@ -347,6 +350,19 @@ show_values( ExifData *data ) #endif /*HAVE_EXIF*/ #ifdef HAVE_EXIF +static ExifData* +vips_exif_load_data_without_fix(const unsigned char* data, unsigned int size) +{ + ExifData *edata = exif_data_new(); + + if ( !edata ) + return NULL; + + exif_data_unset_option(edata, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION); + exif_data_load_data (edata, data, size); + return edata; +} + static int vips_exif_get_int( ExifData *ed, ExifEntry *entry, unsigned long component, int *out ) @@ -526,6 +542,34 @@ get_entry_double( ExifData *ed, int ifd, ExifTag tag, double *out ) return( vips_exif_get_double( ed, entry, 0, out ) ); } +static void +set_entry_double( ExifData *ed, int ifd, ExifTag tag, double in) +{ + ExifEntry *entry; + + if( (entry = exif_content_get_entry( ed->ifd[ifd], tag )) ) { + /* Let's remove the current value */ + exif_content_remove_entry( ed->ifd[ifd], entry ); + entry = NULL; + } + + if ( !( entry = exif_entry_new() ) ) + return; + + entry->tag = tag; + exif_content_add_entry( ed->ifd[ifd], entry ); + + exif_entry_initialize( entry, tag ); + + /* This is a simple yet sufficient implementation */ + ExifRational value; + value.numerator = in * 1000; + value.denominator = 1000; + + if ( entry->data ) + exif_set_rational( entry->data, exif_data_get_byte_order( ed ), value ); +} + static int get_entry_int( ExifData *ed, int ifd, ExifTag tag, int *out ) { @@ -538,7 +582,7 @@ get_entry_int( ExifData *ed, int ifd, ExifTag tag, int *out ) return( vips_exif_get_int( ed, entry, 0, out ) ); } -static void +static int res_from_exif( VipsImage *im, ExifData *ed ) { double xres, yres; @@ -552,7 +596,7 @@ res_from_exif( VipsImage *im, ExifData *ed ) get_entry_int( ed, 0, EXIF_TAG_RESOLUTION_UNIT, &unit ) ) { vips_warn( "VipsJpeg", "%s", _( "error reading resolution" ) ); - return; + return( -1 ); } #ifdef DEBUG @@ -589,7 +633,7 @@ res_from_exif( VipsImage *im, ExifData *ed ) default: vips_warn( "VipsJpeg", "%s", _( "unknown EXIF resolution unit" ) ); - return; + return( -1 ); } #ifdef DEBUG @@ -599,6 +643,8 @@ res_from_exif( VipsImage *im, ExifData *ed ) im->Xres = xres; im->Yres = yres; + + return( 0 ); } static int @@ -626,7 +672,7 @@ parse_exif( VipsImage *im, void *data, int data_length ) ExifData *ed; VipsExif ve; - if( !(ed = exif_data_new_from_data( data, data_length )) ) + if( !(ed = vips_exif_load_data_without_fix( data, data_length )) ) return( -1 ); #ifdef DEBUG_VERBOSE @@ -645,16 +691,23 @@ parse_exif( VipsImage *im, void *data, int data_length ) */ ve.image = im; ve.ed = ed; - exif_data_foreach_content( ed, - (ExifDataForeachContentFunc) attach_exif_content, &ve ); /* Look for resolution fields and use them to set the VIPS * xres/yres fields. + * If the fields are missing, write the one from the jfif. */ - res_from_exif( im, ed ); + if ( res_from_exif( im, ed ) ) { + set_entry_double( ed, 0, EXIF_TAG_X_RESOLUTION, im->Xres ); + set_entry_double( ed, 0, EXIF_TAG_Y_RESOLUTION, im->Yres ); + } + + /* Let's make sure the fields are valid. */ + exif_data_fix( ed ); + + exif_data_foreach_content( ed, + (ExifDataForeachContentFunc) attach_exif_content, &ve ); attach_thumbnail( im, ed ); - exif_data_free( ed ); } #endif /*HAVE_EXIF*/