diff --git a/libvips/conversion/autorot.c b/libvips/conversion/autorot.c index db9c032c..a9d4d1d0 100644 --- a/libvips/conversion/autorot.c +++ b/libvips/conversion/autorot.c @@ -2,6 +2,8 @@ * * 19/10/14 * - from jpegload + * 12/4/16 + * - test and remove orientation from every ifd */ /* @@ -53,34 +55,26 @@ typedef VipsConversionClass VipsAutorotClass; G_DEFINE_TYPE( VipsAutorot, vips_autorot, VIPS_TYPE_CONVERSION ); -#define ORIENTATION ("exif-ifd0-Orientation") - -/** - * vips_autorot_get_angle: - * @im: image to fetch orientation from - * - * Examine the metadata on @im and return the #VipsAngle to rotate by to turn - * the image upright. - * - * See also: vips_autorot(). - * - * Returns: the #VipsAngle to rotate by to make the image upright. - */ -VipsAngle -vips_autorot_get_angle( VipsImage *im ) +static void * +vips_autorot_get_angle_sub( VipsImage *image, + const char *field, GValue *value, void *my_data ) { - VipsAngle angle; + VipsAngle *angle = (VipsAngle *) my_data; + const char *orientation; - angle = VIPS_ANGLE_D0; - if( vips_image_get_typeof( im, ORIENTATION ) && - !vips_image_get_string( im, ORIENTATION, &orientation ) ) { + if( vips_isprefix( "exif-", field ) && + vips_ispostfix( "-Orientation", field ) && + !vips_image_get_string( image, field, &orientation ) ) { if( vips_isprefix( "6", orientation ) ) - angle = VIPS_ANGLE_D90; + *angle = VIPS_ANGLE_D90; else if( vips_isprefix( "8", orientation ) ) - angle = VIPS_ANGLE_D270; + *angle = VIPS_ANGLE_D270; else if( vips_isprefix( "3", orientation ) ) - angle = VIPS_ANGLE_D180; + *angle = VIPS_ANGLE_D180; + else + *angle = VIPS_ANGLE_D0; + /* Other values do rotate + mirror, don't bother handling them * though, how common can mirroring be. * @@ -90,9 +84,56 @@ vips_autorot_get_angle( VipsImage *im ) */ } + return( NULL ); +} + +/** + * vips_autorot_get_angle: + * @image: image to fetch orientation from + * + * Examine the metadata on @im and return the #VipsAngle to rotate by to turn + * the image upright. + * + * See also: vips_autorot(). + * + * Returns: the #VipsAngle to rotate by to make the image upright. + */ +VipsAngle +vips_autorot_get_angle( VipsImage *image ) +{ + VipsAngle angle; + + angle = VIPS_ANGLE_D0; + (void) vips_image_map( image, vips_autorot_get_angle_sub, &angle ); + return( angle ); } +static void * +vips_autorot_remove_angle_sub( VipsImage *image, + const char *field, GValue *value, void *my_data ) +{ + if( vips_isprefix( "exif-", field ) && + vips_ispostfix( "-Orientation", field ) ) + (void) vips_image_remove( image, field ); + + return( NULL ); +} + +/** + * vips_autorot_remove_angle: + * @im: image to remove orientation from + * + * Remove any EXIF tag on @im which looks like orientation. + * + * See also: vips_autorot_get_angle(). + */ +static void +vips_autorot_remove_angle( VipsImage *image ) +{ + (void) vips_image_map( image, vips_autorot_remove_angle_sub, NULL ); +} + static int vips_autorot_build( VipsObject *object ) { @@ -106,11 +147,11 @@ vips_autorot_build( VipsObject *object ) g_object_set( object, "angle", vips_autorot_get_angle( autorot->in ), NULL ); - autorot->angle = vips_autorot_get_angle( autorot->in ); - if( vips_rot( autorot->in, &t[0], autorot->angle, NULL ) || - vips_image_write( t[0], conversion->out ) ) + if( vips_rot( autorot->in, &t[0], autorot->angle, NULL ) ) + return( -1 ); + vips_autorot_remove_angle( t[0] ); + if( vips_image_write( t[0], conversion->out ) ) return( -1 ); - (void) vips_image_remove( conversion->out, ORIENTATION ); return( 0 ); } diff --git a/libvips/include/vips/conversion.h b/libvips/include/vips/conversion.h index 61c70bb6..2473531a 100644 --- a/libvips/include/vips/conversion.h +++ b/libvips/include/vips/conversion.h @@ -126,7 +126,7 @@ int vips_rot( VipsImage *in, VipsImage **out, VipsAngle angle, ... ) __attribute__((sentinel)); int vips_rot45( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); -VipsAngle vips_autorot_get_angle( VipsImage *im ); +VipsAngle vips_autorot_get_angle( VipsImage *image ); int vips_autorot( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); int vips_zoom( VipsImage *in, VipsImage **out, int xfac, int yfac, ... )