diff --git a/ChangeLog b/ChangeLog index a0583dce..4736532c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,7 +7,7 @@ im_lintra(), im_lintra_vec(), im_black(), im_rot90, im_rot180(), im_rot270() im_sintra(), im_costra(), im_tantra(), im_asintra(), im_acostra(), im_atantra(), im_exptra(), im_exp10tra(), im_logtra(), im_log10tra(), - im_abs() + im_abs(), im_sign() redone as classes - added argument priorites to help control arg ordering - generate has a 'stop' param to signal successful early termination diff --git a/libvips/arithmetic/Makefile.am b/libvips/arithmetic/Makefile.am index 75a444a5..9527c551 100644 --- a/libvips/arithmetic/Makefile.am +++ b/libvips/arithmetic/Makefile.am @@ -16,7 +16,7 @@ libarithmetic_la_SOURCES = \ im_multiply.c \ im_point_bilinear.c \ im_remainder.c \ - im_sign.c \ + sign.c \ im_stats.c \ statistic.c \ statistic.h \ diff --git a/libvips/arithmetic/abs.c b/libvips/arithmetic/abs.c index 45bf65e9..fa9ba742 100644 --- a/libvips/arithmetic/abs.c +++ b/libvips/arithmetic/abs.c @@ -70,16 +70,18 @@ #include "arithmetic.h" #include "unary.h" -/** +/** * VipsAbs: * @in: input #VipsImage * @out: output #VipsImage * - * For unsigned formats, this operation calculates (max - @in), eg. (255 - - * @in) for uchar. For signed and float formats, this operation calculates (-1 - * * @in). + * This operation finds the absolute value of an image. It does a copy for + * unsigned integer types, negate for negative values in + * signed integer types, fabs(3) for + * float types, and calculate modulus for complex + * types. * - * See also: im_lintra(). + * See also: im_sign(). * * Returns: 0 on success, -1 on error */ diff --git a/libvips/arithmetic/im_sign.c b/libvips/arithmetic/im_sign.c deleted file mode 100644 index c6875ef9..00000000 --- a/libvips/arithmetic/im_sign.c +++ /dev/null @@ -1,142 +0,0 @@ -/* im_sign.c - * - * 9/7/02 JC - * - from im_cmulnorm - * 9/9/09 - * - gtkdoc, tidies - */ - -/* - - 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 - -#include - -#define CSIGN( IN, OUT ) { \ - IN *p = (IN *) in; \ - OUT *q = (OUT *) out; \ - int x; \ - \ - for( x = 0; x < n; x++ ) { \ - IN re = p[0]; \ - IN im = p[1]; \ - double fac = sqrt( re * re + im * im ); \ - \ - p += 2; \ - \ - if( fac == 0.0 ) { \ - q[0] = 0.0; \ - q[1] = 0.0; \ - } \ - else { \ - q[0] = re / fac; \ - q[1] = im / fac; \ - } \ - \ - q += 2; \ - } \ -} - -#define SIGN( IN, OUT ) { \ - IN *p = (IN *) in; \ - OUT *q = (OUT *) out; \ - int x; \ - \ - for( x = 0; x < n; x++ ) { \ - IN v = p[x]; \ - \ - if( v > 0 ) \ - q[x] = 1; \ - else if( v == 0 ) \ - q[x] = 0; \ - else \ - q[x] = -1; \ - } \ -} - -/* sign buffer processor. - */ -static void -sign_gen( void *in, void *out, int w, IMAGE *im ) -{ - int n = w * im->Bands; - - switch( im->BandFmt ) { - case IM_BANDFMT_UCHAR: SIGN( unsigned char, signed char ); break; - case IM_BANDFMT_CHAR: SIGN( signed char, signed char ); break; - case IM_BANDFMT_USHORT: SIGN( unsigned short, signed char ); break; - case IM_BANDFMT_SHORT: SIGN( signed short, signed char ); break; - case IM_BANDFMT_UINT: SIGN( unsigned int, signed char ); break; - case IM_BANDFMT_INT: SIGN( signed int, signed char ); break; - case IM_BANDFMT_FLOAT: SIGN( float, signed char ); break; - case IM_BANDFMT_DOUBLE: SIGN( double, signed char ); break; - case IM_BANDFMT_COMPLEX: CSIGN( float, float ); break; - case IM_BANDFMT_DPCOMPLEX: CSIGN( double, double ); break; - - default: - g_assert( 0 ); - } -} - -/** - * im_sign: - * @in: input image - * @out: output image - * - * Finds the unit vector in the direction of the pixel value. For non-complex - * images, it returns a signed char image with values -1, 0, and 1 for negative, - * zero and positive pixels. For complex images, it returns a - * complex normalised to length 1. - * - * See also: im_abs(), im_cmulnorm(), im_c2amph(). - * - * Returns: 0 on success, -1 on error - */ -int -im_sign( IMAGE *in, IMAGE *out ) -{ - if( im_piocheck( in, out ) || - im_check_uncoded( "im_sign", in ) || - im_cp_desc( out, in ) ) - return( -1 ); - - if( !vips_bandfmt_iscomplex( in->BandFmt ) ) - out->BandFmt = IM_BANDFMT_CHAR; - - if( im_wrapone( in, out, (im_wrapone_fn) sign_gen, in, NULL ) ) - return( -1 ); - - return( 0 ); -} diff --git a/libvips/arithmetic/sign.c b/libvips/arithmetic/sign.c new file mode 100644 index 00000000..b449b6fe --- /dev/null +++ b/libvips/arithmetic/sign.c @@ -0,0 +1,186 @@ +/* im_sign.c + * + * 9/7/02 JC + * - from im_cmulnorm + * 9/9/09 + * - gtkdoc, tidies + * 6/11/11 + * - redone as a class + */ + +/* + + 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 General Public License for more details. + + 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 + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +/* +#define DEBUG + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include +#include +#include + +#include + +#include "arithmetic.h" +#include "unary.h" + +/** + * VipsSign: + * @in: input image + * @out: output image + * + * Finds the unit vector in the direction of the pixel value. For non-complex + * images, it returns a signed char image with values -1, 0, and 1 for negative, + * zero and positive pixels. For complex images, it returns a + * complex normalised to length 1. + * + * See also: #VipsAbs. + */ + +typedef VipsUnary VipsSign; +typedef VipsUnaryClass VipsSignClass; + +G_DEFINE_TYPE( VipsSign, vips_sign, VIPS_TYPE_UNARY ); + +#define CSIGN( TYPE ) { \ + TYPE *p = (TYPE *) in; \ + TYPE *q = (TYPE *) out; \ + int x; \ + \ + for( x = 0; x < sz; x++ ) { \ + TYPE re = p[0]; \ + TYPE im = p[1]; \ + double fac = sqrt( re * re + im * im ); \ + \ + p += 2; \ + \ + if( fac == 0.0 ) { \ + q[0] = 0.0; \ + q[1] = 0.0; \ + } \ + else { \ + q[0] = re / fac; \ + q[1] = im / fac; \ + } \ + \ + q += 2; \ + } \ +} + +#define SIGN( TYPE ) { \ + TYPE *p = (TYPE *) in; \ + signed char *q = (signed char *) out; \ + int x; \ + \ + for( x = 0; x < sz; x++ ) { \ + TYPE v = p[x]; \ + \ + if( v > 0 ) \ + q[x] = 1; \ + else if( v == 0 ) \ + q[x] = 0; \ + else \ + q[x] = -1; \ + } \ +} + +static void +vips_sign_buffer( VipsArithmetic *arithmetic, PEL *out, PEL **in, int width ) +{ + VipsImage *im = arithmetic->ready[0]; + int sz = width * im->Bands; + + switch( im->BandFmt ) { + case VIPS_FORMAT_UCHAR: SIGN( unsigned char ); break; + case VIPS_FORMAT_CHAR: SIGN( signed char ); break; + case VIPS_FORMAT_USHORT: SIGN( unsigned short ); break; + case VIPS_FORMAT_SHORT: SIGN( signed short ); break; + case VIPS_FORMAT_UINT: SIGN( unsigned int ); break; + case VIPS_FORMAT_INT: SIGN( signed int ); break; + case VIPS_FORMAT_FLOAT: SIGN( float ); break; + case VIPS_FORMAT_DOUBLE: SIGN( double ); break; + case VIPS_FORMAT_COMPLEX: CSIGN( float ); break; + case VIPS_FORMAT_DPCOMPLEX: CSIGN( double ); break; + + default: + g_assert( 0 ); + } +} + +/* Save a bit of typing. + */ +#define UC VIPS_FORMAT_UCHAR +#define C VIPS_FORMAT_CHAR +#define US VIPS_FORMAT_USHORT +#define S VIPS_FORMAT_SHORT +#define UI VIPS_FORMAT_UINT +#define I VIPS_FORMAT_INT +#define F VIPS_FORMAT_FLOAT +#define X VIPS_FORMAT_COMPLEX +#define D VIPS_FORMAT_DOUBLE +#define DX VIPS_FORMAT_DPCOMPLEX + +static const VipsBandFormat vips_bandfmt_sign[10] = { +/* UC C US S UI I F X D DX */ + C, C, C, C, C, C, C, X, C, DX +}; + +static void +vips_sign_class_init( VipsSignClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS( class ); + + object_class->nickname = "sign"; + object_class->description = _( "unit vector of pixel" ); + + vips_arithmetic_set_format_table( aclass, vips_bandfmt_sign ); + + aclass->process_line = vips_sign_buffer; +} + +static void +vips_sign_init( VipsSign *sign ) +{ +} + +int +vips_sign( VipsImage *in, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "sign", ap, in, out ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index f49214f8..5f7a66fe 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -1392,6 +1392,23 @@ im_invert( IMAGE *in, IMAGE *out ) return( 0 ); } +int +im_sign( IMAGE *in, IMAGE *out ) +{ + VipsImage *t; + + if( vips_sign( in, &t, + NULL ) ) + return( -1 ); + if( vips_image_write( t, out ) ) { + g_object_unref( t ); + return( -1 ); + } + g_object_unref( t ); + + return( 0 ); +} + int im_abs( IMAGE *in, IMAGE *out ) { diff --git a/libvips/include/vips/arithmetic.h b/libvips/include/vips/arithmetic.h index e11efe79..f676cae7 100644 --- a/libvips/include/vips/arithmetic.h +++ b/libvips/include/vips/arithmetic.h @@ -86,6 +86,8 @@ int vips_math( VipsImage *in, VipsImage **out, __attribute__((sentinel)); int vips_abs( VipsImage *in, VipsImage **out, ... ) __attribute__((sentinel)); +int vips_sign( VipsImage *in, VipsImage **out, ... ) + __attribute__((sentinel)); @@ -110,7 +112,6 @@ int im_remainder_vec( VipsImage *in, VipsImage *out, int n, double *c ); int im_remainderconst( VipsImage *in, VipsImage *out, double c ); int im_recomb( VipsImage *in, VipsImage *out, DOUBLEMASK *recomb ); -int im_sign( VipsImage *in, VipsImage *out ); int im_floor( VipsImage *in, VipsImage *out ); int im_rint( VipsImage *in, VipsImage *out ); int im_ceil( VipsImage *in, VipsImage *out ); diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index 2d9f4311..998664cc 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -529,6 +529,7 @@ int im_invert( VipsImage *in, VipsImage *out ); int im_lintra( double a, VipsImage *in, double b, VipsImage *out ); int im_lintra_vec( int n, double *a, VipsImage *in, double *b, VipsImage *out ); int im_abs( VipsImage *in, VipsImage *out ); +int im_sign( VipsImage *in, VipsImage *out ); int im_sintra( VipsImage *in, VipsImage *out ); int im_costra( VipsImage *in, VipsImage *out );