better jpeg autorot

jpeg write is more careful about removing exif tags that have been
removed from the image metadata

it failed previously if there were multiple Orientation tags
This commit is contained in:
John Cupitt 2016-04-13 08:39:29 +01:00
parent a7e564ed97
commit 2c646a02e4
5 changed files with 105 additions and 10 deletions

View File

@ -23,6 +23,7 @@
- @out_format in vips_system() can contain [options]
- webpsave_buffer no longer ignores @lossless, thanks aaron42net
- float tiff tagged as scRGB to match photoshop convention, thanks Murat
- better jpeg autorot, thanks otto
24/3/16 started 8.2.4
- fix nohalo and vsqbs interpolators, thanks Rafael

View File

@ -33,6 +33,10 @@
*/
/*
#define DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
@ -64,7 +68,7 @@ vips_autorot_get_angle_sub( VipsImage *image,
const char *orientation;
if( vips_isprefix( "exif-", field ) &&
vips_ispostfix( "-Orientation", field ) &&
vips_ispostfix( field, "-Orientation" ) &&
!vips_image_get_string( image, field, &orientation ) ) {
if( vips_isprefix( "6", orientation ) )
*angle = VIPS_ANGLE_D90;
@ -82,6 +86,10 @@ vips_autorot_get_angle_sub( VipsImage *image,
*
* http://www.80sidea.com/archives/2316
*/
/* Stop searching.
*/
return( image );
}
return( NULL );
@ -106,6 +114,10 @@ vips_autorot_get_angle( VipsImage *image )
angle = VIPS_ANGLE_D0;
(void) vips_image_map( image, vips_autorot_get_angle_sub, &angle );
#ifdef DEBUG
printf( "vips_autorot_get_angle: %d\n", angle );
#endif /*DEBUG*/
return( angle );
}
@ -114,8 +126,13 @@ vips_autorot_remove_angle_sub( VipsImage *image,
const char *field, GValue *value, void *my_data )
{
if( vips_isprefix( "exif-", field ) &&
vips_ispostfix( "-Orientation", field ) )
vips_ispostfix( field, "-Orientation" ) ) {
#ifdef DEBUG
printf( "vips_autorot_remove_angle: %s\n", field );
#endif /*DEBUG*/
(void) vips_image_remove( image, field );
}
return( NULL );
}
@ -128,7 +145,7 @@ vips_autorot_remove_angle_sub( VipsImage *image,
*
* See also: vips_autorot_get_angle().
*/
static void
void
vips_autorot_remove_angle( VipsImage *image )
{
(void) vips_image_map( image, vips_autorot_remove_angle_sub, NULL );

View File

@ -49,7 +49,7 @@
* 24/11/11
* - turn into a set of write fns ready to be called from a class
* 7/8/12
* - use VIPS_META_RESOLUTION_UNIT to select resoltuion unit
* - use VIPS_META_RESOLUTION_UNIT to select resolution unit
* 16/11/12
* - read ifds from exif fields
* - optionally parse rationals as a/b
@ -72,6 +72,8 @@
* - set arbitrary exif tags from metadata
* 25/11/15
* - don't write JFIF headers if we are stripping, thanks Benjamin
* 13/4/16
* - remove deleted exif fields more carefully
*/
/*
@ -626,12 +628,87 @@ vips_exif_image_field( VipsImage *image,
return( NULL );
}
typedef struct _VipsExif {
VipsImage *image;
ExifData *ed;
ExifContent *content;
GSList *to_remove;
} VipsExif;
static void
vips_exif_exif_entry( ExifEntry *entry, VipsExif *ve )
{
const char *tag_name;
char vips_name_txt[256];
VipsBuf vips_name = VIPS_BUF_STATIC( vips_name_txt );
if( !(tag_name = exif_tag_get_name( entry->tag )) )
return;
vips_buf_appendf( &vips_name, "exif-ifd%d-%s",
exif_entry_get_ifd( entry ), tag_name );
/* Does this field exist on the image? If not, schedule it for
* removal.
*/
if( !vips_image_get_typeof( ve->image, vips_buf_all( &vips_name ) ) )
ve->to_remove = g_slist_prepend( ve->to_remove, entry );
}
static void *
vips_exif_exif_remove( ExifEntry *entry, VipsExif *ve )
{
#ifdef DEBUG
{
const char *tag_name;
char vips_name_txt[256];
VipsBuf vips_name = VIPS_BUF_STATIC( vips_name_txt );
tag_name = exif_tag_get_name( entry->tag );
vips_buf_appendf( &vips_name, "exif-ifd%d-%s",
exif_entry_get_ifd( entry ), tag_name );
printf( "vips_exif_exif_remove: %s\n", vips_buf_all( &vips_name ) );
}
#endif /*DEBUG*/
exif_content_remove_entry( ve->content, entry );
return( NULL );
}
static void
vips_exif_exif_content( ExifContent *content, VipsExif *ve )
{
ve->content = content;
ve->to_remove = NULL;
exif_content_foreach_entry( content,
(ExifContentForeachEntryFunc) vips_exif_exif_entry, ve );
vips_slist_map2( ve->to_remove,
(VipsSListMap2Fn) vips_exif_exif_remove, ve, NULL );
VIPS_FREEF( g_slist_free, ve->to_remove );
}
static void
vips_exif_update( ExifData *ed, VipsImage *image )
{
VipsExif ve;
VIPS_DEBUG_MSG( "vips_exif_update: \n" );
/* Walk the image and update any stuff that's been changed in image
* metadata.
*/
vips_image_map( image, vips_exif_image_field, ed );
/* Walk the exif and look for any fields which are NOT in image
* metadata. They must have been removed ... remove them from exif as
* well.
*/
ve.image = image;
ve.ed = ed;
exif_data_foreach_content( ed,
(ExifDataForeachContentFunc) vips_exif_exif_content, &ve );
}
#endif /*HAVE_EXIF*/
@ -667,9 +744,7 @@ 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 );
}

View File

@ -127,6 +127,7 @@ int vips_rot( VipsImage *in, VipsImage **out, VipsAngle angle, ... )
int vips_rot45( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
VipsAngle vips_autorot_get_angle( VipsImage *image );
void vips_autorot_remove_angle( VipsImage *image );
int vips_autorot( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
int vips_zoom( VipsImage *in, VipsImage **out, int xfac, int yfac, ... )

View File

@ -93,8 +93,6 @@
#include <vips/vips.h>
#include <vips/internal.h>
#define ORIENTATION ("exif-ifd0-Orientation")
/* Default settings. We change the default to bicubic in main() if
* this vips has been compiled with bicubic support.
*/
@ -582,6 +580,9 @@ thumbnail_rotate( VipsObject *process, VipsImage *im )
if( rotate_image &&
angle != VIPS_ANGLE_D0 ) {
vips_info( "vipsthumbnail", "rotating by %s",
vips_enum_nick( VIPS_TYPE_ANGLE, angle ) );
/* Need to copy to memory, we have to stay seq.
*/
t[0] = vips_image_new_memory();
@ -590,7 +591,7 @@ thumbnail_rotate( VipsObject *process, VipsImage *im )
return( NULL );
im = t[1];
(void) vips_image_remove( im, ORIENTATION );
vips_autorot_remove_angle( im );
}
return( im );