From ac377c143b310233611de208ef370c2b2ae30ceb Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 17 Oct 2011 07:15:51 +0100 Subject: [PATCH] im_dlip*() redone as a class VipsFlip replaces im_fliphor() and im_flipver(). --- ChangeLog | 6 +- TODO | 7 + libvips/conversion/Makefile.am | 3 +- libvips/conversion/conversion.c | 2 + libvips/conversion/embed.c | 2 +- libvips/conversion/flip.c | 283 +++++++++++++++++++++++++++++ libvips/conversion/im_fliphor.c | 139 -------------- libvips/conversion/im_flipver.c | 130 ------------- libvips/deprecated/vips7compat.c | 32 ++++ libvips/include/vips/conversion.h | 22 ++- libvips/include/vips/enumtypes.h | 2 + libvips/include/vips/vips7compat.h | 3 + libvips/iofuncs/enumtypes.c | 18 ++ 13 files changed, 372 insertions(+), 277 deletions(-) create mode 100644 libvips/conversion/flip.c delete mode 100644 libvips/conversion/im_fliphor.c delete mode 100644 libvips/conversion/im_flipver.c diff --git a/ChangeLog b/ChangeLog index 98400eb5..4860d07b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ 20/8/11 started 7.27.0 - version bump for new dev cycle -- im_subtract(), im_avg(), im_min(), im_minpos(), im_copy(), im_embed() - redone as classes +- im_subtract(), im_avg(), im_min(), im_minpos(), im_copy(), im_embed(), + im_flophor(), im_flipver() redone as classes - added VIPS_ARGUMENT_APPEND to help control arg ordering - generate has a 'stop' param to signal successful early termination - added optional output args, eg. x/y for min @@ -25,7 +25,7 @@ - handle offset correctly in separable convolutions (thanks Nicolas) - macros for class arg boilerplate - class arg order set by new 'priority' param -- VipsExtend enum added +- VipsExtend, VipsDirection enums added 12/9/11 started 7.26.4 - fallback vips_init() diff --git a/TODO b/TODO index eccd1d2d..0e5a6325 100644 --- a/TODO +++ b/TODO @@ -11,6 +11,13 @@ no output arg? +- try + + $ vips im_fliphor firegirl.jpg x.v + + lots of errors + + diff --git a/libvips/conversion/Makefile.am b/libvips/conversion/Makefile.am index 43fb80fb..98a64c92 100644 --- a/libvips/conversion/Makefile.am +++ b/libvips/conversion/Makefile.am @@ -5,6 +5,7 @@ libconversion_la_SOURCES = \ conversion.h \ copy.c \ embed.c \ + flip.c \ conver_dispatch.c \ im_black.c \ im_c2amph.c \ @@ -15,8 +16,6 @@ libconversion_la_SOURCES = \ im_copy_file.c \ im_extract.c \ im_falsecolour.c \ - im_fliphor.c \ - im_flipver.c \ im_gbandjoin.c \ im_insert.c \ im_lrjoin.c \ diff --git a/libvips/conversion/conversion.c b/libvips/conversion/conversion.c index 0924d0fc..bac817ec 100644 --- a/libvips/conversion/conversion.c +++ b/libvips/conversion/conversion.c @@ -104,8 +104,10 @@ vips_conversion_operation_init( void ) { extern GType vips_copy_get_type( void ); extern GType vips_embed_get_type( void ); + extern GType vips_flip_get_type( void ); vips_copy_get_type(); vips_embed_get_type(); + vips_flip_get_type(); } diff --git a/libvips/conversion/embed.c b/libvips/conversion/embed.c index 47387464..f2994556 100644 --- a/libvips/conversion/embed.c +++ b/libvips/conversion/embed.c @@ -52,8 +52,8 @@ */ /* - */ #define VIPS_DEBUG + */ #ifdef HAVE_CONFIG_H #include diff --git a/libvips/conversion/flip.c b/libvips/conversion/flip.c new file mode 100644 index 00000000..589998c8 --- /dev/null +++ b/libvips/conversion/flip.c @@ -0,0 +1,283 @@ +/* im_fliphor + * + * Copyright: 1990, N. Dessipris + * Written on: 28/10/91 + * Updated on: + * 19/7/93 JC + * - now allows IM_CODING_LABQ too + * - yuk! needs rewriting + * 21/12/94 JC + * - rewritten + * 14/4/04 + * - sets Xoffset / Yoffset + * 24/3/09 + * - added IM_CODING_RAD support + * 29/1/10 + * - cleanups + * - gtkdoc + * 17/10/11 + * - redone 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" + +/** + * VipsFlip: + * @in: input image + * @out: output image + * @direction: flip horizontally or vertically + * + * Flips an image left-right or up-down. + * + * See also: im_rot90(). + * + * Returns: 0 on success, -1 on error + */ + +typedef struct _VipsFlip { + VipsConversion parent_instance; + + /* The input image. + */ + VipsImage *input; + + /* Swap bytes on the way through. + */ + VipsDirection direction; + +} VipsFlip; + +typedef VipsConversionClass VipsFlipClass; + +G_DEFINE_TYPE( VipsFlip, vips_flip, VIPS_TYPE_CONVERSION ); + +static int +vips_flip_vertical_gen( VipsRegion *or, void *seq, void *a, void *b, + gboolean *stop ) +{ + VipsRegion *ir = (VipsRegion *) seq; + VipsRect *r = &or->valid; + VipsRect in; + PEL *p, *q; + int y; + + int le = r->left; + int to = r->top; + int bo = VIPS_RECT_BOTTOM( r ); + + int ls; + int psk, qsk; + + /* Transform to input coordinates. + */ + in = *r; + in.top = ir->im->Ysize - bo; + + /* Ask for input we need. + */ + if( vips_region_prepare( ir, &in ) ) + return( -1 ); + + /* Loop, copying and reversing lines. + */ + p = (PEL *) VIPS_REGION_ADDR( ir, le, in.top + in.height - 1 ); + q = (PEL *) VIPS_REGION_ADDR( or, le, to ); + psk = VIPS_REGION_LSKIP( ir ); + qsk = VIPS_REGION_LSKIP( or ); + ls = VIPS_REGION_SIZEOF_LINE( or ); + + for( y = to; y < bo; y++ ) { + memcpy( q, p, ls ); + + p -= psk; + q += qsk; + } + + return( 0 ); +} + +static int +vips_flip_horizontal_gen( VipsRegion *or, void *seq, void *a, void *b, + gboolean *stop ) +{ + VipsRegion *ir = (VipsRegion *) seq; + VipsRect *r = &or->valid; + VipsRect in; + char *p, *q; + int x, y, z; + + int le = r->left; + int ri = VIPS_RECT_RIGHT(r); + int to = r->top; + int bo = VIPS_RECT_BOTTOM(r); + + int ps = VIPS_IMAGE_SIZEOF_PEL( ir->im ); /* sizeof pel */ + + int hgt = ir->im->Xsize - r->width; + + int lastx; + + /* Transform to input coordinates. + */ + in = *r; + in.left = hgt - r->left; + + /* Find x of final pixel in input area. + */ + lastx = VIPS_RECT_RIGHT( &in ) - 1; + + /* Ask for input we need. + */ + if( vips_region_prepare( ir, &in ) ) + return( -1 ); + + /* Loop, copying and reversing lines. + */ + for( y = to; y < bo; y++ ) { + p = VIPS_REGION_ADDR( ir, lastx, y ); + q = VIPS_REGION_ADDR( or, le, y ); + + for( x = le; x < ri; x++ ) { + /* Copy the pel. + */ + for( z = 0; z < ps; z++ ) + q[z] = p[z]; + + /* Skip forwards in out, back in in. + */ + q += ps; + p -= ps; + } + } + + return( 0 ); +} + +static int +vips_flip_build( VipsObject *object ) +{ + VipsConversion *conversion = VIPS_CONVERSION( object ); + VipsFlip *flip = (VipsFlip *) object; + + VipsGenerateFn generate_fn; + + if( VIPS_OBJECT_CLASS( vips_flip_parent_class )->build( object ) ) + return( -1 ); + + if( vips_image_pio_input( flip->input ) || + vips_image_pio_output( conversion->output ) ) + return( -1 ); + + if( vips_image_copy_fields( conversion->output, flip->input ) ) + return( -1 ); + vips_demand_hint( conversion->output, + VIPS_DEMAND_STYLE_THINSTRIP, flip->input, NULL ); + + if( flip->direction == VIPS_DIRECTION_HORIZONTAL ) { + generate_fn = vips_flip_horizontal_gen; + conversion->output->Xoffset = flip->input->Xsize; + conversion->output->Yoffset = 0; + } + else { + generate_fn = vips_flip_vertical_gen; + conversion->output->Xoffset = 0; + conversion->output->Yoffset = flip->input->Ysize; + } + + if( vips_image_generate( conversion->output, + vips_start_one, generate_fn, vips_stop_one, + flip->input, flip ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_flip_class_init( VipsFlipClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + + VIPS_DEBUG_MSG( "vips_flip_class_init\n" ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "flip"; + vobject_class->description = _( "flip an image" ); + vobject_class->build = vips_flip_build; + + VIPS_ARG_IMAGE( class, "in", 1, + _( "Input" ), + _( "Input image" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFlip, input ) ); + + VIPS_ARG_ENUM( class, "direction", 6, + _( "Direction" ), + _( "Direction to flip image" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFlip, direction ), + VIPS_TYPE_DIRECTION, VIPS_DIRECTION_HORIZONTAL ); +} + +static void +vips_flip_init( VipsFlip *flip ) +{ +} + +int +vips_flip( VipsImage *in, VipsImage **out, VipsDirection direction, ... ) +{ + va_list ap; + int result; + + va_start( ap, direction ); + result = vips_call_split( "flip", ap, in, out, direction ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/conversion/im_fliphor.c b/libvips/conversion/im_fliphor.c deleted file mode 100644 index 5fa2e45b..00000000 --- a/libvips/conversion/im_fliphor.c +++ /dev/null @@ -1,139 +0,0 @@ -/* im_fliphor - * - * Copyright: 1990, N. Dessipris - * Written on: 28/10/91 - * Updated on: - * 19/7/93 JC - * - now allows IM_CODING_LABQ too - * - yuk! needs rewriting - * 21/12/94 JC - * - rewritten - * 14/4/04 - * - sets Xoffset / Yoffset - * 24/3/09 - * - added IM_CODING_RAD support - * 29/1/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 - -/* Flip a small area. - */ -static int -flip_gen( REGION *or, void *seq, void *a, void *b ) -{ - REGION *ir = (REGION *) seq; - Rect *r = &or->valid; - Rect in; - char *p, *q; - int x, y, z; - - int le = r->left; - int ri = IM_RECT_RIGHT(r); - int to = r->top; - int bo = IM_RECT_BOTTOM(r); - - int ps = IM_IMAGE_SIZEOF_PEL( ir->im ); /* sizeof pel */ - - int hgt = ir->im->Xsize - r->width; - - int lastx; - - /* Transform to input coordinates. - */ - in = *r; - in.left = hgt - r->left; - - /* Find x of final pixel in input area. - */ - lastx = IM_RECT_RIGHT( &in ) - 1; - - /* Ask for input we need. - */ - if( im_prepare( ir, &in ) ) - return( -1 ); - - /* Loop, copying and reversing lines. - */ - for( y = to; y < bo; y++ ) { - p = IM_REGION_ADDR( ir, lastx, y ); - q = IM_REGION_ADDR( or, le, y ); - - for( x = le; x < ri; x++ ) { - /* Copy the pel. - */ - for( z = 0; z < ps; z++ ) - q[z] = p[z]; - - /* Skip forwards in out, back in in. - */ - q += ps; - p -= ps; - } - } - - return( 0 ); -} - -/** - * im_fliphor: - * @in: input image - * @out: output image - * - * Flips an image left-right. - * - * See also: im_flipver(), im_rot90(). - * - * Returns: 0 on success, -1 on error - */ -int -im_fliphor( IMAGE *in, IMAGE *out ) -{ - if( im_piocheck( in, out ) || - im_check_coding_known( "im_fliphor", in ) || - im_cp_desc( out, in ) || - im_demand_hint( out, IM_THINSTRIP, in, NULL ) || - im_generate( out, - im_start_one, flip_gen, im_stop_one, in, NULL ) ) - return( -1 ); - - out->Xoffset = in->Xsize; - out->Yoffset = 0; - - return( 0 ); -} diff --git a/libvips/conversion/im_flipver.c b/libvips/conversion/im_flipver.c deleted file mode 100644 index 7e462d3b..00000000 --- a/libvips/conversion/im_flipver.c +++ /dev/null @@ -1,130 +0,0 @@ -/* im_flipver - * - * Copyright: 1990, N. Dessipris - * Written on: 28/10/91 - * Updated on: - * 21/12/94 JC - * - adapted from new im_fliphor(). - * 30/8/96 JC - * - ooops! IM_REGION_SIZEOF_LINE() not valid until im_prepare() has been - * called - * 7/3/03 JC - * - ahem, memcpy() line size calc was wrong, occasional segvs - * 14/4/04 - * - sets Xoffset / Yoffset - * 24/3/09 - * - added IM_CODING_RAD support - * 29/1/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 - -/* Flip a small area. - */ -static int -flip_gen( REGION *or, void *seq, void *a, void *b ) -{ - REGION *ir = (REGION *) seq; - Rect *r = &or->valid; - Rect in; - PEL *p, *q; - int y; - - int le = r->left; - int to = r->top; - int bo = IM_RECT_BOTTOM( r ); - - int ls; - int psk, qsk; - - /* Transform to input coordinates. - */ - in = *r; - in.top = ir->im->Ysize - bo; - - /* Ask for input we need. - */ - if( im_prepare( ir, &in ) ) - return( -1 ); - - /* Loop, copying and reversing lines. - */ - p = (PEL *) IM_REGION_ADDR( ir, le, in.top + in.height - 1 ); - q = (PEL *) IM_REGION_ADDR( or, le, to ); - psk = IM_REGION_LSKIP( ir ); - qsk = IM_REGION_LSKIP( or ); - ls = IM_REGION_SIZEOF_LINE( or ); - - for( y = to; y < bo; y++ ) { - memcpy( q, p, ls ); - - p -= psk; - q += qsk; - } - - return( 0 ); -} - -/** - * im_flipver: - * @in: input image - * @out: output image - * - * Flips an image top-bottom. - * - * See also: im_fliphor(), im_rot90(). - * - * Returns: 0 on success, -1 on error - */ -int -im_flipver( IMAGE *in, IMAGE *out ) -{ - if( im_piocheck( in, out ) || - im_check_coding_known( "im_flipver", in ) || - im_cp_desc( out, in ) || - im_demand_hint( out, IM_THINSTRIP, in, NULL ) || - im_generate( out, - im_start_one, flip_gen, im_stop_one, in, NULL ) ) - return( -1 ); - - out->Xoffset = 0; - out->Yoffset = in->Ysize; - - return( 0 ); -} diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index a3886895..973eaddb 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -1079,3 +1079,35 @@ im_embed( IMAGE *in, IMAGE *out, int type, int x, int y, int width, int height ) return( 0 ); } + +int +im_fliphor( IMAGE *in, IMAGE *out ) +{ + VipsImage *t; + + if( vips_flip( in, &t, VIPS_DIRECTION_HORIZONTAL, 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 ) +{ + VipsImage *t; + + if( vips_flip( in, &t, VIPS_DIRECTION_VERTICAL, NULL ) ) + return( -1 ); + if( vips_image_write( t, out ) ) { + g_object_unref( t ); + return( -1 ); + } + g_object_unref( t ); + + return( 0 ); +} diff --git a/libvips/include/vips/conversion.h b/libvips/include/vips/conversion.h index 84592b69..c51a4c2e 100644 --- a/libvips/include/vips/conversion.h +++ b/libvips/include/vips/conversion.h @@ -76,11 +76,31 @@ typedef enum { VIPS_EXTEND_LAST = 5 } VipsExtend; +/** + * VipsDirection: + * @VIPS_DIRECTION_HORIZONTAL; left-right + * @VIPS_DIRECTION_VERTICAL; top-bottom + * + * See vips_flip(), vips_join() and so on. + * + * Operations like vips_flip() need to be told whether to flip left-right or + * top-bottom. + * + * See also: vips_flip(), vips_join(). + */ +typedef enum { + VIPS_DIRECTION_HORIZONTAL, + VIPS_DIRECTION_VERTICAL, + VIPS_DIRECTION_LAST +} VipsDirection; + int vips_copy( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); int vips_embed( VipsImage *in, VipsImage **out, int x, int y, int width, int height, ... ) __attribute__((sentinel)); +int vips_flip( VipsImage *in, VipsImage **out, VipsDirection direction, ... ) + __attribute__((sentinel)); @@ -126,8 +146,6 @@ int im_replicate( VipsImage *in, VipsImage *out, int across, int down ); 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_fliphor( VipsImage *in, VipsImage *out ); -int im_flipver( VipsImage *in, VipsImage *out ); int im_rot90( VipsImage *in, VipsImage *out ); int im_rot180( VipsImage *in, VipsImage *out ); int im_rot270( VipsImage *in, VipsImage *out ); diff --git a/libvips/include/vips/enumtypes.h b/libvips/include/vips/enumtypes.h index 6d96d032..00d23cdb 100644 --- a/libvips/include/vips/enumtypes.h +++ b/libvips/include/vips/enumtypes.h @@ -9,6 +9,8 @@ G_BEGIN_DECLS /* enumerations from "../../../libvips/include/vips/conversion.h" */ GType vips_extend_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_EXTEND (vips_extend_get_type()) +GType vips_direction_get_type (void) G_GNUC_CONST; +#define VIPS_TYPE_DIRECTION (vips_direction_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 d8c103e6..6bbe9775 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -540,6 +540,9 @@ int im_copy_native( VipsImage *in, VipsImage *out, gboolean is_msb_first ); int im_embed( VipsImage *in, VipsImage *out, int type, int x, int y, int width, int height ); +int im_fliphor( VipsImage *in, VipsImage *out ); +int im_flipver( VipsImage *in, VipsImage *out ); + /* ruby-vips uses this */ #define vips_class_map_concrete_all vips_class_map_all diff --git a/libvips/iofuncs/enumtypes.c b/libvips/iofuncs/enumtypes.c index cfdc48bd..e7c66e37 100644 --- a/libvips/iofuncs/enumtypes.c +++ b/libvips/iofuncs/enumtypes.c @@ -26,6 +26,24 @@ vips_extend_get_type( void ) return( etype ); } +GType +vips_direction_get_type( void ) +{ + static GType etype = 0; + + if( etype == 0 ) { + static const GEnumValue values[] = { + {VIPS_DIRECTION_HORIZONTAL, "VIPS_DIRECTION_HORIZONTAL", "horizontal"}, + {VIPS_DIRECTION_VERTICAL, "VIPS_DIRECTION_VERTICAL", "vertical"}, + {VIPS_DIRECTION_LAST, "VIPS_DIRECTION_LAST", "last"}, + {0, NULL, NULL} + }; + + etype = g_enum_register_static( "VipsDirection", values ); + } + + return( etype ); +} /* enumerations from "../../libvips/include/vips/util.h" */ GType vips_token_get_type( void )