diff --git a/ChangeLog b/ChangeLog index 0e17fb59..4b73a8f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -20,6 +20,7 @@ - Python x.bandjoin(y) is now x.ibandjoin(y), sorry - oop, removed a DEBUG from buffer.c, vips is 30% faster - faster and lower-mem TIFF read +- faster bilinear interpolator 7/5/15 started 8.1.1 - oop, vips-8.0 wrapper script should be vips-8.1, thanks Danilo diff --git a/libvips/resample/interpolate.c b/libvips/resample/interpolate.c index 1bc7fde7..c8b3ac19 100644 --- a/libvips/resample/interpolate.c +++ b/libvips/resample/interpolate.c @@ -429,12 +429,13 @@ G_DEFINE_TYPE( VipsInterpolateBilinear, vips_interpolate_bilinear, */ #define BILINEAR_INT_INNER { \ - tq[z] = (c1 * tp1[z] + c2 * tp2[z] + \ - c3 * tp3[z] + c4 * tp4[z]) >> VIPS_INTERPOLATE_SHIFT; \ + tq[z] = (sc1 * tp1[z] + sc2 * tp2[z] + \ + sc3 * tp3[z] + sc4 * tp4[z]) >> VIPS_INTERPOLATE_SHIFT; \ z += 1; \ } /* Fixed-point arithmetic, no tables. + */ #define BILINEAR_INT( TYPE ) { \ TYPE * restrict tq = (TYPE *) out; \ \ @@ -443,10 +444,15 @@ G_DEFINE_TYPE( VipsInterpolateBilinear, vips_interpolate_bilinear, \ float Yd = 1.0f - Y; \ \ - int c4 = VIPS_INTERPOLATE_SCALE * (Y * X); \ - int c2 = VIPS_INTERPOLATE_SCALE * (Yd * X); \ - int c3 = VIPS_INTERPOLATE_SCALE * (Y - c4); \ - int c1 = VIPS_INTERPOLATE_SCALE * (Yd - c2); \ + float c4 = Y * X; \ + float c2 = Yd * X; \ + float c3 = Y - c4; \ + float c1 = Yd - c2; \ + \ + int sc1 = VIPS_INTERPOLATE_SCALE * c1;\ + int sc2 = VIPS_INTERPOLATE_SCALE * c2;\ + int sc3 = VIPS_INTERPOLATE_SCALE * c3;\ + int sc4 = VIPS_INTERPOLATE_SCALE * c4;\ \ const TYPE * restrict tp1 = (TYPE *) p1; \ const TYPE * restrict tp2 = (TYPE *) p2; \ @@ -456,32 +462,6 @@ G_DEFINE_TYPE( VipsInterpolateBilinear, vips_interpolate_bilinear, z = 0; \ VIPS_UNROLL( b, BILINEAR_INT_INNER ); \ } - */ - -/* Fixed-point arithmetic, no tables. - */ -#define BILINEAR_INT( TYPE ) { \ - TYPE * restrict tq = (TYPE *) out; \ - \ - float Y = y - iy; \ - float X = x - ix; \ - \ - float Yd = 1.0f - Y; \ - \ - int c4 = VIPS_INTERPOLATE_SCALE * (Y * X); \ - int c2 = VIPS_INTERPOLATE_SCALE * (Yd * X); \ - int c3 = VIPS_INTERPOLATE_SCALE * (Y - c4); \ - int c1 = VIPS_INTERPOLATE_SCALE * (Yd - c2); \ - \ - const TYPE * restrict tp1 = (TYPE *) p1; \ - const TYPE * restrict tp2 = (TYPE *) p2; \ - const TYPE * restrict tp3 = (TYPE *) p3; \ - const TYPE * restrict tp4 = (TYPE *) p4; \ - \ - for( z = 0; z < b; z++ ) \ - tq[z] = (c1 * tp1[z] + c2 * tp2[z] + \ - c3 * tp3[z] + c4 * tp4[z]) >> VIPS_INTERPOLATE_SHIFT; \ -} #define BILINEAR_FLOAT_INNER { \ tq[z] = c1 * tp1[z] + c2 * tp2[z] + \ @@ -557,8 +537,36 @@ vips_interpolate_bilinear_interpolate( VipsInterpolate *interpolate, g_assert( (int) x + 1 < VIPS_RECT_RIGHT( &in->valid ) ); g_assert( (int) y + 1 < VIPS_RECT_BOTTOM( &in->valid ) ); + unsigned char * restrict tq = (unsigned char *) out; + + float Y = y - iy; + float X = x - ix; + + float Yd = 1.0f - Y; + + float c4 = Y * X; + float c2 = Yd * X; + float c3 = Y - c4; + float c1 = Yd - c2; + + int sc1 = VIPS_INTERPOLATE_SCALE * c1; + int sc2 = VIPS_INTERPOLATE_SCALE * c2; + int sc3 = VIPS_INTERPOLATE_SCALE * c3; + int sc4 = VIPS_INTERPOLATE_SCALE * c4; + + const unsigned char * restrict tp1 = (unsigned char *) p1; + const unsigned char * restrict tp2 = (unsigned char *) p2; + const unsigned char * restrict tp3 = (unsigned char *) p3; + const unsigned char * restrict tp4 = (unsigned char *) p4; + + for( z = 0; z < b; z++ ) + tq[z] = (sc1 * tp1[z] + sc2 * tp2[z] + + sc3 * tp3[z] + sc4 * tp4[z]) >> VIPS_INTERPOLATE_SHIFT; + +/* SWITCH_INTERPOLATE( in->im->BandFmt, BILINEAR_INT, BILINEAR_FLOAT ); + */ } static void