new bilinear
This commit is contained in:
parent
213cb019de
commit
ae31832180
@ -7,6 +7,7 @@
|
|||||||
- updated README
|
- updated README
|
||||||
- don't use tables for bilinear on float data for a small speedup (thanks
|
- don't use tables for bilinear on float data for a small speedup (thanks
|
||||||
Nicolas Robidoux)
|
Nicolas Robidoux)
|
||||||
|
- no tables for uchar either, about a 15% speedup (thank Nicolas)
|
||||||
|
|
||||||
30/11/10 started 7.24.0
|
30/11/10 started 7.24.0
|
||||||
- bump for new stable
|
- bump for new stable
|
||||||
|
20
TODO
20
TODO
@ -1,23 +1,3 @@
|
|||||||
- bilinear tweaks need sorting out
|
|
||||||
|
|
||||||
time vips im_affinei wtc.v wtc2.v bilinear 0.97 0 0 0.97 0 0 0 0 10000 10000
|
|
||||||
|
|
||||||
fastest of 4 runs, user time
|
|
||||||
|
|
||||||
7.24 - 4.0s
|
|
||||||
j-monday - 3.5s
|
|
||||||
n-20:59 - 4.0s
|
|
||||||
n-21:14 - 3.9s
|
|
||||||
n-22:20 - 4.1s
|
|
||||||
n-00:06 - 3.8s
|
|
||||||
n-14:26 - 4.1s
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- fits save
|
|
||||||
|
|
||||||
- lazy fits load
|
|
||||||
|
|
||||||
|
|
||||||
- im_conv()/im_morph() could have more than 10 programs? try 20 and see if we
|
- im_conv()/im_morph() could have more than 10 programs? try 20 and see if we
|
||||||
still have a speedup
|
still have a speedup
|
||||||
|
@ -326,46 +326,14 @@ typedef VipsInterpolateClass VipsInterpolateBilinearClass;
|
|||||||
G_DEFINE_TYPE( VipsInterpolateBilinear, vips_interpolate_bilinear,
|
G_DEFINE_TYPE( VipsInterpolateBilinear, vips_interpolate_bilinear,
|
||||||
VIPS_TYPE_INTERPOLATE );
|
VIPS_TYPE_INTERPOLATE );
|
||||||
|
|
||||||
/* Precalculated interpolation matricies, only for int types.
|
|
||||||
* We go to scale + 1 so
|
|
||||||
* we can round-to-nearest safely.
|
|
||||||
*/
|
|
||||||
static int vips_bilinear_matrixi
|
|
||||||
[VIPS_TRANSFORM_SCALE + 1][VIPS_TRANSFORM_SCALE + 1][4];
|
|
||||||
|
|
||||||
/* in this class, name vars in the 2x2 grid as eg.
|
/* in this class, name vars in the 2x2 grid as eg.
|
||||||
* p1 p2
|
* p1 p2
|
||||||
* p3 p4
|
* p3 p4
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Interpolate a section ... int8/16 types, lookup tables for interpolation
|
/* Fixed-point arithmetic, no tables.
|
||||||
* factors, fixed-point arithmetic.
|
|
||||||
*/
|
*/
|
||||||
#define BILINEAR_INT( TYPE ) { \
|
#define BILINEAR_INT( TYPE ) { \
|
||||||
TYPE *tq = (TYPE *) out; \
|
|
||||||
\
|
|
||||||
const int six = sx & (VIPS_TRANSFORM_SCALE * 2 - 1); \
|
|
||||||
const int siy = sy & (VIPS_TRANSFORM_SCALE * 2 - 1); \
|
|
||||||
\
|
|
||||||
const int tx = (six + 1) >> 1; \
|
|
||||||
const int ty = (siy + 1) >> 1; \
|
|
||||||
\
|
|
||||||
const int c1 = vips_bilinear_matrixi[tx][ty][0]; \
|
|
||||||
const int c2 = vips_bilinear_matrixi[tx][ty][1]; \
|
|
||||||
const int c3 = vips_bilinear_matrixi[tx][ty][2]; \
|
|
||||||
const int c4 = vips_bilinear_matrixi[tx][ty][3]; \
|
|
||||||
\
|
|
||||||
const TYPE *tp1 = (TYPE *) p1; \
|
|
||||||
const TYPE *tp2 = (TYPE *) p2; \
|
|
||||||
const TYPE *tp3 = (TYPE *) p3; \
|
|
||||||
const TYPE *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_INT2( TYPE ) { \
|
|
||||||
TYPE *tq = (TYPE *) out; \
|
TYPE *tq = (TYPE *) out; \
|
||||||
\
|
\
|
||||||
const int X = (x - ix) * 128; \
|
const int X = (x - ix) * 128; \
|
||||||
@ -384,118 +352,6 @@ static int vips_bilinear_matrixi
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* n-20:59
|
|
||||||
*/
|
|
||||||
#define BILINEAR_INT3( TYPE ) { \
|
|
||||||
TYPE *tq = (TYPE *) out; \
|
|
||||||
\
|
|
||||||
const int X = (x - ix) * 128; \
|
|
||||||
const int Y = (y - iy) * 128; \
|
|
||||||
\
|
|
||||||
const TYPE *tp1 = (TYPE *) p1; \
|
|
||||||
const TYPE *tp2 = (TYPE *) p2; \
|
|
||||||
const TYPE *tp3 = (TYPE *) p3; \
|
|
||||||
const TYPE *tp4 = (TYPE *) p4; \
|
|
||||||
\
|
|
||||||
for( z = 0; z < b; z++ ) { \
|
|
||||||
const int d = tp2[z] - tp1[z]; \
|
|
||||||
\
|
|
||||||
tq[z] = ( ( ( ( ( ( tp4[z] - tp3[z] - d ) * X ) >> 7 ) + tp3[z] - tp1[z]) * Y + d * X) >> 7) + tp1[z]; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* n-21:14
|
|
||||||
*/
|
|
||||||
#define BILINEAR_INT4( TYPE ) { \
|
|
||||||
TYPE *tq = (TYPE *) out; \
|
|
||||||
\
|
|
||||||
const int X = (x - ix) * 128; \
|
|
||||||
const int Y = (y - iy) * 128; \
|
|
||||||
\
|
|
||||||
const TYPE *tp1 = (TYPE *) p1; \
|
|
||||||
const TYPE *tp2 = (TYPE *) p2; \
|
|
||||||
const TYPE *tp3 = (TYPE *) p3; \
|
|
||||||
const TYPE *tp4 = (TYPE *) p4; \
|
|
||||||
\
|
|
||||||
for( z = 0; z < b; z++ ) { \
|
|
||||||
const int d21 = tp2[z] - tp1[z]; \
|
|
||||||
const int d31 = tp3[z] - tp1[z]; \
|
|
||||||
const int d34 = tp3[z] - tp4[z]; \
|
|
||||||
\
|
|
||||||
tq[z] = ( ( d21 * X + ( d31 - ( ( (d21+d34) * X ) >> 7)) * Y) >> 7) + tp1[z]; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* n-22:20
|
|
||||||
*/
|
|
||||||
#define BILINEAR_INT5( TYPE ) { \
|
|
||||||
TYPE *tq = (TYPE *) out; \
|
|
||||||
\
|
|
||||||
const int X = (x - ix) * 128; \
|
|
||||||
const int Y = (y - iy) * 128; \
|
|
||||||
\
|
|
||||||
const TYPE *tp1 = (TYPE *) p1; \
|
|
||||||
const TYPE *tp2 = (TYPE *) p2; \
|
|
||||||
const TYPE *tp3 = (TYPE *) p3; \
|
|
||||||
const TYPE *tp4 = (TYPE *) p4; \
|
|
||||||
\
|
|
||||||
const int X128 = X * 128; \
|
|
||||||
\
|
|
||||||
for( z = 0; z < b; z++ ) { \
|
|
||||||
const int d21 = tp2[z] - tp1[z]; \
|
|
||||||
const int d31 = tp3[z] - tp1[z]; \
|
|
||||||
const int d34 = tp3[z] - tp4[z]; \
|
|
||||||
\
|
|
||||||
tq[z] = ( ( d21 * X128 + ( d31 * 128 - ( ( (d21+d34) * X ))) * Y) >> 14) + tp1[z]; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* n-00:06
|
|
||||||
*/
|
|
||||||
#define BILINEAR_INT6( TYPE ) { \
|
|
||||||
TYPE *tq = (TYPE *) out; \
|
|
||||||
\
|
|
||||||
const int X = (x - ix) * 128; \
|
|
||||||
const int Y = (y - iy) * 128; \
|
|
||||||
\
|
|
||||||
const TYPE *tp1 = (TYPE *) p1; \
|
|
||||||
const TYPE *tp2 = (TYPE *) p2; \
|
|
||||||
const TYPE *tp3 = (TYPE *) p3; \
|
|
||||||
const TYPE *tp4 = (TYPE *) p4; \
|
|
||||||
\
|
|
||||||
const int X128 = X * 128; \
|
|
||||||
\
|
|
||||||
for( z = 0; z < b; z++ ) { \
|
|
||||||
const int d21 = tp2[z] - tp1[z]; \
|
|
||||||
const int d31 = tp3[z] - tp1[z]; \
|
|
||||||
const int d34 = tp3[z] - tp4[z]; \
|
|
||||||
\
|
|
||||||
tq[z] = ( tp1[z] << 14 + d21 * X128 + ( d31 * 128 - ( ( (d21+d34) * X ))) * Y) >> 14; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* n-14:26
|
|
||||||
*/
|
|
||||||
#define BILINEAR_INT7( TYPE ) { \
|
|
||||||
TYPE *tq = (TYPE *) out; \
|
|
||||||
\
|
|
||||||
const int X = (x - ix) * 128; \
|
|
||||||
const int Y = (y - iy) * 128; \
|
|
||||||
\
|
|
||||||
const TYPE *tp1 = (TYPE *) p1; \
|
|
||||||
const TYPE *tp2 = (TYPE *) p2; \
|
|
||||||
const TYPE *tp3 = (TYPE *) p3; \
|
|
||||||
const TYPE *tp4 = (TYPE *) p4; \
|
|
||||||
\
|
|
||||||
for( z = 0; z < b; z++ ) { \
|
|
||||||
const int d21 = tp2[z] - tp1[z]; \
|
|
||||||
const int d31 = tp3[z] - tp1[z]; \
|
|
||||||
const int d34 = tp3[z] - tp4[z]; \
|
|
||||||
\
|
|
||||||
tq[z] = tp1[z] + ( ( ( ( d31 << 7 ) - ( ( (d21+d34) * X ))) * Y + ( d21 * ( X << 7 ) )) >> 14); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Interpolate a pel ... int32 and float types, no tables, float
|
/* Interpolate a pel ... int32 and float types, no tables, float
|
||||||
* arithmetic.
|
* arithmetic.
|
||||||
*/
|
*/
|
||||||
@ -551,26 +407,6 @@ vips_interpolate_bilinear_interpolate( VipsInterpolate *interpolate,
|
|||||||
const int ls = IM_REGION_LSKIP( in );
|
const int ls = IM_REGION_LSKIP( in );
|
||||||
const int b = in->im->Bands;
|
const int b = in->im->Bands;
|
||||||
|
|
||||||
/* We want ((int)x), but the tables versions needs to find a mask
|
|
||||||
* index quickly from the residual. Calculate both.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Find the mask index. We round-to-nearest, so we need to generate
|
|
||||||
* indexes in 0 to VIPS_TRANSFORM_SCALE, 2^n + 1 values. We multiply
|
|
||||||
* by 2 more than we need to, add one, mask, then shift down again to
|
|
||||||
* get the extra range.
|
|
||||||
const int sx = x * VIPS_TRANSFORM_SCALE * 2;
|
|
||||||
const int sy = y * VIPS_TRANSFORM_SCALE * 2;
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* We want ((int)x) ... avoid repeating this double -> int conversion
|
|
||||||
* by just shifting sx down.
|
|
||||||
const int ix = sx >> (VIPS_TRANSFORM_SHIFT + 1);
|
|
||||||
const int iy = sy >> (VIPS_TRANSFORM_SHIFT + 1);
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
const int ix = (int) x;
|
const int ix = (int) x;
|
||||||
const int iy = (int) y;
|
const int iy = (int) y;
|
||||||
|
|
||||||
@ -582,7 +418,7 @@ vips_interpolate_bilinear_interpolate( VipsInterpolate *interpolate,
|
|||||||
int z;
|
int z;
|
||||||
|
|
||||||
SWITCH_INTERPOLATE( in->im->BandFmt,
|
SWITCH_INTERPOLATE( in->im->BandFmt,
|
||||||
BILINEAR_INT2, BILINEAR_FLOAT );
|
BILINEAR_INT, BILINEAR_FLOAT );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -591,44 +427,12 @@ vips_interpolate_bilinear_class_init( VipsInterpolateBilinearClass *class )
|
|||||||
VipsObjectClass *object_class = VIPS_OBJECT_CLASS( class );
|
VipsObjectClass *object_class = VIPS_OBJECT_CLASS( class );
|
||||||
VipsInterpolateClass *interpolate_class =
|
VipsInterpolateClass *interpolate_class =
|
||||||
(VipsInterpolateClass *) class;
|
(VipsInterpolateClass *) class;
|
||||||
int x, y;
|
|
||||||
|
|
||||||
object_class->nickname = "bilinear";
|
object_class->nickname = "bilinear";
|
||||||
object_class->description = _( "Bilinear interpolation" );
|
object_class->description = _( "Bilinear interpolation" );
|
||||||
|
|
||||||
interpolate_class->interpolate = vips_interpolate_bilinear_interpolate;
|
interpolate_class->interpolate = vips_interpolate_bilinear_interpolate;
|
||||||
interpolate_class->window_size = 2;
|
interpolate_class->window_size = 2;
|
||||||
|
|
||||||
/* Calculate the interpolation matricies.
|
|
||||||
*/
|
|
||||||
for( x = 0; x < VIPS_TRANSFORM_SCALE + 1; x++ )
|
|
||||||
for( y = 0; y < VIPS_TRANSFORM_SCALE + 1; y++ ) {
|
|
||||||
double X, Y, Xd, Yd;
|
|
||||||
double c1, c2, c3, c4;
|
|
||||||
|
|
||||||
/* Interpolation errors.
|
|
||||||
*/
|
|
||||||
X = (double) x / VIPS_TRANSFORM_SCALE;
|
|
||||||
Y = (double) y / VIPS_TRANSFORM_SCALE;
|
|
||||||
Xd = 1.0 - X;
|
|
||||||
Yd = 1.0 - Y;
|
|
||||||
|
|
||||||
/* Weights.
|
|
||||||
*/
|
|
||||||
c1 = Xd * Yd;
|
|
||||||
c2 = X * Yd;
|
|
||||||
c3 = Xd * Y;
|
|
||||||
c4 = X * Y;
|
|
||||||
|
|
||||||
vips_bilinear_matrixi[x][y][0] =
|
|
||||||
c1 * VIPS_INTERPOLATE_SCALE;
|
|
||||||
vips_bilinear_matrixi[x][y][1] =
|
|
||||||
c2 * VIPS_INTERPOLATE_SCALE;
|
|
||||||
vips_bilinear_matrixi[x][y][2] =
|
|
||||||
c3 * VIPS_INTERPOLATE_SCALE;
|
|
||||||
vips_bilinear_matrixi[x][y][3] =
|
|
||||||
c4 * VIPS_INTERPOLATE_SCALE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user