This commit is contained in:
John Cupitt 2008-10-21 14:26:05 +00:00
parent aa79d71aa3
commit c39c35881f
3 changed files with 81 additions and 70 deletions

View File

@ -98,16 +98,16 @@ int vips_interpolate_get_window_size( VipsInterpolate *interpolate );
VIPS_TYPE_INTERPOLATE_NEAREST, VipsInterpolateNearestClass ))
typedef struct _VipsInterpolateNearest {
VipsObject parent_object;
VipsInterpolate parent_object;
} VipsInterpolateNearest;
typedef struct _VipsInterpolateNearestClass {
VipsObjectClass parent_class;
VipsInterpolateClass parent_class;
} VipsInterpolateNearestClass;
VipsInterpolateNearest *vips_interpolate_nearest_new( void );
VipsInterpolate *vips_interpolate_nearest_new( void );
GType vips_interpolate_nearest_get_type( void );
/* Convenience: return a static fast nearest, so no need to free it.
@ -145,7 +145,7 @@ VipsInterpolate *vips_interpolate_nearest_static( void );
VIPS_TYPE_INTERPOLATE_BILINEAR, VipsInterpolateBilinearClass ))
typedef struct _VipsInterpolateBilinear {
VipsObject parent_object;
VipsInterpolate parent_object;
/* Set this to not use tables ...slightly more accurate.
*/
@ -153,7 +153,7 @@ typedef struct _VipsInterpolateBilinear {
} VipsInterpolateBilinear;
typedef struct _VipsInterpolateBilinearClass {
VipsObjectClass parent_class;
VipsInterpolateClass parent_class;
/* Precalculated interpolation matricies. int (used for pel sizes up
* to short), and double (for all others). We go to scale + 1, so
@ -165,7 +165,7 @@ typedef struct _VipsInterpolateBilinearClass {
GType vips_interpolate_bilinear_get_type( void );
void vips_interpolate_bilinear_set_slow( VipsInterpolateBilinear *, gboolean );
VipsInterpolateBilinear *vips_interpolate_bilinear_new( void );
VipsInterpolate *vips_interpolate_bilinear_new( void );
/* Convenience: return a static fast bilinear, so no need to free it.
*/
@ -190,18 +190,22 @@ VipsInterpolate *vips_interpolate_bilinear_static( void );
VIPS_TYPE_INTERPOLATE_YAFR, VipsInterpolateYafrClass ))
typedef struct _VipsInterpolateYafr {
VipsObject parent_object;
VipsInterpolate parent_object;
} VipsInterpolateYafr;
typedef struct _VipsInterpolateYafrClass {
VipsObjectClass parent_class;
VipsInterpolateClass parent_class;
} VipsInterpolateYafrClass;
VipsInterpolateYafr *vips_interpolate_yafr_new( void );
VipsInterpolate *vips_interpolate_yafr_new( void );
void vips_interpolate_yafr_set_thing( VipsInterpolateYafr *, double thing );
/* Convenience: return a static default yafr, so no need to free it.
*/
VipsInterpolate *vips_interpolate_yafr_static( void );
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -109,13 +109,13 @@ vips_interpolate_get_type( void )
if( !type ) {
static const GTypeInfo info = {
sizeof( VipsObjectClass ),
sizeof( VipsInterpolateClass ),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) vips_interpolate_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof( VipsObject ),
sizeof( VipsInterpolate ),
32, /* n_preallocs */
(GInstanceInitFunc) vips_interpolate_init,
};
@ -229,13 +229,13 @@ vips_interpolate_nearest_get_type( void )
if( !type ) {
static const GTypeInfo info = {
sizeof( VipsObjectClass ),
sizeof( VipsInterpolateNearestClass ),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) vips_interpolate_nearest_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof( VipsObject ),
sizeof( VipsInterpolateNearest ),
32, /* n_preallocs */
(GInstanceInitFunc) vips_interpolate_nearest_init,
};
@ -247,10 +247,11 @@ vips_interpolate_nearest_get_type( void )
return( type );
}
VipsInterpolateNearest *
VipsInterpolate *
vips_interpolate_nearest_new( void )
{
return( g_object_new( VIPS_TYPE_INTERPOLATE_NEAREST, NULL ) );
return( VIPS_INTERPOLATE( g_object_new(
VIPS_TYPE_INTERPOLATE_NEAREST, NULL ) ) );
}
/* Convenience: return a static nearest you don't need to free.
@ -261,8 +262,7 @@ vips_interpolate_nearest_static( void )
static VipsInterpolate *interpolate = NULL;
if( !interpolate )
interpolate =
VIPS_INTERPOLATE( vips_interpolate_nearest_new() );
interpolate = vips_interpolate_nearest_new();
return( interpolate );
}
@ -270,6 +270,11 @@ vips_interpolate_nearest_static( void )
/* VipsInterpolateBilinear class
*/
/* in this class, name vars in the 2x2 grid as eg.
* p1 p2
* p3 p4
*/
#ifdef DEBUG
static void
vips_interpolate_bilinear_finalize( GObject *gobject )
@ -297,19 +302,11 @@ vips_interpolate_bilinear_finalize( GObject *gobject )
const int c3 = (m4 * m1) >> VIPS_INTERPOLATE_SHIFT; \
const int c4 = (m4 * m2) >> VIPS_INTERPOLATE_SHIFT; \
\
/* var points to \
* p1 (x_int, y_int) \
* p2 (x_int+1, y_int) \
* p3 (x_int, y_int+1) \
* p4 (x_int+1, y_int+1) \
*/ \
const TYPE *tp1 = (TYPE *) p1; \
const TYPE *tp2 = (TYPE *) p2; \
const TYPE *tp3 = (TYPE *) p3; \
const TYPE *tp4 = (TYPE *) p4; \
\
/* Interpolate each band. \
*/ \
for( z = 0; z < b; z++ ) \
tq[z] = (c1 * tp1[z] + c2 * tp2[z] + \
c3 * tp3[z] + c4 * tp4[z]) >> VIPS_INTERPOLATE_SHIFT; \
@ -330,19 +327,11 @@ vips_interpolate_bilinear_finalize( GObject *gobject )
const double c3 = m4 * m1; \
const double c4 = m4 * m2; \
\
/* var points to \
* p1 (x_int, y_int) \
* p2 (x_int+1, y_int) \
* p3 (x_int, y_int+1) \
* p4 (x_int+1, y_int+1) \
*/ \
const TYPE *tp1 = (TYPE *) p1; \
const TYPE *tp2 = (TYPE *) p2; \
const TYPE *tp3 = (TYPE *) p3; \
const TYPE *tp4 = (TYPE *) p4; \
\
/* Interpolate each band. \
*/ \
for( z = 0; z < b; z++ ) \
tq[z] = c1 * tp1[z] + c2 * tp2[z] + \
c3 * tp3[z] + c4 * tp4[z]; \
@ -353,19 +342,11 @@ vips_interpolate_bilinear_finalize( GObject *gobject )
#define BILINEAR_SLOW( TYPE ) { \
TYPE *tq = (TYPE *) q; \
\
/* var points to \
* p1 (x_int, y_int) \
* p2 (x_int+1, y_int) \
* p3 (x_int, y_int+1) \
* p4 (x_int+1, y_int+1) \
*/ \
const TYPE *tp1 = (TYPE *) p1; \
const TYPE *tp2 = (TYPE *) p2; \
const TYPE *tp3 = (TYPE *) p3; \
const TYPE *tp4 = (TYPE *) p4; \
\
/* Interpolate each band. \
*/ \
for( z = 0; z < b; z++ ) \
tq[z] = c1 * tp1[z] + c2 * tp2[z] + \
c3 * tp3[z] + c4 * tp4[z]; \
@ -433,19 +414,13 @@ vips_interpolate_bilinear_interpolate( VipsInterpolate *interpolate,
*/
const double c1 = Xd * Yd;
const double c2 = X * Yd;
const double c3 = X * Y;
const double c4 = Xd * Y;
const double c3 = Xd * Y;
const double c4 = X * Y;
/* var points to
* p1 (x_int, y_int)
* p2 (x_int+1, y_int)
* p3 (x_int, y_int+1)
* p4 (x_int+1, y_int+1)
*/
const PEL *p1 = (PEL *) IM_REGION_ADDR( in, xi, yi );
const PEL *p2 = p1 + ps;
const PEL *p3 = p1 + ls;
const PEL *p4 = p1 + ls + ps;
const PEL *p4 = p3 + ps;
SWITCH_INTERPOLATE( in->im->BandFmt,
BILINEAR_SLOW, BILINEAR_SLOW );
@ -471,20 +446,39 @@ vips_interpolate_bilinear_interpolate( VipsInterpolate *interpolate,
const int in_x_int = sxi >> VIPS_TRANSFORM_SHIFT;
const int in_y_int = syi >> VIPS_TRANSFORM_SHIFT;
/* var points to
* p1 (x_int, y_int)
* p2 (x_int+1, y_int)
* p3 (x_int, y_int+1)
* p4 (x_int+1, y_int+1)
*/
const PEL *p1 = (PEL *)
IM_REGION_ADDR( in, in_x_int, in_y_int );
const PEL *p2 = p1 + ps;
const PEL *p3 = p1 + ls;
const PEL *p4 = p1 + ls + ps;
const PEL *p4 = p3 + ps;
{
unsigned char *tq = (unsigned char *) q;
const int m1 = class->matrix_int[xi][0];
const int m2 = class->matrix_int[xi][1];
const int m3 = class->matrix_int[yi][0];
const int m4 = class->matrix_int[yi][1];
const int c1 = (m3 * m1) >> VIPS_INTERPOLATE_SHIFT;
const int c2 = (m3 * m2) >> VIPS_INTERPOLATE_SHIFT;
const int c3 = (m4 * m1) >> VIPS_INTERPOLATE_SHIFT;
const int c4 = (m4 * m2) >> VIPS_INTERPOLATE_SHIFT;
const unsigned char *tp1 = (unsigned char *) p1;
const unsigned char *tp2 = (unsigned char *) p2;
const unsigned char *tp3 = (unsigned char *) p3;
const unsigned char *tp4 = (unsigned char *) p4;
for( z = 0; z < b; z++ )
tq[z] = (c1 * tp1[z] + c2 * tp2[z] +
c3 * tp3[z] + c4 * tp4[z]) >> VIPS_INTERPOLATE_SHIFT;
}
/*
SWITCH_INTERPOLATE( in->im->BandFmt,
BILINEAR_INT, BILINEAR_FLOAT );
*/
}
}
@ -510,8 +504,10 @@ vips_interpolate_bilinear_class_init( VipsInterpolateBilinearClass *class )
/* Calculate the interpolation matricies.
*/
for( x = 0; x < VIPS_TRANSFORM_SCALE + 1; x++ ) {
const double c1 = (double) x / VIPS_TRANSFORM_SCALE;
const double c2 = 1.0 - c1;
/* At x == 0, we want to give all the weight to the LH pixel.
*/
const double c2 = (double) x / VIPS_TRANSFORM_SCALE;
const double c1 = 1.0 - c2;
class->matrix_double[x][0] = c1;
class->matrix_double[x][1] = c2;
@ -539,13 +535,13 @@ vips_interpolate_bilinear_get_type( void )
if( !type ) {
static const GTypeInfo info = {
sizeof( VipsObjectClass ),
sizeof( VipsInterpolateBilinearClass ),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) vips_interpolate_bilinear_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof( VipsObject ),
sizeof( VipsInterpolateBilinear ),
32, /* n_preallocs */
(GInstanceInitFunc) vips_interpolate_bilinear_init,
};
@ -564,13 +560,13 @@ vips_interpolate_bilinear_set_slow( VipsInterpolateBilinear *bilinear,
bilinear->slow = slow;
}
VipsInterpolateBilinear *
VipsInterpolate *
vips_interpolate_bilinear_new( void )
{
return( g_object_new( VIPS_TYPE_INTERPOLATE_BILINEAR, NULL ) );
return( VIPS_INTERPOLATE( g_object_new(
VIPS_TYPE_INTERPOLATE_BILINEAR, NULL ) ) );
}
/* Convenience: return a static bilinear you don't need to free.
*/
VipsInterpolate *
@ -579,8 +575,7 @@ vips_interpolate_bilinear_static( void )
static VipsInterpolate *interpolate = NULL;
if( !interpolate )
interpolate =
VIPS_INTERPOLATE( vips_interpolate_bilinear_new() );
interpolate = vips_interpolate_bilinear_new();
return( interpolate );
}

View File

@ -553,13 +553,21 @@ affinei_vec( im_object *argv )
VipsInterpolate *interpolate;
int result;
switch( interpol ) {
case 1:
interpolate = vips_interpolate_nearest_static();
interpolate = vips_interpolate_nearest_new();
break;
case 2:
interpolate = vips_interpolate_bilinear_static();
interpolate = vips_interpolate_bilinear_new();
break;
case 3:
interpolate = vips_interpolate_bilinear_new();
vips_interpolate_bilinear_set_slow(
VIPS_INTERPOLATE_BILINEAR( interpolate ), TRUE );
break;
default:
@ -567,8 +575,12 @@ affinei_vec( im_object *argv )
return( -1 );
}
return( im_affinei( argv[0], argv[1], interpolate,
a, b, c, d, dx, dy, x, y, w, h ) );
result = im_affinei( argv[0], argv[1], interpolate,
a, b, c, d, dx, dy, x, y, w, h );
g_object_unref( interpolate );
return( result );
}
/* Description of im_affinei.