diff --git a/ChangeLog b/ChangeLog index 962373fe..61cd5e8d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,7 +4,7 @@ im_flophor(), im_flipver(), im_insert(), im_insert_noexpand(), im_lrjoin(), im_tbjoin(), im_extract_area(), im_extract_bands(), im_extract_areabands(), im_replicate(), im_clip2fmt(), im_gbandjoin(), im_bandjoin(), im_invert(), - im_lintra(), im_lintra_vec(), im_black() + im_lintra(), im_lintra_vec(), im_black(), im_rot90, im_rot180(), im_rot270() redone as classes - added argument priorites to help control arg ordering - generate has a 'stop' param to signal successful early termination diff --git a/TODO b/TODO index a147f36a..3994fe66 100644 --- a/TODO +++ b/TODO @@ -24,6 +24,41 @@ move format to new-style and try it +- also VipsFormat ... could this replace vips_image_new_from_string()? or + could we call this from vips_image_new_from_string()? + + at the moment, VipsFormat subclasses never get made, we just use the classes + ... we'd need to start making real vipsformat objects for this to work + + how would this work? + + at the moment we have + + image = vips_image_new_from_file( filename ); + + build a VipsImage with filename "r" + + we also have the new CLI thing + + obj = vips_object_new_from_string( class, str ); + + calls class->new_from_string( first-component(str) ), then sets + optional args from rest-of-str(str), then does _build() + + image-class->new_from_string() just make a vipsimage "r" str + + the _build() uses VipsFormat() to load via im_tiff2vips() or whatever + + so ... we could change vips_image_new_from_file() to be + + VIPS_IMAGE( vips_object_new_from_string( VipsImageClass, str ) ) + + we could also make VipsImage::new_from_string() make a real VipsFormat + object, then load options could be set from the str + + how does save work? we call image-class->output_to_arg(obj, str), which in + turn calls vips_image_write(), which in turn uses VipsFormat + @@ -127,41 +162,6 @@ -- also VipsFormat ... could this replace vips_image_new_from_string()? or - could we call this from vips_image_new_from_string()? - - at the moment, VipsFormat subclasses never get made, we just use the classes - ... we'd need to start making real vipsformat objects for this to work - - how would this work? - - at the moment we have - - image = vips_image_new_from_file( filename ); - - build a VipsImage with filename "r" - - we also have the new CLI thing - - obj = vips_object_new_from_string( class, str ); - - calls class->new_from_string( first-component(str) ), then sets - optional args from rest-of-str(str), then does _build() - - image-class->new_from_string() just make a vipsimage "r" str - - the _build() uses VipsFormat() to load via im_tiff2vips() or whatever - - so ... we could change vips_image_new_from_file() to be - - VIPS_IMAGE( vips_object_new_from_string( VipsImageClass, str ) ) - - we could also make VipsImage::new_from_string() make a real VipsFormat - object, then load options could be set from the str - - how does save work? we call image-class->output_to_arg(obj, str), which in - turn calls vips_image_write(), which in turn uses VipsFormat - diff --git a/libvips/conversion/Makefile.am b/libvips/conversion/Makefile.am index 98157fd0..10fa546b 100644 --- a/libvips/conversion/Makefile.am +++ b/libvips/conversion/Makefile.am @@ -13,6 +13,7 @@ libconversion_la_SOURCES = \ cast.c \ bandjoin.c \ black.c \ + rot.c \ conver_dispatch.c \ im_c2amph.c \ im_c2rect.c \ @@ -24,9 +25,6 @@ libconversion_la_SOURCES = \ im_msb.c \ im_grid.c \ im_ri2c.c \ - im_rot180.c \ - im_rot270.c \ - im_rot90.c \ im_scale.c \ im_insert.c \ im_scaleps.c \ diff --git a/libvips/conversion/conversion.c b/libvips/conversion/conversion.c index faa167f2..847b1418 100644 --- a/libvips/conversion/conversion.c +++ b/libvips/conversion/conversion.c @@ -113,6 +113,7 @@ vips_conversion_operation_init( void ) extern GType vips_cast_get_type( void ); extern GType vips_bandjoin_get_type( void ); extern GType vips_black_get_type( void ); + extern GType vips_rot_get_type( void ); vips_copy_get_type(); vips_embed_get_type(); @@ -125,5 +126,6 @@ vips_conversion_operation_init( void ) vips_cast_get_type(); vips_bandjoin_get_type(); vips_black_get_type(); + vips_rot_get_type(); } diff --git a/libvips/conversion/flip.c b/libvips/conversion/flip.c index b37e07ea..ffcab56e 100644 --- a/libvips/conversion/flip.c +++ b/libvips/conversion/flip.c @@ -72,7 +72,7 @@ * * Flips an image left-right or up-down. * - * See also: im_rot90(). + * See also: #VipsRot. * * Returns: 0 on success, -1 on error */ @@ -84,7 +84,7 @@ typedef struct _VipsFlip { */ VipsImage *in; - /* Swap bytes on the way through. + /* Left-right or up-down. */ VipsDirection direction; diff --git a/libvips/conversion/im_rot180.c b/libvips/conversion/im_rot180.c deleted file mode 100644 index c2bc64f9..00000000 --- a/libvips/conversion/im_rot180.c +++ /dev/null @@ -1,156 +0,0 @@ -/* im_rot180 - * - * Copyright: 1991, N. Dessipris - * Written on: 28/10/91 - * Updated on: 2/4/92, J.Cupitt - * bugs in im_la90rot fixed, now works for any type. - * 19/7/93 JC - * - IM_CODING_LABQ allowed now - * 15/11/94 JC - * - name changed - * - memory leaks fixed - * 8/2/95 JC - * - oops! memory allocation problem fixed - * 18/5/95 JC - * - IM_MAXLINES increased - * 13/8/96 JC - * - rewritten for partials - * - adapted from im_rot90 - * 14/4/04 - * - sets Xoffset / Yoffset - * 24/3/09 - * - added IM_CODING_RAD support - * 1/2/10 - * - cleanups - * - gtkdoc - */ - -/* - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 -#include - -#include - -static int -rot180_gen( REGION *or, void *seq, void *a, void *b ) -{ - REGION *ir = (REGION *) seq; - IMAGE *in = (IMAGE *) a; - - /* Output area. - */ - Rect *r = &or->valid; - int le = r->left; - int ri = IM_RECT_RIGHT(r); - int to = r->top; - int bo = IM_RECT_BOTTOM(r); - - int x, y; - - /* Pixel geometry. - */ - int ps; - - /* Find the area of the input image we need. - */ - Rect need; - - need.left = in->Xsize - ri; - need.top = in->Ysize - bo; - need.width = r->width; - need.height = r->height; - if( im_prepare( ir, &need ) ) - return( -1 ); - - /* Find PEL size and line skip for ir. - */ - ps = IM_IMAGE_SIZEOF_PEL( in ); - - /* Rotate the bit we now have. - */ - for( y = to; y < bo; y++ ) { - /* Start of this output line. - */ - PEL *q = (PEL *) IM_REGION_ADDR( or, le, y ); - - /* Corresponding position in ir. - */ - PEL *p = (PEL *) IM_REGION_ADDR( ir, - need.left + need.width - 1, - need.top + need.height - (y - to) - 1 ); - - /* Blap across! - */ - for( x = le; x < ri; x++ ) { - memcpy( q, p, ps ); - q += ps; - p -= ps; - } - } - - return( 0 ); -} - -/** - * im_rot180: - * @in: input image - * @out: output image - * - * Rotate an image 180 degrees. - * - * See also: im_rot90(), im_rot270(), im_affinei_all(). - * - * Returns: 0 on success, -1 on error - */ -int -im_rot180( IMAGE *in, IMAGE *out ) -{ - if( im_piocheck( in, out ) || - im_check_coding_known( "im_rot180", in ) ) - return( -1 ); - - if( im_cp_desc( out, in ) || - im_demand_hint( out, IM_THINSTRIP, in, NULL ) ) - return( -1 ); - - if( im_generate( out, - im_start_one, rot180_gen, im_stop_one, in, NULL ) ) - return( -1 ); - - out->Xoffset = in->Xsize; - out->Yoffset = in->Ysize; - - return( 0 ); -} - diff --git a/libvips/conversion/im_rot270.c b/libvips/conversion/im_rot270.c deleted file mode 100644 index 3191861c..00000000 --- a/libvips/conversion/im_rot270.c +++ /dev/null @@ -1,162 +0,0 @@ -/* im_rot270 - * - * Copyright: 1991, N. Dessipris - * Written on: 28/10/91 - * Updated on: 2/4/92, J.Cupitt - * bugs in im_la90rot fixed, now works for any type. - * 19/7/93 JC - * - IM_CODING_LABQ allowed now - * 15/11/94 JC - * - name changed - * - memory leaks fixed - * 8/2/95 JC - * - oops! memory allocation problem fixed - * 18/5/95 JC - * - IM_MAXLINES increased - * 13/8/96 JC - * - rewritten for partials - * 6/11/02 JC - * - speed-up ... replace memcpy() with a loop for small pixels - * 14/4/04 - * - sets Xoffset / Yoffset - * 24/3/09 - * - added IM_CODING_RAD support - * 1/2/10 - * - cleanups - * - gtkdoc - */ - -/* - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 -#include - -#include - -/* Rotate a small piece. - */ -static int -rot270_gen( REGION *or, void *seq, void *a, void *b ) -{ - REGION *ir = (REGION *) seq; - IMAGE *in = (IMAGE *) a; - - /* Output area. - */ - Rect *r = &or->valid; - int le = r->left; - int ri = IM_RECT_RIGHT(r); - int to = r->top; - int bo = IM_RECT_BOTTOM(r); - - int x, y, i; - - /* Pixel geometry. - */ - int ps, ls; - - /* Find the area of the input image we need. - */ - Rect need; - - need.left = in->Xsize - bo; - need.top = le; - need.width = r->height; - need.height = r->width; - if( im_prepare( ir, &need ) ) - return( -1 ); - - /* Find PEL size and line skip for ir. - */ - ps = IM_IMAGE_SIZEOF_PEL( in ); - ls = IM_REGION_LSKIP( ir ); - - /* Rotate the bit we now have. - */ - for( y = to; y < bo; y++ ) { - /* Start of this output line. - */ - PEL *q = (PEL *) IM_REGION_ADDR( or, le, y ); - - /* Corresponding position in ir. - */ - PEL *p = (PEL *) IM_REGION_ADDR( ir, - need.left + need.width - (y - to) - 1, - need.top ); - - for( x = le; x < ri; x++ ) { - for( i = 0; i < ps; i++ ) - q[i] = p[i]; - - q += ps; - p += ls; - } - } - - return( 0 ); -} - -/** - * im_rot270: - * @in: input image - * @out: output image - * - * Rotate an image 270 degrees. - * - * See also: im_rot180(), im_rot90(), im_affinei_all(). - * - * Returns: 0 on success, -1 on error - */ -int -im_rot270( IMAGE *in, IMAGE *out ) -{ - if( im_piocheck( in, out ) || - im_check_coding_known( "im_rot270", in ) ) - return( -1 ); - - if( im_cp_desc( out, in ) || - im_demand_hint( out, IM_SMALLTILE, in, NULL ) ) - return( -1 ); - out->Xsize = in->Ysize; - out->Ysize = in->Xsize; - - if( im_generate( out, - im_start_one, rot270_gen, im_stop_one, in, NULL ) ) - return( -1 ); - - out->Xoffset = 0; - out->Yoffset = in->Xsize; - - return( 0 ); -} - diff --git a/libvips/conversion/im_rot90.c b/libvips/conversion/im_rot90.c deleted file mode 100644 index 68bc6b54..00000000 --- a/libvips/conversion/im_rot90.c +++ /dev/null @@ -1,162 +0,0 @@ -/* im_rot90 - * - * Copyright: 1991, N. Dessipris - * Written on: 28/10/91 - * Updated on: 2/4/92, J.Cupitt - * bugs in im_la90rot fixed, now works for any type. - * 19/7/93 JC - * - IM_CODING_LABQ allowed now - * 15/11/94 JC - * - name changed - * - memory leaks fixed - * 8/2/95 JC - * - oops! memory allocation problem fixed - * 18/5/95 JC - * - IM_MAXLINES increased - * 13/8/96 JC - * - rewritten for partials - * 6/11/02 JC - * - speed-up ... replace memcpy() with a loop for small pixels - * 14/4/04 - * - sets Xoffset / Yoffset - * 24/3/09 - * - added IM_CODING_RAD support - * 1/2/10 - * - cleanups - * - gtkdoc - */ - -/* - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 -#include - -#include - -/* Rotate a small piece. - */ -static int -rot90_gen( REGION *or, void *seq, void *a, void *b ) -{ - REGION *ir = (REGION *) seq; - IMAGE *in = (IMAGE *) a; - - /* Output area. - */ - Rect *r = &or->valid; - int le = r->left; - int ri = IM_RECT_RIGHT(r); - int to = r->top; - int bo = IM_RECT_BOTTOM(r); - - int x, y, i; - - /* Pixel geometry. - */ - int ps, ls; - - /* Find the area of the input image we need. - */ - Rect need; - - need.left = to; - need.top = in->Ysize - ri; - need.width = r->height; - need.height = r->width; - if( im_prepare( ir, &need ) ) - return( -1 ); - - /* Find PEL size and line skip for ir. - */ - ps = IM_IMAGE_SIZEOF_PEL( in ); - ls = IM_REGION_LSKIP( ir ); - - /* Rotate the bit we now have. - */ - for( y = to; y < bo; y++ ) { - /* Start of this output line. - */ - PEL *q = (PEL *) IM_REGION_ADDR( or, le, y ); - - /* Corresponding position in ir. - */ - PEL *p = (PEL *) IM_REGION_ADDR( ir, - need.left + y - to, - need.top + need.height - 1 ); - - for( x = le; x < ri; x++ ) { - for( i = 0; i < ps; i++ ) - q[i] = p[i]; - - q += ps; - p -= ls; - } - } - - return( 0 ); -} - -/** - * im_rot90: - * @in: input image - * @out: output image - * - * Rotate an image 90 degrees. - * - * See also: im_rot180(), im_rot270(), im_affinei_all(). - * - * Returns: 0 on success, -1 on error - */ -int -im_rot90( IMAGE *in, IMAGE *out ) -{ - if( im_piocheck( in, out ) || - im_check_coding_known( "im_rot90", in ) ) - return( -1 ); - - if( im_cp_desc( out, in ) || - im_demand_hint( out, IM_SMALLTILE, in, NULL ) ) - return( -1 ); - out->Xsize = in->Ysize; - out->Ysize = in->Xsize; - - if( im_generate( out, - im_start_one, rot90_gen, im_stop_one, in, NULL ) ) - return( -1 ); - - out->Xoffset = in->Ysize; - out->Yoffset = 0; - - return( 0 ); -} - diff --git a/libvips/conversion/rot.c b/libvips/conversion/rot.c new file mode 100644 index 00000000..8b7ab17c --- /dev/null +++ b/libvips/conversion/rot.c @@ -0,0 +1,398 @@ +/* im_rot90 + * + * Copyright: 1991, N. Dessipris + * Written on: 28/10/91 + * Updated on: 2/4/92, J.Cupitt + * bugs in im_la90rot fixed, now works for any type. + * 19/7/93 JC + * - IM_CODING_LABQ allowed now + * 15/11/94 JC + * - name changed + * - memory leaks fixed + * 8/2/95 JC + * - oops! memory allocation problem fixed + * 18/5/95 JC + * - IM_MAXLINES increased + * 13/8/96 JC + * - rewritten for partials + * 6/11/02 JC + * - speed-up ... replace memcpy() with a loop for small pixels + * 14/4/04 + * - sets Xoffset / Yoffset + * 24/3/09 + * - added IM_CODING_RAD support + * 1/2/10 + * - cleanups + * - gtkdoc + * 4/11/11 + * - rewrite as a class + */ + +/* + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +/* +#define VIPS_DEBUG + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include +#include +#include + +#include +#include +#include + +#include "conversion.h" + +/** + * VipsRot: + * @in: input image + * @out: output image + * @direction: rot horizontally or vertically + * + * Rots an image left-right or up-down. + * + * See also: #VipsFlip. + * + * Returns: 0 on success, -1 on error + */ + +typedef struct _VipsRot { + VipsConversion parent_instance; + + /* The input image. + */ + VipsImage *in; + + /* Rotate by ... + */ + VipsAngle angle; + +} VipsRot; + +typedef VipsConversionClass VipsRotClass; + +G_DEFINE_TYPE( VipsRot, vips_rot, VIPS_TYPE_CONVERSION ); + +static int +vips_rot90_gen( VipsRegion *or, void *seq, void *a, void *b, + gboolean *stop ) +{ + VipsRegion *ir = (VipsRegion *) seq; + VipsImage *in = (VipsImage *) a; + + /* Output area. + */ + VipsRect *r = &or->valid; + int le = r->left; + int ri = IM_RECT_RIGHT(r); + int to = r->top; + int bo = IM_RECT_BOTTOM(r); + + int x, y, i; + + /* Pixel geometry. + */ + int ps, ls; + + /* Find the area of the input image we need. + */ + VipsRect need; + + need.left = to; + need.top = in->Ysize - ri; + need.width = r->height; + need.height = r->width; + if( vips_region_prepare( ir, &need ) ) + return( -1 ); + + /* Find PEL size and line skip for ir. + */ + ps = VIPS_IMAGE_SIZEOF_PEL( in ); + ls = VIPS_REGION_LSKIP( ir ); + + /* Rotate the bit we now have. + */ + for( y = to; y < bo; y++ ) { + /* Start of this output line. + */ + PEL *q = (PEL *) VIPS_REGION_ADDR( or, le, y ); + + /* Corresponding position in ir. + */ + PEL *p = (PEL *) VIPS_REGION_ADDR( ir, + need.left + y - to, + need.top + need.height - 1 ); + + for( x = le; x < ri; x++ ) { + for( i = 0; i < ps; i++ ) + q[i] = p[i]; + + q += ps; + p -= ls; + } + } + + return( 0 ); +} + +static int +vips_rot180_gen( VipsRegion *or, void *seq, void *a, void *b, + gboolean *stop ) +{ + VipsRegion *ir = (VipsRegion *) seq; + VipsImage *in = (VipsImage *) a; + + /* Output area. + */ + VipsRect *r = &or->valid; + int le = r->left; + int ri = IM_RECT_RIGHT(r); + int to = r->top; + int bo = IM_RECT_BOTTOM(r); + + int x, y; + + /* Pixel geometry. + */ + int ps; + + /* Find the area of the input image we need. + */ + Rect need; + + need.left = in->Xsize - ri; + need.top = in->Ysize - bo; + need.width = r->width; + need.height = r->height; + if( vips_region_prepare( ir, &need ) ) + return( -1 ); + + /* Find PEL size and line skip for ir. + */ + ps = VIPS_IMAGE_SIZEOF_PEL( in ); + + /* Rotate the bit we now have. + */ + for( y = to; y < bo; y++ ) { + /* Start of this output line. + */ + PEL *q = (PEL *) VIPS_REGION_ADDR( or, le, y ); + + /* Corresponding position in ir. + */ + PEL *p = (PEL *) VIPS_REGION_ADDR( ir, + need.left + need.width - 1, + need.top + need.height - (y - to) - 1 ); + + /* Blap across! + */ + for( x = le; x < ri; x++ ) { + memcpy( q, p, ps ); + q += ps; + p -= ps; + } + } + + return( 0 ); +} + +static int +vips_rot270_gen( VipsRegion *or, void *seq, void *a, void *b, + gboolean *stop ) +{ + VipsRegion *ir = (VipsRegion *) seq; + VipsImage *in = (VipsImage *) a; + + /* Output area. + */ + VipsRect *r = &or->valid; + int le = r->left; + int ri = IM_RECT_RIGHT(r); + int to = r->top; + int bo = IM_RECT_BOTTOM(r); + + int x, y, i; + + /* Pixel geometry. + */ + int ps, ls; + + /* Find the area of the input image we need. + */ + VipsRect need; + + need.left = in->Xsize - bo; + need.top = le; + need.width = r->height; + need.height = r->width; + if( vips_region_prepare( ir, &need ) ) + return( -1 ); + + /* Find PEL size and line skip for ir. + */ + ps = VIPS_IMAGE_SIZEOF_PEL( in ); + ls = VIPS_REGION_LSKIP( ir ); + + /* Rotate the bit we now have. + */ + for( y = to; y < bo; y++ ) { + /* Start of this output line. + */ + PEL *q = (PEL *) VIPS_REGION_ADDR( or, le, y ); + + /* Corresponding position in ir. + */ + PEL *p = (PEL *) VIPS_REGION_ADDR( ir, + need.left + need.width - (y - to) - 1, + need.top ); + + for( x = le; x < ri; x++ ) { + for( i = 0; i < ps; i++ ) + q[i] = p[i]; + + q += ps; + p += ls; + } + } + + return( 0 ); +} + +static int +vips_rot_build( VipsObject *object ) +{ + VipsConversion *conversion = VIPS_CONVERSION( object ); + VipsRot *rot = (VipsRot *) object; + + VipsGenerateFn generate_fn; + VipsDemandStyle hint; + + if( VIPS_OBJECT_CLASS( vips_rot_parent_class )->build( object ) ) + return( -1 ); + + if( rot->angle == VIPS_ANGLE_0 ) + return( vips_image_write( rot->in, conversion->out ) ); + + if( vips_image_pio_input( rot->in ) || + vips_image_pio_output( conversion->out ) ) + return( -1 ); + + if( vips_image_copy_fields( conversion->out, rot->in ) ) + return( -1 ); + + switch( rot->angle ) { + case VIPS_ANGLE_90: + generate_fn = vips_rot90_gen; + hint = VIPS_DEMAND_STYLE_SMALLTILE; + conversion->out->Xsize = rot->in->Ysize; + conversion->out->Ysize = rot->in->Xsize; + conversion->out->Xoffset = rot->in->Ysize; + conversion->out->Yoffset = 0; + break; + + case VIPS_ANGLE_180: + generate_fn = vips_rot180_gen; + hint = VIPS_DEMAND_STYLE_THINSTRIP; + conversion->out->Xoffset = rot->in->Xsize; + conversion->out->Yoffset = rot->in->Ysize; + break; + + case VIPS_ANGLE_270: + generate_fn = vips_rot270_gen; + hint = VIPS_DEMAND_STYLE_SMALLTILE; + conversion->out->Xsize = rot->in->Ysize; + conversion->out->Ysize = rot->in->Xsize; + conversion->out->Xoffset = 0; + conversion->out->Yoffset = rot->in->Xsize; + break; + + default: + g_assert( 0 ); + } + + vips_demand_hint( conversion->out, hint, rot->in, NULL ); + + if( vips_image_generate( conversion->out, + vips_start_one, generate_fn, vips_stop_one, + rot->in, rot ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_rot_class_init( VipsRotClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + + VIPS_DEBUG_MSG( "vips_rot_class_init\n" ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "rot"; + vobject_class->description = _( "rotate an image" ); + vobject_class->build = vips_rot_build; + + VIPS_ARG_IMAGE( class, "in", 1, + _( "Input" ), + _( "Input image" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsRot, in ) ); + + VIPS_ARG_ENUM( class, "angle", 6, + _( "Angle" ), + _( "Angle to rotate image" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsRot, angle ), + VIPS_TYPE_ANGLE, VIPS_ANGLE_90 ); +} + +static void +vips_rot_init( VipsRot *rot ) +{ +} + +int +vips_rot( VipsImage *in, VipsImage **out, VipsAngle angle, ... ) +{ + va_list ap; + int result; + + va_start( ap, angle ); + result = vips_call_split( "rot", ap, in, out, angle ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index 9c3517fe..c9ebfc48 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -1096,6 +1096,54 @@ im_fliphor( IMAGE *in, IMAGE *out ) return( 0 ); } +int +im_rot90( IMAGE *in, IMAGE *out ) +{ + VipsImage *t; + + if( vips_rot( in, &t, VIPS_ANGLE_90, NULL ) ) + return( -1 ); + if( vips_image_write( t, out ) ) { + g_object_unref( t ); + return( -1 ); + } + g_object_unref( t ); + + return( 0 ); +} + +int +im_rot180( IMAGE *in, IMAGE *out ) +{ + VipsImage *t; + + if( vips_rot( in, &t, VIPS_ANGLE_180, NULL ) ) + return( -1 ); + if( vips_image_write( t, out ) ) { + g_object_unref( t ); + return( -1 ); + } + g_object_unref( t ); + + return( 0 ); +} + +int +im_rot270( IMAGE *in, IMAGE *out ) +{ + VipsImage *t; + + if( vips_rot( in, &t, VIPS_ANGLE_270, NULL ) ) + return( -1 ); + if( vips_image_write( t, out ) ) { + g_object_unref( t ); + return( -1 ); + } + g_object_unref( t ); + + return( 0 ); +} + int im_flipver( IMAGE *in, IMAGE *out ) { diff --git a/libvips/include/vips/conversion.h b/libvips/include/vips/conversion.h index 0c281e80..d76778b1 100644 --- a/libvips/include/vips/conversion.h +++ b/libvips/include/vips/conversion.h @@ -114,6 +114,27 @@ typedef enum { VIPS_ALIGN_LAST } VipsAlign; +/** + * VipsAngle: + * @VIPS_ANGLE_0; no rotate + * @VIPS_ANGLE_90; 90 degrees anti-clockwise + * @VIPS_ANGLE_180; 180 degree rotate + * @VIPS_ANGLE_270; 90 degrees clockwise + * + * See vips_rot() and so on. + * + * Fixed rotate angles. + * + * See also: vips_rot(). + */ +typedef enum { + VIPS_ANGLE_0, + VIPS_ANGLE_90, + VIPS_ANGLE_180, + VIPS_ANGLE_270, + VIPS_ANGLE_LAST +} VipsAngle; + int vips_copy( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); int vips_embed( VipsImage *in, VipsImage **out, @@ -142,6 +163,8 @@ int vips_bandjoin2( VipsImage *in1, VipsImage *in2, VipsImage **out, ... ) __attribute__((sentinel)); int vips_black( VipsImage **out, int width, int height, ... ) __attribute__((sentinel)); +int vips_rot( VipsImage *in, VipsImage **out, VipsAngle angle, ... ) + __attribute__((sentinel)); @@ -172,10 +195,6 @@ int im_insertset( VipsImage *main, VipsImage *sub, VipsImage *out, int n, int *x int im_grid( VipsImage *in, VipsImage *out, int tile_height, int across, int down ); int im_wrap( VipsImage *in, VipsImage *out, int x, int y ); -int im_rot90( VipsImage *in, VipsImage *out ); -int im_rot180( VipsImage *in, VipsImage *out ); -int im_rot270( VipsImage *in, VipsImage *out ); - int im_subsample( VipsImage *in, VipsImage *out, int xshrink, int yshrink ); int im_zoom( VipsImage *in, VipsImage *out, int xfac, int yfac ); diff --git a/libvips/include/vips/enumtypes.h b/libvips/include/vips/enumtypes.h index 57b29b2b..73462d9c 100644 --- a/libvips/include/vips/enumtypes.h +++ b/libvips/include/vips/enumtypes.h @@ -13,6 +13,8 @@ GType vips_direction_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_DIRECTION (vips_direction_get_type()) GType vips_align_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_ALIGN (vips_align_get_type()) +GType vips_angle_get_type (void) G_GNUC_CONST; +#define VIPS_TYPE_ANGLE (vips_angle_get_type()) /* enumerations from "../../../libvips/include/vips/util.h" */ GType vips_token_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_TOKEN (vips_token_get_type()) diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index a25fd956..81d0ff06 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -559,6 +559,10 @@ int im_bandjoin( VipsImage *in1, VipsImage *in2, VipsImage *out ); int im_gbandjoin( VipsImage **in, VipsImage *out, int n ); int im_black( VipsImage *out, int x, int y, int bands ); +int im_rot90( VipsImage *in, VipsImage *out ); +int im_rot180( VipsImage *in, VipsImage *out ); +int im_rot270( VipsImage *in, VipsImage *out ); + /* ruby-vips uses this diff --git a/libvips/iofuncs/enumtypes.c b/libvips/iofuncs/enumtypes.c index d88f0da1..4d699bf7 100644 --- a/libvips/iofuncs/enumtypes.c +++ b/libvips/iofuncs/enumtypes.c @@ -63,6 +63,26 @@ vips_align_get_type( void ) return( etype ); } +GType +vips_angle_get_type( void ) +{ + static GType etype = 0; + + if( etype == 0 ) { + static const GEnumValue values[] = { + {VIPS_ANGLE_0, "VIPS_ANGLE_0", "0"}, + {VIPS_ANGLE_90, "VIPS_ANGLE_90", "90"}, + {VIPS_ANGLE_180, "VIPS_ANGLE_180", "180"}, + {VIPS_ANGLE_270, "VIPS_ANGLE_270", "270"}, + {VIPS_ANGLE_LAST, "VIPS_ANGLE_LAST", "last"}, + {0, NULL, NULL} + }; + + etype = g_enum_register_static( "VipsAngle", values ); + } + + return( etype ); +} /* enumerations from "../../libvips/include/vips/util.h" */ GType vips_token_get_type( void ) diff --git a/libvips/iofuncs/init.c b/libvips/iofuncs/init.c index 96e0400e..4b99cd41 100644 --- a/libvips/iofuncs/init.c +++ b/libvips/iofuncs/init.c @@ -724,4 +724,3 @@ vips_guess_libdir( const char *argv0, const char *env_name ) return( libdir ); } -