diff --git a/TODO b/TODO index a95bdc25..bcdbab03 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,18 @@ +- optional output args are broken + + vips_min( im, &min, + "x", &xpos, + "y", &ypos, + NULL ); + + tries to set "x" and "y" during vips_operation_set_valist_optional(), + instead it should read them during output arg readout phase + + + + + + - is our C API too awkward? we'll need diff --git a/libvips/arithmetic/Makefile.am b/libvips/arithmetic/Makefile.am index 1839e524..2d5b3650 100644 --- a/libvips/arithmetic/Makefile.am +++ b/libvips/arithmetic/Makefile.am @@ -15,7 +15,6 @@ libarithmetic_la_SOURCES = \ im_maxpos.c \ im_maxpos_vec.c \ im_measure.c \ - im_minpos.c \ im_multiply.c \ im_point_bilinear.c \ im_remainder.c \ @@ -24,6 +23,7 @@ libarithmetic_la_SOURCES = \ statistic.c \ statistic.h \ avg.c \ + min.c \ subtract.c \ math.c \ arithmetic.c \ diff --git a/libvips/arithmetic/arithmetic.c b/libvips/arithmetic/arithmetic.c index 47fa462d..256684d9 100644 --- a/libvips/arithmetic/arithmetic.c +++ b/libvips/arithmetic/arithmetic.c @@ -240,9 +240,11 @@ vips_arithmetic_operation_init( void ) extern GType vips_add_get_type( void ); extern GType vips_subtract_get_type( void ); extern GType vips_avg_get_type( void ); + extern GType vips_min_get_type( void ); vips_add_get_type(); vips_subtract_get_type(); vips_avg_get_type(); + vips_min_get_type(); } diff --git a/libvips/arithmetic/avg.c b/libvips/arithmetic/avg.c index 97642f07..3a91c730 100644 --- a/libvips/arithmetic/avg.c +++ b/libvips/arithmetic/avg.c @@ -170,20 +170,18 @@ vips_avg_stop( VipsStatistic *statistic, void *seq ) #define LOOP( TYPE ) { \ TYPE *p = (TYPE *) in; \ \ - for( x = 0; x < sz; x++ ) \ - m += p[x]; \ + for( i = 0; i < sz; i++ ) \ + m += p[i]; \ } #define CLOOP( TYPE ) { \ TYPE *p = (TYPE *) in; \ \ - for( x = 0; x < sz; x++ ) { \ - double mod, re, im; \ + for( i = 0; i < sz; i++ ) { \ + double mod; \ \ - re = p[0]; \ - im = p[1]; \ + mod = p[0] * p[0] + p[1] * p[1]; \ p += 2; \ - mod = re * re + im * im; \ \ m += mod; \ } \ @@ -192,21 +190,22 @@ vips_avg_stop( VipsStatistic *statistic, void *seq ) /* Loop over region, accumulating a sum in *tmp. */ static int -vips_avg_scan( VipsStatistic *statistic, void *seq, void *in, int n ) +vips_avg_scan( VipsStatistic *statistic, void *seq, + int x, int y, void *in, int n ) { - const VipsImage *im = statistic->input; - const int sz = n * vips_image_get_bands( im ); + const VipsImage *input = statistic->input; + const int sz = n * vips_image_get_bands( input ); double *sum = (double *) seq; - int x; + int i; double m; m = *sum; /* Now generate code for all types. */ - switch( vips_image_get_format( im ) ) { + switch( vips_image_get_format( input ) ) { case VIPS_FORMAT_UCHAR: LOOP( unsigned char ); break; case VIPS_FORMAT_CHAR: LOOP( signed char ); break; case VIPS_FORMAT_USHORT: LOOP( unsigned short ); break; diff --git a/libvips/arithmetic/im_minpos.c b/libvips/arithmetic/im_minpos.c deleted file mode 100644 index 82ce27d5..00000000 --- a/libvips/arithmetic/im_minpos.c +++ /dev/null @@ -1,262 +0,0 @@ -/* im_minpos.c - * - * Copyright: 1990, J. Cupitt - * - * Author: J. Cupitt - * Written on: 02/05/1990 - * Modified on : 18/03/1991, N. Dessipris - * 23/11/92 JC - * - correct result for more than 1 band now. - * 23/7/93 JC - * - im_incheck() added - * 20/6/95 JC - * - now returns double for value, like im_max() - * 4/9/09 - * - gtkdoc comment - * 8/9/09 - * - rewrite, from im_maxpos() - */ - -/* - - 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 DEBUG - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /*HAVE_CONFIG_H*/ -#include - -#include -#include -#include - -#include -#include - -#ifdef WITH_DMALLOC -#include -#endif /*WITH_DMALLOC*/ - -/* A position and minimum. - */ -typedef struct _Minpos { - int xpos; - int ypos; - double min; -} Minpos; - -/* New sequence value. - */ -static void * -minpos_start( IMAGE *in, void *a, void *b ) -{ - Minpos *global_minpos = (Minpos *) b; - Minpos *minpos; - - if( !(minpos = IM_NEW( NULL, Minpos )) ) - return( NULL ); - *minpos = *global_minpos; - - return( (void *) minpos ); -} - -/* Merge the sequence value back into the per-call state. - */ -static int -minpos_stop( void *seq, void *a, void *b ) -{ - Minpos *global_minpos = (Minpos *) b; - Minpos *minpos = (Minpos *) seq; - - /* Merge. - */ - if( minpos->min < global_minpos->min ) - *global_minpos = *minpos; - - im_free( seq ); - - return( 0 ); -} - -#define LOOP( TYPE ) { \ - TYPE *p = (TYPE *) in; \ - TYPE m; \ - \ - m = min; \ - \ - for( x = 0; x < sz; x++ ) { \ - TYPE v = p[x]; \ - \ - if( v < m ) { \ - m = v; \ - xpos = r->left + x / reg->im->Bands; \ - ypos = r->top + y; \ - } \ - } \ - \ - min = m; \ -} - -#define CLOOP( TYPE ) { \ - TYPE *p = (TYPE *) in; \ - \ - for( x = 0; x < sz; x++ ) { \ - double mod, re, im; \ - \ - re = p[0]; \ - im = p[1]; \ - p += 2; \ - mod = re * re + im * im; \ - \ - if( mod < min ) { \ - min = mod; \ - xpos = r->left + x / reg->im->Bands; \ - ypos = r->top + y; \ - } \ - } \ -} - -/* Loop over region, adding to seq. - */ -static int -minpos_scan( REGION *reg, void *seq, void *a, void *b, gboolean *stop ) -{ - const Rect *r = ®->valid; - const int sz = IM_REGION_N_ELEMENTS( reg ); - Minpos *minpos = (Minpos *) seq; - - int x, y; - double min; - int xpos, ypos; - - xpos = minpos->xpos; - ypos = minpos->ypos; - min = minpos->min; - - for( y = 0; y < r->height; y++ ) { - PEL *in = (PEL *) IM_REGION_ADDR( reg, r->left, r->top + y ); - - switch( reg->im->BandFmt ) { - case IM_BANDFMT_UCHAR: LOOP( unsigned char ); break; - case IM_BANDFMT_CHAR: LOOP( signed char ); break; - case IM_BANDFMT_USHORT: LOOP( unsigned short ); break; - case IM_BANDFMT_SHORT: LOOP( signed short ); break; - case IM_BANDFMT_UINT: LOOP( unsigned int ); break; - case IM_BANDFMT_INT: LOOP( signed int ); break; - case IM_BANDFMT_FLOAT: LOOP( float ); break; - case IM_BANDFMT_DOUBLE: LOOP( double ); break; - case IM_BANDFMT_COMPLEX: CLOOP( float ); break; - case IM_BANDFMT_DPCOMPLEX: CLOOP( double ); break; - - default: - g_assert( 0 ); - } - } - - minpos->xpos = xpos; - minpos->ypos = ypos; - minpos->min = min; - - return( 0 ); -} - -/** - * im_minpos: - * @in: image to search - * @xpos: returned x position of minimum - * @ypos: returned y position of minimum - * @out: returned pixel value at that position - * - * Function to find the minimum of an image. Works for any - * image type. Returns a double and the location of min. For complex images, - * finds the pixel with the smallest modulus. - * - * See also: im_maxpos(), im_min(), im_stats(), im_maxpos_avg(). - * - * Returns: 0 on success, -1 on error - */ -int -im_minpos( IMAGE *in, int *xpos, int *ypos, double *out ) -{ - Minpos *global_minpos; - - if( im_pincheck( in ) || - im_check_uncoded( "im_minpos", in ) ) - return( -1 ); - - if( !(global_minpos = IM_NEW( in, Minpos )) ) - return( -1 ); - if( im__value( in, &global_minpos->min ) ) - return( -1 ); - global_minpos->xpos = 0; - global_minpos->ypos = 0; - - /* We use square mod for scanning, for speed. - */ - if( vips_bandfmt_iscomplex( in->BandFmt ) ) - global_minpos->min *= global_minpos->min; - - if( vips_sink( in, minpos_start, minpos_scan, minpos_stop, - in, global_minpos ) ) - return( -1 ); - - /* Back to modulus. - */ - if( vips_bandfmt_iscomplex( in->BandFmt ) ) - global_minpos->min = sqrt( global_minpos->min ); - - if( xpos ) - *xpos = global_minpos->xpos; - if( ypos ) - *ypos = global_minpos->ypos; - if( out ) - *out = global_minpos->min; - - return( 0 ); -} - -/** - * im_min: - * @in: input #IMAGE - * @out: output double - * - * Finds the the minimum value of image #in and returns it at the - * location pointed by @out. If input is complex, the min modulus - * is returned. im_min() finds the minimum of all bands: if you - * want to find the minimum of each band separately, use im_stats(). - * - * See also: im_minpos(), im_min(), im_stats(). - * - * Returns: 0 on success, -1 on error - */ -int -im_min( IMAGE *in, double *out ) -{ - return( im_minpos( in, NULL, NULL, out ) ); -} diff --git a/libvips/arithmetic/min.c b/libvips/arithmetic/min.c new file mode 100644 index 00000000..d9507f53 --- /dev/null +++ b/libvips/arithmetic/min.c @@ -0,0 +1,329 @@ +/* find image minimum + * + * Copyright: 1990, J. Cupitt + * + * Author: J. Cupitt + * Written on: 02/05/1990 + * Modified on : 18/03/1991, N. Dessipris + * 23/11/92 JC + * - correct result for more than 1 band now. + * 23/7/93 JC + * - im_incheck() added + * 20/6/95 JC + * - now returns double for value, like im_max() + * 4/9/09 + * - gtkdoc comment + * 8/9/09 + * - rewrite, from im_maxpos() + * 30/8/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 DEBUG + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include +#include +#include + +#include +#include + +#include "statistic.h" + +#ifdef WITH_DMALLOC +#include +#endif /*WITH_DMALLOC*/ + +/** + * VipsMin: + * @in: input #VipsImage + * @out: output pixel minimum + * + * This operation finds the minimum value in an image. + * + * If the image contains several minimum values, only the first one found is + * returned. + * + * It operates on all + * bands of the input image: use im_stats() if you need to find an + * minimum for each band. For complex images, return the minimum modulus. + * + * See also: #VipsAvg, im_stats(), im_bandmean(), im_deviate(), im_rank() + */ + +/* Properties. + */ +enum { + PROP_OUTPUT = 1, + PROP_X, /* Position of minimum */ + PROP_Y, + PROP_LAST +}; + +typedef struct _VipsMin { + VipsStatistic parent_instance; + + gboolean set; /* FALSE means no value yet */ + + /* The current miniumum. When scanning complex images, we keep the + * square of the modulus here and do a single sqrt() right at the end. + */ + double min; + + /* And its position. + */ + int x, y; +} VipsMin; + +typedef VipsStatisticClass VipsMinClass; + +G_DEFINE_TYPE( VipsMin, vips_min, VIPS_TYPE_STATISTIC ); + +static int +vips_min_build( VipsObject *object ) +{ + VipsStatistic *statistic = VIPS_STATISTIC( object ); + VipsImage *input = statistic->input; + VipsMin *min = (VipsMin *) object; + + double m; + + if( VIPS_OBJECT_CLASS( vips_min_parent_class )->build( object ) ) + return( -1 ); + + /* For speed we accumulate min^2 for complex. + */ + m = min->min; + if( vips_bandfmt_iscomplex( vips_image_get_format( input ) ) ) + m = sqrt( m ); + + /* We have to set the props via g_object_set() to stop vips + * complaining they are unset. + */ + g_object_set( min, + "out", m, + "x", min->x, + "y", min->y, + NULL ); + + return( 0 ); +} + +/* New sequence value. Make a private VipsMin for this thread. + */ +static void * +vips_min_start( VipsStatistic *statistic ) +{ + VipsMin *global = (VipsMin *) statistic; + VipsMin *min; + + if( !(min = VIPS_NEW( NULL, VipsMin )) ) + return( NULL ); + *min = *global; + + return( (void *) min ); +} + +/* Merge the sequence value back into the per-call state. + */ +static int +vips_min_stop( VipsStatistic *statistic, void *seq ) +{ + VipsMin *global = (VipsMin *) statistic; + VipsMin *min = (VipsMin *) seq; + + if( !global->set || + min->min < global->min ) { + global->min = min->min; + global->x = min->x; + global->y = min->y; + global->set = TRUE; + } + + vips_free( min ); + + return( 0 ); +} + +#define LOOP( TYPE ) { \ + TYPE *p = (TYPE *) in; \ + TYPE m; \ + \ + if( min->set ) \ + m = min->min; \ + else \ + m = p[0]; \ + \ + for( i = 0; i < sz; i++ ) { \ + if( p[i] < m ) { \ + m = p[i]; \ + min->x = x + i / bands; \ + min->y = y; \ + } \ + } \ + \ + min->min = m; \ + min->set = TRUE; \ +} + +#define CLOOP( TYPE ) { \ + TYPE *p = (TYPE *) in; \ + double m; \ + \ + if( min->set ) \ + m = min->min; \ + else \ + m = p[0] * p[0] + p[1] * p[1]; \ + \ + for( i = 0; i < sz; i++ ) { \ + double mod; \ + \ + mod = p[0] * p[0] + p[1] * p[1]; \ + p += 2; \ + \ + if( mod < m ) { \ + m = mod; \ + min->x = x + i / bands; \ + min->y = y; \ + } \ + } \ + \ + min->min = m; \ + min->set = TRUE; \ +} + +/* Loop over region, adding to seq. + */ +static int +vips_min_scan( VipsStatistic *statistic, void *seq, + int x, int y, void *in, int n ) +{ + VipsMin *min = (VipsMin *) seq; + const VipsImage *input = statistic->input; + const int bands = vips_image_get_bands( input ); + const int sz = n * bands; + + int i; + + switch( vips_image_get_format( input ) ) { + case IM_BANDFMT_UCHAR: LOOP( unsigned char ); break; + case IM_BANDFMT_CHAR: LOOP( signed char ); break; + case IM_BANDFMT_USHORT: LOOP( unsigned short ); break; + case IM_BANDFMT_SHORT: LOOP( signed short ); break; + case IM_BANDFMT_UINT: LOOP( unsigned int ); break; + case IM_BANDFMT_INT: LOOP( signed int ); break; + case IM_BANDFMT_FLOAT: LOOP( float ); break; + case IM_BANDFMT_DOUBLE: LOOP( double ); break; + case IM_BANDFMT_COMPLEX: CLOOP( float ); break; + case IM_BANDFMT_DPCOMPLEX: CLOOP( double ); break; + + default: + g_assert( 0 ); + } + + return( 0 ); +} + +static void +vips_min_class_init( VipsMinClass *class ) +{ + GObjectClass *gobject_class = (GObjectClass *) class; + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsStatisticClass *sclass = VIPS_STATISTIC_CLASS( class ); + + GParamSpec *pspec; + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "min"; + object_class->description = _( "find image minimum" ); + object_class->build = vips_min_build; + + sclass->start = vips_min_start; + sclass->scan = vips_min_scan; + sclass->stop = vips_min_stop; + + pspec = g_param_spec_double( "out", "Output", + _( "Output value" ), + -G_MAXDOUBLE, + G_MAXDOUBLE, + 0.0, + G_PARAM_READWRITE ); + g_object_class_install_property( gobject_class, + PROP_OUTPUT, pspec ); + vips_object_class_install_argument( object_class, pspec, + VIPS_ARGUMENT_REQUIRED_OUTPUT | VIPS_ARGUMENT_APPEND, + G_STRUCT_OFFSET( VipsMin, min ) ); + + pspec = g_param_spec_int( "x", "x", + _( "Horizontal position of minimum" ), + 0, 1000000, 0, + G_PARAM_READWRITE ); + g_object_class_install_property( gobject_class, + PROP_X, pspec ); + vips_object_class_install_argument( object_class, pspec, + VIPS_ARGUMENT_OPTIONAL_OUTPUT, + G_STRUCT_OFFSET( VipsMin, x ) ); + + pspec = g_param_spec_int( "y", "y", + _( "Vertical position of minimum" ), + 0, 1000000, 0, + G_PARAM_READWRITE ); + g_object_class_install_property( gobject_class, + PROP_Y, pspec ); + vips_object_class_install_argument( object_class, pspec, + VIPS_ARGUMENT_OPTIONAL_OUTPUT, + G_STRUCT_OFFSET( VipsMin, y ) ); +} + +static void +vips_min_init( VipsMin *min ) +{ +} + +int +vips_min( VipsImage *in, double *out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_call_split( "min", ap, in, out ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/arithmetic/statistic.c b/libvips/arithmetic/statistic.c index c616bd95..d2381454 100644 --- a/libvips/arithmetic/statistic.c +++ b/libvips/arithmetic/statistic.c @@ -88,11 +88,17 @@ vips_statistic_scan( VipsRegion *region, p = (PEL *) IM_REGION_ADDR( region, r->left, r->top ); for( y = 0; y < r->height; y++ ) { - if( class->scan( statistic, seq, p, r->width ) ) + if( class->scan( statistic, + seq, r->left, r->top + y, p, r->width ) ) return( -1 ); p += lsk; } + /* If we've requested stop, pass the message on. + */ + if( statistic->stop ) + *stop = TRUE; + return( 0 ); } diff --git a/libvips/arithmetic/statistic.h b/libvips/arithmetic/statistic.h index d71d6509..9bf064ff 100644 --- a/libvips/arithmetic/statistic.h +++ b/libvips/arithmetic/statistic.h @@ -55,8 +55,8 @@ typedef struct _VipsStatistic VipsStatistic; typedef struct _VipsStatisticClass VipsStatisticClass; typedef void *(*VipsStatisticStartFn)( VipsStatistic *statistic ); -typedef int (*VipsStatisticScanFn)( VipsStatistic *statistic, void *seq, - void *p, int n ); +typedef int (*VipsStatisticScanFn)( VipsStatistic *statistic, + void *seq, int x, int y, void *p, int n ); typedef int (*VipsStatisticStopFn)( VipsStatistic *statistic, void *seq ); struct _VipsStatistic { @@ -66,6 +66,10 @@ struct _VipsStatistic { */ VipsImage *input; + /* Set this to stop computation early. + */ + gboolean stop; + /* Client data for the subclass. */ void *a; diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index 3ff2130d..2ef34dfb 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -963,3 +963,15 @@ int im_generate( VipsImage *im, return( vips_image_generate( im, start, (VipsGenerateFn) generate, stop, a, b ) ); } + +int +im_minpos( IMAGE *in, int *xpos, int *ypos, double *out ) +{ + return( vips_min( in, out, "x", xpos, "y", ypos, NULL ) ); +} + +int +im_min( IMAGE *in, double *out ) +{ + return( im_minpos( in, NULL, NULL, out ) ); +} diff --git a/libvips/include/vips/arithmetic.h b/libvips/include/vips/arithmetic.h index 5fd3efb9..b70108ec 100644 --- a/libvips/include/vips/arithmetic.h +++ b/libvips/include/vips/arithmetic.h @@ -40,6 +40,7 @@ extern "C" { VipsImage *vips_add( VipsImage *in1, VipsImage *in2, ... ); VipsImage *vips_subtract( VipsImage *in1, VipsImage *in2, ... ); int vips_avg( VipsImage *in, double *out, ... ); +int vips_min( VipsImage *in, double *out, ... ); @@ -50,11 +51,8 @@ DOUBLEMASK *im_measure_area( VipsImage *im, int *sel, int nsel, const char *name ); DOUBLEMASK *im_stats( VipsImage *in ); int im_max( VipsImage *in, double *out ); -int im_min( VipsImage *in, double *out ); -int im_avg( VipsImage *in, double *out ); int im_deviate( VipsImage *in, double *out ); int im_maxpos( VipsImage *in, int *xpos, int *ypos, double *out ); -int im_minpos( VipsImage *in, int *xpos, int *ypos, double *out ); int im_maxpos_avg( VipsImage *im, double *xpos, double *ypos, double *out ); int im_maxpos_vec( VipsImage *im, int *xpos, int *ypos, double *maxima, int n ); int im_minpos_vec( VipsImage *im, int *xpos, int *ypos, double *minima, int n ); diff --git a/libvips/include/vips/object.h b/libvips/include/vips/object.h index c5c2df87..bbc42627 100644 --- a/libvips/include/vips/object.h +++ b/libvips/include/vips/object.h @@ -77,7 +77,9 @@ VIPS_ARGUMENT_REQUIRED_INPUT Eg. the "left" argument for an add operation VIPS_ARGUMENT_OPTIONAL_INPUT Eg. the "caption" for an object -VIPS_ARGUMENT_OUTPUT Eg. the "result" of an add operation +VIPS_ARGUMENT_REQUIRED_OUTPUT Eg. the "result" of an add operation + +VIPS_ARGUMENT_OPTIONAL_OUTPUT Eg. the x pos of the image minimum Other combinations are used internally, eg. supplying the cast-table for an arithmetic operation @@ -101,6 +103,11 @@ VIPS_ARGUMENT_OUTPUT Eg. the "result" of an add operation VIPS_ARGUMENT_CONSTRUCT | \ VIPS_ARGUMENT_SET_ONCE) +#define VIPS_ARGUMENT_OPTIONAL_OUTPUT \ + (VIPS_ARGUMENT_OUTPUT | \ + VIPS_ARGUMENT_CONSTRUCT | \ + VIPS_ARGUMENT_SET_ONCE) + /* Keep one of these for every argument. */ typedef struct _VipsArgument { diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index 12421d1e..d4b05fd1 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -490,6 +490,9 @@ int im_wrapmany( VipsImage **in, VipsImage *out, int im_add( VipsImage *in1, VipsImage *in2, VipsImage *out ); int im_subtract( VipsImage *in1, VipsImage *in2, VipsImage *out ); +int im_min( VipsImage *in, double *out ); +int im_minpos( VipsImage *in, int *xpos, int *ypos, double *out ); +int im_avg( VipsImage *in, double *out ); #ifdef __cplusplus } diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index 027e67f0..d6df050b 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -702,6 +702,7 @@ vips_object_set_property( GObject *gobject, } #ifdef DEBUG +#endif /*DEBUG*/ { char *str_value; @@ -711,7 +712,6 @@ vips_object_set_property( GObject *gobject, printf( ".%s = %s\n", g_param_spec_get_name( pspec ), str_value ); g_free( str_value ); } -#endif /*DEBUG*/ g_assert( ((VipsArgument *) argument_class)->pspec == pspec ); g_assert( ((VipsArgument *) argument_instance)->pspec == pspec );