diff --git a/TODO b/TODO index 84791ff5..db7eeb02 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,19 @@ +- built with O2, experiment with + + - floorf() + - try commenting out the thing that calculates cardinal_one etc. to get + an idea of the possible speedup with LUTs + - time for uchar vs. vips-bilinear and new bilinear and float yafr + - can we build and time gegl? + + + add a vips_interpolate_get_method() which returns the function pointer, use + that in the inner loop instead of function dispatch + + done ... try editing im_affinei and time + + + - vips_object_print, set_name etc. need writing - im_buf_t -> VipsBuf diff --git a/include/vips/interpolate.h b/include/vips/interpolate.h index 214fa9ab..51d10d34 100644 --- a/include/vips/interpolate.h +++ b/include/vips/interpolate.h @@ -56,14 +56,20 @@ typedef struct _VipsInterpolate { } VipsInterpolate; +/* An interpolation function. This is a class method, but we have a lookup + * function for it to speed up dispatch. + */ +typedef void (*VipsInterpolateMethod)( VipsInterpolate *, + REGION *out, REGION *in, + int out_x, int out_y, double in_x, double in_y ); + typedef struct _VipsInterpolateClass { VipsObjectClass parent_class; /* Write to pixel out(x,y), interpolating from in(x,y). The caller has * to set the regions up. */ - void (*interpolate)( VipsInterpolate *, REGION *out, REGION *in, - int out_x, int out_y, double in_x, double in_y ); + VipsInterpolateMethod interpolate; /* This interpolator needs a window this many pixels across and down. */ @@ -77,6 +83,7 @@ typedef struct _VipsInterpolateClass { GType vips_interpolate_get_type( void ); void vips_interpolate( VipsInterpolate *interpolate, REGION *out, REGION *in, int out_x, int out_y, double in_x, double in_y ); +VipsInterpolateMethod vips_interpolate_get_method( VipsInterpolate * ); int vips_interpolate_get_window_size( VipsInterpolate *interpolate ); /* Nearest class starts. diff --git a/libsrc/mosaicing/im_affinei.c b/libsrc/mosaicing/im_affinei.c index d3fe8c87..398bfc84 100644 --- a/libsrc/mosaicing/im_affinei.c +++ b/libsrc/mosaicing/im_affinei.c @@ -213,6 +213,8 @@ affinei_gen( REGION *or, void *seq, void *a, void *b ) const int window_size = vips_interpolate_get_window_size( affine->interpolate ); const int half_window_size = window_size / 2; + VipsInterpolateMethod interpolate = + vips_interpolate_get_method( affine->interpolate ); /* Output area for this call. */ @@ -322,7 +324,8 @@ affinei_gen( REGION *or, void *seq, void *a, void *b ) q[z] = 0; } else { - vips_interpolate( affine->interpolate, or, ir, + interpolate( affine->interpolate, + or, ir, x, y, ix, iy ); } diff --git a/libsrc/mosaicing/interpolate.c b/libsrc/mosaicing/interpolate.c index 693e32ac..5d61df1c 100644 --- a/libsrc/mosaicing/interpolate.c +++ b/libsrc/mosaicing/interpolate.c @@ -142,6 +142,19 @@ vips_interpolate( VipsInterpolate *interpolate, REGION *out, REGION *in, class->interpolate( interpolate, out, in, out_x, out_y, in_x, in_y ); } +/* As above, but return the function pointer. Use this to cache method + * dispatch. + */ +VipsInterpolateMethod +vips_interpolate_get_method( VipsInterpolate *interpolate ) +{ + VipsInterpolateClass *class = VIPS_INTERPOLATE_GET_CLASS( interpolate ); + + g_assert( class->interpolate ); + + return( class->interpolate ); +} + /* Get this interpolator's required window size. */ int diff --git a/libsrc/mosaicing/yafrtest.cpp b/libsrc/mosaicing/yafrtest.cpp index 06c6839d..0c270e18 100644 --- a/libsrc/mosaicing/yafrtest.cpp +++ b/libsrc/mosaicing/yafrtest.cpp @@ -1,4 +1,4 @@ -/* vipsinterpolateyafr_test ... yarf as a vips interpolate class +/* vipsinterpolateyafr_test ... yafr as a vips interpolate class */ /* @@ -118,8 +118,8 @@ static VipsInterpolateClass *vips_interpolate_yafr_test_parent_class = NULL; * the interior of the bichromatic region. */ -/* Pointers to write to / read from, how much to add to move right a pixel, - * how much to add to move down a line. +/* Pointers to write to / read from, channel number, number of channels, + * how many bytes to add to move down a line. */ /* T is the type of pixels we are reading and writing. @@ -128,12 +128,12 @@ static VipsInterpolateClass *vips_interpolate_yafr_test_parent_class = NULL; * for others we need float or even double. */ -template static inline void +template static void inline catrom_yafr_test( - PEL *out, PEL *in, + PEL *pout, const PEL *pin, const int channels, - const int pixels_per_buffer_row, - const float sharpening, + const int lskip, + const double sharpening, const float cardinal_one, const float cardinal_two, @@ -205,26 +205,27 @@ catrom_yafr_test( * consideration. The in pointer is assumed * to point to uno_one when catrom_yafr_test is entered. */ + const int pel_skip = lskip / sizeof( T ); - const T uno_one = in[ 0 ]; - const T uno_two = in[ channels]; - const T uno_thr = in[ 2 * channels]; - const T uno_fou = in[ 3 * channels]; + const T uno_one = in[0 ]; + const T uno_two = in[ channels ]; + const T uno_thr = in[2 * channels ]; + const T uno_fou = in[3 * channels ]; - const T dos_one = in[ pixels_per_buffer_row * channels]; - const T dos_two = in[(1 + pixels_per_buffer_row) * channels]; - const T dos_thr = in[(2 + pixels_per_buffer_row) * channels]; - const T dos_fou = in[(3 + pixels_per_buffer_row) * channels]; + const T dos_one = in[ pel_skip]; + const T dos_two = in[ channels + pel_skip]; + const T dos_thr = in[2 * channels + pel_skip]; + const T dos_fou = in[3 * channels + pel_skip]; - const T tre_one = in[ 2 * pixels_per_buffer_row * channels]; - const T tre_two = in[(1 + 2 * pixels_per_buffer_row) * channels]; - const T tre_thr = in[(2 + 2 * pixels_per_buffer_row) * channels]; - const T tre_fou = in[(3 + 2 * pixels_per_buffer_row) * channels]; + const T tre_one = in[ 2 * pel_skip]; + const T tre_two = in[ channels + 2 * pel_skip]; + const T tre_thr = in[2 * channels + 2 * pel_skip]; + const T tre_fou = in[3 * channels + 2 * pel_skip]; - const T qua_one = in[ 3 * pixels_per_buffer_row * channels]; - const T qua_two = in[(1 + 3 * pixels_per_buffer_row) * channels]; - const T qua_thr = in[(2 + 3 * pixels_per_buffer_row) * channels]; - const T qua_fou = in[(3 + 3 * pixels_per_buffer_row) * channels]; + const T qua_one = in[ 3 * pel_skip]; + const T qua_two = in[ channels + 3 * pel_skip]; + const T qua_thr = in[2 * channels + 3 * pel_skip]; + const T qua_fou = in[3 * channels + 3 * pel_skip]; /* * Computation of the YAFR_TEST correction: @@ -548,8 +549,8 @@ vips_interpolate_yafr_test_interpolate( VipsInterpolate *interpolate, /* Pel size and line size. */ const int channels = in->im->Bands; - const int pixels_per_buffer_row = - IM_REGION_LSKIP( in ) / (sizeof( float ) * channels); + const int lskip = IM_REGION_LSKIP( in ); + const int esize = IM_IMAGE_SIZEOF_ELEMENT( in->im ); /* Where we write the result. */ @@ -558,8 +559,8 @@ vips_interpolate_yafr_test_interpolate( VipsInterpolate *interpolate, /* Put this in a macro to save some typing. */ #define CALL(T, D) \ - catrom_yafr_test(q + z, p + z, \ - channels, pixels_per_buffer_row, \ + catrom_yafr_test(q + z * esize, p + z * esize, \ + channels, lskip, \ yafr_test->sharpening, \ cardinal_one, \ cardinal_two, \ @@ -612,21 +613,22 @@ vips_interpolate_yafr_test_interpolate( VipsInterpolate *interpolate, case IM_BANDFMT_DOUBLE: for( int z = 0; z < channels; z++ ) - CALL( float, float ); + CALL( double, double ); break; - + default: + break; } } static void -vips_interpolate_yafr_test_class_init( VipsInterpolateYafrTestClass *class ) +vips_interpolate_yafr_test_class_init( VipsInterpolateYafrTestClass *iclass ) { VipsInterpolateClass *interpolate_class = - VIPS_INTERPOLATE_CLASS( class ); + VIPS_INTERPOLATE_CLASS( iclass ); vips_interpolate_yafr_test_parent_class = - g_type_class_peek_parent( class ); + VIPS_INTERPOLATE_CLASS( g_type_class_peek_parent( iclass ) ); interpolate_class->interpolate = vips_interpolate_yafr_test_interpolate; interpolate_class->window_size = 4; @@ -644,7 +646,7 @@ vips_interpolate_yafr_test_init( VipsInterpolateYafrTest *yafr_test ) } GType -vips_interpolate_yafr_test_get_type( void ) +vips_interpolate_yafr_test_get_type() { static GType type = 0; @@ -662,7 +664,8 @@ vips_interpolate_yafr_test_get_type( void ) }; type = g_type_register_static( VIPS_TYPE_INTERPOLATE, - "VipsInterpolateYafrTest", &info, 0 ); + "VipsInterpolateYafrTest", &info, + (GTypeFlags) 0 ); } return( type );