From ae016dd4086cd68d54d0cbadaeaa1c51fe63a0fb Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 23 Aug 2011 20:56:35 +0100 Subject: [PATCH] turn im_subtract() into a class --- ChangeLog | 1 + libvips/arithmetic/Makefile.am | 2 +- libvips/arithmetic/add.c | 2 +- libvips/arithmetic/arithmetic.c | 2 + .../arithmetic/{im_subtract.c => subtract.c} | 224 ++++++++++-------- libvips/deprecated/vips7compat.c | 22 ++ 6 files changed, 157 insertions(+), 96 deletions(-) rename libvips/arithmetic/{im_subtract.c => subtract.c} (75%) diff --git a/ChangeLog b/ChangeLog index 86eac91c..63d87981 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 20/8/11 started 7.27.0 - version bump for new dev cycle +- im_subtract() redone as a class 10/8/11 started 7.26.3 - don't use G_VALUE_COLLECT_INIT(), many platforms do not have a glib this diff --git a/libvips/arithmetic/Makefile.am b/libvips/arithmetic/Makefile.am index ed651793..986cac07 100644 --- a/libvips/arithmetic/Makefile.am +++ b/libvips/arithmetic/Makefile.am @@ -22,7 +22,7 @@ libarithmetic_la_SOURCES = \ im_remainder.c \ im_sign.c \ im_stats.c \ - im_subtract.c \ + subtract.c \ math.c \ arithmetic.c \ arithmetic.h \ diff --git a/libvips/arithmetic/add.c b/libvips/arithmetic/add.c index 23e1ad3b..8e4e68b1 100644 --- a/libvips/arithmetic/add.c +++ b/libvips/arithmetic/add.c @@ -108,7 +108,7 @@ * following table is used to determine the output type: * * - * im_add() type promotion + * VipsAdd type promotion * * * diff --git a/libvips/arithmetic/arithmetic.c b/libvips/arithmetic/arithmetic.c index 192fe04e..fd5d4c82 100644 --- a/libvips/arithmetic/arithmetic.c +++ b/libvips/arithmetic/arithmetic.c @@ -239,7 +239,9 @@ void vips_arithmetic_operation_init( void ) { extern GType vips_add_get_type( void ); + extern GType vips_subtract_get_type( void ); vips_add_get_type(); + vips_subtract_get_type(); } diff --git a/libvips/arithmetic/im_subtract.c b/libvips/arithmetic/subtract.c similarity index 75% rename from libvips/arithmetic/im_subtract.c rename to libvips/arithmetic/subtract.c index 09f09be8..6b07f573 100644 --- a/libvips/arithmetic/im_subtract.c +++ b/libvips/arithmetic/subtract.c @@ -1,13 +1,4 @@ -/* @(#) Subtract two images - * @(#) Images must have the same no of bands and can be of any type - * @(#) No check for overflow is carried out. - * @(#) - * @(#) int - * @(#) im_subtract( in1, in2, out) - * @(#) IMAGE *in1, *in2, *out; - * @(#) - * @(#) Returns 0 on success and -1 on error - * @(#) +/* Subtract two images * * Copyright: 1990, N. Dessipris. * @@ -38,23 +29,25 @@ * - remove separate complex case, just double size * 31/7/10 * - remove liboil + * 23/8/11 + * - rewrite as a class from add.c */ /* - 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 + Copyright (C) 1991-2005 The National Gallery + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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. + GNU General Public License for more details. - You should have received a copy of the GNU Lesser General Public License + You should have received a copy of the GNU 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 @@ -66,6 +59,10 @@ */ +/* +#define DEBUG + */ + #ifdef HAVE_CONFIG_H #include #endif /*HAVE_CONFIG_H*/ @@ -76,82 +73,18 @@ #include #include -#include + +#include "arithmetic.h" +#include "binary.h" #ifdef WITH_DMALLOC #include #endif /*WITH_DMALLOC*/ -#define LOOP( IN, OUT ) { \ - IN *p1 = (IN *) in[0]; \ - IN *p2 = (IN *) in[1]; \ - OUT *q = (OUT *) out; \ - \ - for( x = 0; x < sz; x++ ) \ - q[x] = p1[x] - p2[x]; \ -} - -static void -subtract_buffer( PEL **in, PEL *out, int width, IMAGE *im ) -{ - /* Complex just doubles the size. - */ - const int sz = width * im->Bands * - (vips_bandfmt_iscomplex( im->BandFmt ) ? 2 : 1); - - int x; - - /* Add all input types. Keep types here in sync with bandfmt_subtract[] - * below. - */ - switch( im->BandFmt ) { - case IM_BANDFMT_CHAR: LOOP( signed char, signed short ); break; - case IM_BANDFMT_UCHAR: LOOP( unsigned char, signed short ); break; - case IM_BANDFMT_SHORT: LOOP( signed short, signed int ); break; - case IM_BANDFMT_USHORT: LOOP( unsigned short, signed int ); break; - case IM_BANDFMT_INT: LOOP( signed int, signed int ); break; - case IM_BANDFMT_UINT: LOOP( unsigned int, signed int ); break; - - case IM_BANDFMT_FLOAT: - case IM_BANDFMT_COMPLEX: - LOOP( float, float ); - break; - - case IM_BANDFMT_DOUBLE: - case IM_BANDFMT_DPCOMPLEX: - LOOP( double, double ); - break; - - default: - g_assert( 0 ); - } -} - -/* Save a bit of typing. - */ -#define UC IM_BANDFMT_UCHAR -#define C IM_BANDFMT_CHAR -#define US IM_BANDFMT_USHORT -#define S IM_BANDFMT_SHORT -#define UI IM_BANDFMT_UINT -#define I IM_BANDFMT_INT -#define F IM_BANDFMT_FLOAT -#define X IM_BANDFMT_COMPLEX -#define D IM_BANDFMT_DOUBLE -#define DX IM_BANDFMT_DPCOMPLEX - -/* Type promotion for subtraction. Sign and value preserving. Make sure these - * match the case statement in subtract_buffer() above. - */ -static int bandfmt_subtract[10] = { -/* UC C US S UI I F X D DX */ - S, S, I, I, I, I, F, X, D, DX -}; - /** - * im_subtract: - * @in1: input image 1 - * @in2: input image 2 + * VipsSubtract: + * @in1: input image + * @in2: input image * @out: output image * * This operation calculates @in1 - @in2 and writes the result to @out. @@ -170,7 +103,7 @@ static int bandfmt_subtract[10] = { * following table is used to determine the output type: * *
- * im_subtract() type promotion + * VipsSubtract type promotion * * * @@ -230,11 +163,114 @@ static int bandfmt_subtract[10] = { * * Returns: 0 on success, -1 on error */ -int -im_subtract( IMAGE *in1, IMAGE *in2, IMAGE *out ) -{ - return( im__arith_binary( "im_subtract", - in1, in2, out, - bandfmt_subtract, - (im_wrapmany_fn) subtract_buffer, NULL ) ); + +typedef VipsBinary VipsSubtract; +typedef VipsBinaryClass VipsSubtractClass; + +G_DEFINE_TYPE( VipsSubtract, vips_subtract, VIPS_TYPE_BINARY ); + +#define LOOP( IN, OUT ) { \ + IN *p1 = (IN *) left; \ + IN *p2 = (IN *) right; \ + OUT *q = (OUT *) out; \ + \ + for( x = 0; x < sz; x++ ) \ + q[x] = p1[x] - p2[x]; \ +} + +static void +subtract_buffer( VipsBinary *binary, + PEL *out, PEL *left, PEL *right, int width ) +{ + VipsImage *im = binary->left_processed; + + /* Complex just doubles the size. + */ + const int sz = width * im->Bands * + (vips_band_format_iscomplex( im->BandFmt ) ? 2 : 1); + + int x; + + /* Keep types here in sync with bandfmt_subtract[] + * below. + */ + switch( im->BandFmt ) { + case IM_BANDFMT_CHAR: LOOP( signed char, signed short ); break; + case IM_BANDFMT_UCHAR: LOOP( unsigned char, signed short ); break; + case IM_BANDFMT_SHORT: LOOP( signed short, signed int ); break; + case IM_BANDFMT_USHORT: LOOP( unsigned short, signed int ); break; + case IM_BANDFMT_INT: LOOP( signed int, signed int ); break; + case IM_BANDFMT_UINT: LOOP( unsigned int, signed int ); break; + + case IM_BANDFMT_FLOAT: + case IM_BANDFMT_COMPLEX: + LOOP( float, float ); + break; + + case IM_BANDFMT_DOUBLE: + case IM_BANDFMT_DPCOMPLEX: + LOOP( double, double ); + break; + + default: + g_assert( 0 ); + } +} + +/* Save a bit of typing. + */ +#define UC IM_BANDFMT_UCHAR +#define C IM_BANDFMT_CHAR +#define US IM_BANDFMT_USHORT +#define S IM_BANDFMT_SHORT +#define UI IM_BANDFMT_UINT +#define I IM_BANDFMT_INT +#define F IM_BANDFMT_FLOAT +#define X IM_BANDFMT_COMPLEX +#define D IM_BANDFMT_DOUBLE +#define DX IM_BANDFMT_DPCOMPLEX + +/* Type promotion for subtraction. Sign and value preserving. Make sure these + * match the case statement in subtract_buffer() above. + */ +static int bandfmt_subtract[10] = { +/* UC C US S UI I F X D DX */ + S, S, I, I, I, I, F, X, D, DX +}; + +static void +vips_subtract_class_init( VipsSubtractClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS( class ); + VipsBinaryClass *bclass = VIPS_BINARY_CLASS( class ); + + object_class->nickname = "subtract"; + object_class->description = _( "subtract two images" ); + + vips_arithmetic_set_format_table( aclass, bandfmt_subtract ); + + bclass->process_line = subtract_buffer; +} + +VipsImage * +vips_subtract( VipsImage *in1, VipsImage *in2, ... ) +{ + va_list ap; + int result; + VipsImage *out; + + va_start( ap, in2 ); + result = vips_call_split( "subtract", ap, in1, in2, &out ); + va_end( ap ); + + if( result ) + return( NULL ); + + return( out ); +} + +static void +vips_subtract_init( VipsSubtract *subtract ) +{ } diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index e02a1fb8..35d69e1b 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -926,3 +926,25 @@ im_add( IMAGE *in1, IMAGE *in2, IMAGE *out ) return( 0 ); } + +int +im_subtract( IMAGE *in1, IMAGE *in2, IMAGE *out ) +{ + VipsImage *x; + + if( vips_call( "subtract", in1, in2, &x, NULL ) ) + return( -1 ); + if( im_copy( x, out ) ) { + g_object_unref( x ); + return( -1 ); + } + + /* When im_copy() is vips8'd it'll make a ref to in which will be + * junked when the copy shuts down and we can unref x directly. + * + * Until then, we have to use the "close" signal to delay the unref. + */ + vips_object_local( out, x ); + + return( 0 ); +}