diff --git a/.travis.yml b/.travis.yml index 27aab72d..bccafb7d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: cpp before_script: - ./autogen.sh - - ./configure --disable-dependency-tracking --with-jpeg-includes=$JPEG/include --with-jpeg-libraries=$JPEG/lib diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index 58fa9b46..9c662d69 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -1818,15 +1818,21 @@ vips_foreign_save_dz_build( VipsObject *object ) if( (p = (char *) vips__find_rightmost_brackets( dz->basename )) ) *p = '\0'; if( (p = strrchr( dz->basename, '.' )) ) { - *p = '\0'; - /* If we're writing to thing.zip or thing.szi, default to zip * container. */ - if( !vips_object_argument_isset( object, "container" ) ) + if( !vips_object_argument_isset( object, "container" ) ) if( strcasecmp( p + 1, "zip" ) == 0 || - strcasecmp( p + 1, "szi" ) == 0 ) + strcasecmp( p + 1, "szi" ) == 0 ) dz->container = VIPS_FOREIGN_DZ_CONTAINER_ZIP; + + /* Always remove .szi, .zip, .dz. We don't remove all suffixes + * since we might be writing to a dirname with a dot in. + */ + if( strcasecmp( p + 1, "zip" ) == 0 || + strcasecmp( p + 1, "szi" ) == 0 || + strcasecmp( p + 1, "dz" ) == 0 ) + *p = '\0'; } } @@ -2053,7 +2059,7 @@ static int bandfmt_dz[10] = { UC, C, US, S, UI, I, F, F, D, D }; -const char *dz_suffs[] = { ".dz", NULL }; +static const char *dz_suffs[] = { ".dz", NULL }; static void vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class ) diff --git a/libvips/foreign/jpeg.h b/libvips/foreign/jpeg.h index ac7e6edc..8c1e018a 100644 --- a/libvips/foreign/jpeg.h +++ b/libvips/foreign/jpeg.h @@ -77,6 +77,8 @@ typedef struct { void vips__new_output_message( j_common_ptr cinfo ); void vips__new_error_exit( j_common_ptr cinfo ); +int vips__set_exif_resolution( ExifData *ed, VipsImage *im ); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 79d120a2..2a4eba1b 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,27 @@ show_values( ExifData *data ) #endif /*HAVE_EXIF*/ #ifdef HAVE_EXIF +/* Like exif_data_new_from_data(), but don't default missing fields. + * + * If we do exif_data_new_from_data(), then missing fields are set to + * their default value and we won't know about it. + */ +static ExifData * +vips_exif_load_data_without_fix( void *data, int data_length ) +{ + ExifData *ed; + + if( !(ed = exif_data_new()) ) { + vips_error( "VipsJpeg", "%s", _( "unable to init exif" ) ); + return( NULL ); + } + + exif_data_unset_option( ed, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION ); + exif_data_load_data( ed, data, data_length ); + + return( ed ); +} + static int vips_exif_get_int( ExifData *ed, ExifEntry *entry, unsigned long component, int *out ) @@ -538,7 +562,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 +576,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 +613,7 @@ res_from_exif( VipsImage *im, ExifData *ed ) default: vips_warn( "VipsJpeg", "%s", _( "unknown EXIF resolution unit" ) ); - return; + return( -1 ); } #ifdef DEBUG @@ -599,6 +623,8 @@ res_from_exif( VipsImage *im, ExifData *ed ) im->Xres = xres; im->Yres = yres; + + return( 0 ); } static int @@ -626,7 +652,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 @@ -634,27 +660,28 @@ parse_exif( VipsImage *im, void *data, int data_length ) show_values( ed ); #endif /*DEBUG_VERBOSE*/ + /* Look for resolution fields and use them to set the VIPS + * xres/yres fields. + * + * If the fields are missing, write the ones from jfif. + */ + if( res_from_exif( im, ed ) && + vips__set_exif_resolution( ed, im ) ) + return( -1 ); + + /* Make sure all required fields are there before we attach to vips + * metadata. + */ + exif_data_fix( ed ); + /* Attach informational fields for what we find. - - FIXME ... better to have this in the UI layer? - - Or we could attach non-human-readable tags here (int, - double etc) and then move the human stuff to the UI - layer? - */ 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. - */ - res_from_exif( im, ed ); - attach_thumbnail( im, ed ); - exif_data_free( ed ); } #endif /*HAVE_EXIF*/ diff --git a/libvips/foreign/jpegsave.c b/libvips/foreign/jpegsave.c index 5289f176..bf5f1283 100644 --- a/libvips/foreign/jpegsave.c +++ b/libvips/foreign/jpegsave.c @@ -424,7 +424,7 @@ vips_foreign_save_jpeg_mime_init( VipsForeignSaveJpegMime *mime ) * * @optimize_coding: %gboolean, compute optimal Huffman coding tables * * @interlace: %gboolean, write an interlaced (progressive) jpeg * * @strip: %gboolean, remove all metadata from image - * * @no-subsample: %gboolean, disable chroma subsampling + * * @no_subsample: %gboolean, disable chroma subsampling * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block * * @overshoot_deringing: %gboolean, overshoot samples with extreme values * * @optimize_scans: %gboolean, split DCT coefficients into separate scans @@ -453,7 +453,7 @@ vips_foreign_save_jpeg_mime_init( VipsForeignSaveJpegMime *mime ) * If @strip is set, no EXIF data, IPCT data, ICC profile or XMP metadata is * written into the output file. * - * If @no-subsample is set, chrominance subsampling is disabled. This will + * If @no_subsample is set, chrominance subsampling is disabled. This will * improve quality at the cost of larger file size. Useful for high Q factors. * * If @trellis_quant is set and the version of libjpeg supports it @@ -534,12 +534,12 @@ vips_jpegsave( VipsImage *in, const char *filename, ... ) * * Optional arguments: * - * * @Q: JPEG quality factor - * * @profile: attach this ICC profile - * * @optimize_coding: compute optimal Huffman coding tables - * * @interlace: write an interlaced (progressive) jpeg - * * @strip: remove all metadata from image - * * @no-subsample: disable chroma subsampling + * * @Q: %gint, quality factor + * * @profile: filename of ICC profile to attach + * * @optimize_coding: %gboolean, compute optimal Huffman coding tables + * * @interlace: %gboolean, write an interlaced (progressive) jpeg + * * @strip: %gboolean, remove all metadata from image + * * @no_subsample: %gboolean, disable chroma subsampling * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block * * @overshoot_deringing: %gboolean, overshoot samples with extreme values * * @optimize_scans: %gboolean, split DCT coefficients into separate scans @@ -590,11 +590,12 @@ vips_jpegsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) * * Optional arguments: * - * * @Q: JPEG quality factor - * * @profile: attach this ICC profile - * * @optimize_coding: compute optimal Huffman coding tables - * * @strip: remove all metadata from image - * * @no-subsample: disable chroma subsampling + * * @Q: %gint, quality factor + * * @profile: filename of ICC profile to attach + * * @optimize_coding: %gboolean, compute optimal Huffman coding tables + * * @interlace: %gboolean, write an interlaced (progressive) jpeg + * * @strip: %gboolean, remove all metadata from image + * * @no_subsample: %gboolean, disable chroma subsampling * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block * * @overshoot_deringing: %gboolean, overshoot samples with extreme values * * @optimize_scans: %gboolean, split DCT coefficients into separate scans diff --git a/libvips/foreign/vips2jpeg.c b/libvips/foreign/vips2jpeg.c index 04ec6aa6..ceb36c89 100644 --- a/libvips/foreign/vips2jpeg.c +++ b/libvips/foreign/vips2jpeg.c @@ -273,29 +273,21 @@ vips_exif_set_int( ExifData *ed, static void vips_exif_double_to_rational( double value, ExifRational *rv ) { - unsigned int scale; - - /* We scale up to fill uint32, then set that as the - * denominator. Try to avoid generating 0. + /* We will usually set factors of 10, so use 1000 as the denominator + * and it'll probably be OK. */ - scale = (unsigned int) ((UINT_MAX - 1000) / value); - scale = scale == 0 ? 1 : scale; - rv->numerator = value * scale; - rv->denominator = scale; + rv->numerator = value * 1000; + rv->denominator = 1000; } static void vips_exif_double_to_srational( double value, ExifSRational *srv ) { - int scale; - - /* We scale up to fill int32, then set that as the - * denominator. Try to avoid generating 0. + /* We will usually set factors of 10, so use 1000 as the denominator + * and it'll probably be OK. */ - scale = (int) ((INT_MAX - 1000) / value); - scale = scale == 0 ? 1 : scale; - srv->numerator = value * scale; - srv->denominator = scale; + srv->numerator = value * 1000; + srv->denominator = 1000; } /* Parse a char* into an ExifRational. We allow floats as well. @@ -461,15 +453,17 @@ write_tag( ExifData *ed, int ifd, ExifTag tag, write_fn fn, void *data ) /* This is different, we set the xres/yres from the vips header rather than * from the exif tags on the image metadata. + * + * This is also called from the jpg reader to fix up bad exif resoltion. */ -static int -set_exif_resolution( ExifData *ed, VipsImage *im ) +int +vips__set_exif_resolution( ExifData *ed, VipsImage *im ) { double xres, yres; const char *p; int unit; - VIPS_DEBUG_MSG( "set_exif_resolution: vips res of %g, %g\n", + VIPS_DEBUG_MSG( "vips__set_exif_resolution: vips res of %g, %g\n", im->Xres, im->Yres ); /* Default to inches, more progs support it. @@ -823,7 +817,7 @@ write_exif( Write *write ) /* Update EXIF resolution from the vips image header. */ - if( set_exif_resolution( ed, write->in ) ) { + if( vips__set_exif_resolution( ed, write->in ) ) { exif_data_free( ed ); return( -1 ); }