diff --git a/ChangeLog b/ChangeLog index 195c7de9..60261618 100644 --- a/ChangeLog +++ b/ChangeLog @@ -32,6 +32,7 @@ - im_maxpos()/im_minpos() are partial and work for complex - im_max()/im_min() are now convenience functions - im_maxpos_avg() handles complex and multi-band images +- added im_point(), rewrite im_point_bilinear() in terms of this 25/3/09 started 7.18.0 - revised version numbers diff --git a/TODO b/TODO index a39b41cb..cdc0075b 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,11 @@ +- try + + $ vips im_point kylie110.jpg bilinear 0 0 0 + (vips:8895): GLib-GObject-WARNING **: invalid unclassed pointer in cast to + `VipsInterpolate' + Segmentation fault + + how odd - im_maxpos_vec needs gtkdoc diff --git a/libvips/arithmetic/arith_dispatch.c b/libvips/arithmetic/arith_dispatch.c index 1b4dcacf..2b0e9a07 100644 --- a/libvips/arithmetic/arith_dispatch.c +++ b/libvips/arithmetic/arith_dispatch.c @@ -319,6 +319,41 @@ static im_function avg_desc = { image_in_num_out /* Arg list */ }; +/* Args to im_point. + */ +static im_arg_desc point_args[] = { + IM_INPUT_IMAGE( "in" ), + IM_INPUT_INTERPOLATE( "interpolate" ), + IM_INPUT_DOUBLE( "x" ), + IM_INPUT_DOUBLE( "y" ), + IM_INPUT_INT( "band" ), + IM_OUTPUT_DOUBLE( "out" ) +}; + +/* Call im_point via arg vector. + */ +static int +point_vec( im_object *argv ) +{ + VipsInterpolate *interpolate = VIPS_INTERPOLATE( argv[2] ); + double x = *((double *) argv[2]); + double y = *((double *) argv[3]); + int band = *((double *) argv[4]); + + return( im_point( argv[0], interpolate, x, y, band, argv[5] ) ); +} + +/* Description of im_point. + */ +static im_function point_desc = { + "im_point", + "interpolate value at single point", + IM_FN_PIO, + point_vec, + IM_NUMBER( point_args ), + point_args +}; + /* Args to im_point_bilinear. */ static im_arg_desc point_bilinear_args[] = { @@ -1356,6 +1391,7 @@ static im_function *arith_list[] = { &asintra_desc, &atantra_desc, &avg_desc, + &point_desc, &point_bilinear_desc, &bandmean_desc, &ceil_desc, diff --git a/libvips/arithmetic/im_point_bilinear.c b/libvips/arithmetic/im_point_bilinear.c index 97169af6..2ce2274a 100644 --- a/libvips/arithmetic/im_point_bilinear.c +++ b/libvips/arithmetic/im_point_bilinear.c @@ -1,20 +1,13 @@ -/* @(#) Find the value at (x,y) in given band of image. - * @(#) Use bilinear interpolation if x or y are non-integral. - * @(#) - * @(#) int im_maxpos_vec( - * @(#) IMAGE *im, - * @(#) double x, - * @(#) double y, - * @(#) int band, - * @(#) double *val - * @(#) ); - * @(#) +/* im_point_bilinear.c * * Copyright: 2006, The Nottingham Trent University * * Author: Tom Vajzovic * * Written on: 2006-09-26 + * + * 9/9/09 + * - rewrite in terms of im_affinei() and im_avg() */ /* @@ -43,85 +36,81 @@ */ -/** HEADERS **/ - #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #include +#include + #include -#include #ifdef WITH_DMALLOC #include #endif /*WITH_DMALLOC */ +/** + * im_point: + * @im: image to read from + * @interpolate: interpolator to sample points with + * @x: x position to interpolate + * @y: y position to interpolate + * @band: band to read + * @out: return interpolated value + * + * Find the value at (@x, @y) in given band of image. + * Use bilinear interpolation if @x or @y are non-integral. + * + * See also: im_avg(), #VipsInterpolate + * + * Returns: 0 on success, -1 on error + */ +int +im_point( IMAGE *im, VipsInterpolate *interpolate, + double x, double y, int band, double *out ) +{ + IMAGE *t[2]; -/** EXPORTED FUNCTION **/ + if( band >= im->Bands || + x < 0.0 || y < 0.0 || + x > im->Xsize || y > im->Ysize ) { + im_error( "im_point_bilinear", "%s", + _( "coords outside image" ) ); + return( -1 ); + } -int im_point_bilinear( IMAGE *im, double x, double y, int band, double *val ){ -#define FUNCTION_NAME "im_point_bilinear" + if( im_open_local_array( im, t, 2, "im_point_bilinear", "p" ) || + im_extract_band( im, t[0], band ) || + im_affinei( t[0], t[1], + interpolate, + 1, 0, 0, 1, + x - floor( x ), y - floor( y ), + floor( x ), floor( y ), 1, 1 ) || + im_avg( t[1], out ) ) + return( -1 ); - double x_frac= x - (int) x; - double y_frac= y - (int) y; - Rect need= { x, y, ( x_frac ? 2 : 1 ), ( y_frac ? 2 : 1 ) }; - REGION *reg; - - if( im_pincheck( im ) ) - return -1; - - if( im-> Coding ){ - im_error( FUNCTION_NAME, "%s", _("uncoded images only") ); - return -1; - } - if( !( im_isint( im ) || im_isfloat( im ) ) ){ - im_error( FUNCTION_NAME, "%s", _("scalar images only") ); - return -1; - } - if( band >= im-> Bands || x < 0.0 || y < 0.0 || x > im-> Xsize || y > im-> Ysize ){ - im_error( FUNCTION_NAME, "%s", _("coords outside image") ); - return -1; - } - if( ! val ){ - im_error( FUNCTION_NAME, "%s", _("invalid arguments") ); - return -1; - } - - reg= im_region_create( im ); - - if( ! reg || im_prepare( reg, &need ) ) - return -1; - - if( ! im_rect_includesrect( ®-> valid, &need ) ){ - im_error( FUNCTION_NAME, "%s", _("coords outside image") ); - im_region_free( reg ); - return -1; - } - - if( x_frac ) - if( y_frac ) - *val= x_frac * y_frac * (double) IM_REGION_VALUE( reg, ((int)x + 1), ((int)y + 1), band ) - + x_frac * ( 1.0 - y_frac ) * (double) IM_REGION_VALUE( reg, ((int)x + 1), (int)y , band ) - + ( 1.0 - x_frac ) * y_frac * (double) IM_REGION_VALUE( reg, (int)x, ((int)y + 1), band ) - + ( 1.0 - x_frac ) * ( 1.0 - y_frac ) * (double) IM_REGION_VALUE( reg, (int)x, (int)y , band ); - - else - *val= x_frac * IM_REGION_VALUE( reg, ((int)x + 1), (int)y, band ) - + ( 1.0 - x_frac ) * IM_REGION_VALUE( reg, (int)x, (int)y, band ); - - else - if( y_frac ) - *val= y_frac * IM_REGION_VALUE( reg, (int)x, ((int)y + 1), band ) - + ( 1.0 - y_frac ) * IM_REGION_VALUE( reg, (int)x, (int)y , band ); - - else - *val= IM_REGION_VALUE( reg, (int)x, (int)y, band ); - - im_region_free( reg ); - - return 0; - -#undef FUNCTION_NAME + return( 0 ); +} + +/** + * im_point_bilinear: + * @im: image to read from + * @x: x position to interpolate + * @y: y position to interpolate + * @band: band to read + * @out: return interpolated value + * + * Find the value at (@x,@y) in given band of image. + * Use bilinear interpolation if @x or @y are non-integral. + * + * See also: im_avg(), im_point(). + * + * Returns: 0 on success, -1 on error + */ +int +im_point_bilinear( IMAGE *im, double x, double y, int band, double *out ) +{ + return( im_point( im, vips_interpolate_bilinear_static(), + x, y, band, out ) ); } diff --git a/libvips/include/vips/arithmetic.h b/libvips/include/vips/arithmetic.h index b2116686..97311682 100644 --- a/libvips/include/vips/arithmetic.h +++ b/libvips/include/vips/arithmetic.h @@ -60,7 +60,9 @@ int im_lintra( double a, IMAGE *in, double b, IMAGE *out ); int im_lintra_vec( int n, double *a, IMAGE *in, double *b, IMAGE *out ); int im_multiply( IMAGE *in1, IMAGE *in2, IMAGE *out ); int im_divide( IMAGE *in1, IMAGE *in2, IMAGE *out ); -int im_point_bilinear( IMAGE *im, double x, double y, int band, double *val ); +int im_point( IMAGE *im, VipsInterpolate *interpolate, + double x, double y, int band, double *out ); +int im_point_bilinear( IMAGE *im, double x, double y, int band, double *out ); int im_powtra( IMAGE *in, IMAGE *out, double e ); int im_powtra_vec( IMAGE *in, IMAGE *out, int n, double *e ); int im_exptra( IMAGE *in, IMAGE *out );