diff --git a/ChangeLog b/ChangeLog index 24cadd3d..1b9f39e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,6 +17,7 @@ - remove cimg support, we have a gmic plugin now instead - add support for vips8 plugins - added "autorotate" option to jpeg load +- added autorot operator 8/10/14 started 7.40.11 - rework extra band handling for colour functions diff --git a/libvips/conversion/Makefile.am b/libvips/conversion/Makefile.am index 9b0e786c..d28f6a7d 100644 --- a/libvips/conversion/Makefile.am +++ b/libvips/conversion/Makefile.am @@ -25,6 +25,7 @@ libconversion_la_SOURCES = \ bandary.c \ rot.c \ rot45.c \ + autorot.c \ ifthenelse.c \ falsecolour.c \ msb.c \ diff --git a/libvips/conversion/autorot.c b/libvips/conversion/autorot.c new file mode 100644 index 00000000..467910da --- /dev/null +++ b/libvips/conversion/autorot.c @@ -0,0 +1,149 @@ +/* autorot + * + * 19/10/14 + * - from jpegload + */ + +/* + + This file is part of VIPS. + + VIPS is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include + +#include "pconversion.h" + +typedef struct _VipsAutorot { + VipsConversion parent_instance; + + VipsImage *in; + +} VipsAutorot; + +typedef VipsConversionClass VipsAutorotClass; + +G_DEFINE_TYPE( VipsAutorot, vips_autorot, VIPS_TYPE_CONVERSION ); + +#define ORIENTATION ("exif-ifd0-Orientation") + +VipsAngle +vips_autorot_get_angle( VipsImage *im ) +{ + VipsAngle angle; + const char *orientation; + + angle = VIPS_ANGLE_D0; + if( vips_image_get_typeof( im, ORIENTATION ) && + !vips_image_get_string( im, ORIENTATION, &orientation ) ) { + if( vips_isprefix( "6", orientation ) ) + angle = VIPS_ANGLE_D90; + else if( vips_isprefix( "8", orientation ) ) + angle = VIPS_ANGLE_D270; + else if( vips_isprefix( "3", orientation ) ) + angle = VIPS_ANGLE_D180; + /* Other values do rotate + mirror, don't bother handling them + * though, how common can mirroring be. + * + * See: + * + * http://www.80sidea.com/archives/2316 + */ + } + + return( angle ); +} + +static int +vips_autorot_build( VipsObject *object ) +{ + VipsConversion *conversion = VIPS_CONVERSION( object ); + VipsAutorot *autorot = (VipsAutorot *) object; + + if( VIPS_OBJECT_CLASS( vips_autorot_parent_class )->build( object ) ) + return( -1 ); + + if( vips_rot( autorot->in, &conversion->out, + vips_autorot_get_angle( autorot->in ), NULL ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_autorot_class_init( VipsAutorotClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "autorot"; + vobject_class->description = _( "autorotate image by exif tag" ); + vobject_class->build = vips_autorot_build; + + VIPS_ARG_IMAGE( class, "in", 1, + _( "Input" ), + _( "Input image" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsAutorot, in ) ); + +} + +static void +vips_autorot_init( VipsAutorot *autorot ) +{ +} + +/** + * vips_autorot: + * @in: input image + * @out: output image + * @...: %NULL-terminated list of optional named arguments + * + * Look at the exif tags and rotate the image to make it upright. + * + * See also: vips_rot(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_autorot( VipsImage *in, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "autorot", ap, in, out ); + va_end( ap ); + + return( result ); +} + diff --git a/libvips/conversion/conversion.c b/libvips/conversion/conversion.c index b1c071d1..90c72cba 100644 --- a/libvips/conversion/conversion.c +++ b/libvips/conversion/conversion.c @@ -233,6 +233,7 @@ vips_conversion_operation_init( void ) extern GType vips_black_get_type( void ); extern GType vips_rot_get_type( void ); extern GType vips_rot45_get_type( void ); + extern GType vips_autorot_get_type( void ); extern GType vips_ifthenelse_get_type( void ); extern GType vips_recomb_get_type( void ); extern GType vips_bandmean_get_type( void ); @@ -271,6 +272,7 @@ vips_conversion_operation_init( void ) vips_black_get_type(); vips_rot_get_type(); vips_rot45_get_type(); + vips_autorot_get_type(); vips_ifthenelse_get_type(); vips_recomb_get_type(); vips_bandmean_get_type(); diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index a0190c70..da4f4028 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -685,35 +685,6 @@ attach_blob( VipsImage *im, const char *field, void *data, int data_length ) return( 0 ); } -#define ORIENTATION ("exif-ifd0-Orientation") - -static VipsAngle -get_angle( VipsImage *im ) -{ - VipsAngle angle; - const char *orientation; - - angle = VIPS_ANGLE_D0; - if( vips_image_get_typeof( im, ORIENTATION ) && - !vips_image_get_string( im, ORIENTATION, &orientation ) ) { - if( vips_isprefix( "6", orientation ) ) - angle = VIPS_ANGLE_D90; - else if( vips_isprefix( "8", orientation ) ) - angle = VIPS_ANGLE_D270; - else if( vips_isprefix( "3", orientation ) ) - angle = VIPS_ANGLE_D180; - /* Other values do rotate + mirror, don't bother handling them - * though, how common can mirroring be. - * - * See: - * - * http://www.80sidea.com/archives/2316 - */ - } - - return( angle ); -} - /* Number of app2 sections we can capture. Each one can be 64k, so 6400k should * be enough for anyone (haha). */ @@ -1002,13 +973,15 @@ read_jpeg_generate( VipsRegion *or, return( 0 ); } +#define ORIENTATION ("exif-ifd0-Orientation") + /* Auto-rotate, if rotate_image is set. */ static VipsImage * read_jpeg_rotate( VipsObject *process, VipsImage *im ) { VipsImage **t = (VipsImage **) vips_object_local_array( process, 2 ); - VipsAngle angle = get_angle( im ); + VipsAngle angle = vips_autorot_get_angle( im ); if( angle != VIPS_ANGLE_D0 ) { /* Need to copy to memory or disc, we have to stay seq. @@ -1103,7 +1076,7 @@ vips__jpeg_read( ReadJpeg *jpeg, VipsImage *out, gboolean header_only ) /* Swap width and height if we're going to rotate this image. */ if( jpeg->autorotate ) { - VipsAngle angle = get_angle( out ); + VipsAngle angle = vips_autorot_get_angle( out ); if( angle == VIPS_ANGLE_D90 || angle == VIPS_ANGLE_D270 ) diff --git a/libvips/include/vips/conversion.h b/libvips/include/vips/conversion.h index a5a09f65..ca5d4e94 100644 --- a/libvips/include/vips/conversion.h +++ b/libvips/include/vips/conversion.h @@ -124,6 +124,9 @@ 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 ); +int vips_autorot( VipsImage *in, VipsImage **out, ... ) + __attribute__((sentinel)); int vips_zoom( VipsImage *in, VipsImage **out, int xfac, int yfac, ... ) __attribute__((sentinel)); int vips_subsample( VipsImage *in, VipsImage **out, int xfac, int yfac, ... )