use corner convention everywhere
all interpolators use corner convention
This commit is contained in:
parent
823068a282
commit
43d69e74e7
@ -22,8 +22,6 @@
|
||||
- vipsthumbnail -o allows absolute file names
|
||||
- much better exif handling for jpg images (thanks Gary)
|
||||
- preserve jpeg app13 (photoshop ipct)
|
||||
- nearest neighbour goes back to round down ... round to nearest caused a
|
||||
range of annoying problems, such as strange half-pixels along edges
|
||||
- vips_max() / _min() track the top n maxima / minima
|
||||
- deprecate im_maxpos_avg(): too specialised to be worth maintaining
|
||||
- deprecate im_linreg(): easily done by combining other operators
|
||||
@ -32,6 +30,8 @@
|
||||
- added vips_bandbool(), with vips_bandand(), _bandor(), _bandeor() as
|
||||
convenience functions
|
||||
- added scRGB colourspace, linear light float space with sRGB primaries
|
||||
- all interpolators use corner convention ... we had round-to-nearest in
|
||||
several of them before, causing a range of annoying problems
|
||||
|
||||
14/11/12 started 7.30.6
|
||||
- capture tiff warnings earlier
|
||||
|
2
TODO
2
TODO
@ -4,7 +4,7 @@
|
||||
|
||||
dx/dy displace output
|
||||
|
||||
- switch to corner convention everywhere
|
||||
- make affinei into a class
|
||||
|
||||
|
||||
|
||||
|
@ -105,7 +105,7 @@ G_DEFINE_TYPE( VipsInterpolateBicubic, vips_interpolate_bicubic,
|
||||
*/
|
||||
template <typename T, int min_value, int max_value>
|
||||
static void inline
|
||||
bicubic_int_tab( void *pout, const PEL *pin,
|
||||
bicubic_int_tab( void *pout, const VipsPel *pin,
|
||||
const int bands, const int lskip,
|
||||
const int *cx, const int *cy )
|
||||
{
|
||||
@ -173,7 +173,7 @@ bicubic_int_tab( void *pout, const PEL *pin,
|
||||
*/
|
||||
template <typename T>
|
||||
static void inline
|
||||
bicubic_float_tab( void *pout, const PEL *pin,
|
||||
bicubic_float_tab( void *pout, const VipsPel *pin,
|
||||
const int bands, const int lskip,
|
||||
const double *cx, const double *cy )
|
||||
{
|
||||
@ -236,7 +236,7 @@ bicubic_float_tab( void *pout, const PEL *pin,
|
||||
*/
|
||||
template <typename T>
|
||||
static void inline
|
||||
bicubic_notab( void *pout, const PEL *pin,
|
||||
bicubic_notab( void *pout, const VipsPel *pin,
|
||||
const int bands, const int lskip,
|
||||
double x, double y )
|
||||
{
|
||||
@ -303,7 +303,7 @@ bicubic_notab( void *pout, const PEL *pin,
|
||||
|
||||
static void
|
||||
vips_interpolate_bicubic_interpolate( VipsInterpolate *interpolate,
|
||||
void *out, REGION *in, double x, double y )
|
||||
void *out, VipsRegion *in, double x, double y )
|
||||
{
|
||||
/* 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
|
||||
@ -326,7 +326,7 @@ vips_interpolate_bicubic_interpolate( VipsInterpolate *interpolate,
|
||||
|
||||
/* Back and up one to get the top-left of the 4x4.
|
||||
*/
|
||||
const PEL *p = (PEL *) IM_REGION_ADDR( in, ix - 1, iy - 1 );
|
||||
const VipsPel *p = VIPS_REGION_ADDR( in, ix - 1, iy - 1 );
|
||||
|
||||
/* Look up the tables we need.
|
||||
*/
|
||||
@ -338,7 +338,7 @@ vips_interpolate_bicubic_interpolate( VipsInterpolate *interpolate,
|
||||
/* Pel size and line size.
|
||||
*/
|
||||
const int bands = in->im->Bands;
|
||||
const int lskip = IM_REGION_LSKIP( in );
|
||||
const int lskip = VIPS_REGION_LSKIP( in );
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_interpolate_bicubic_interpolate: %g %g\n", x, y );
|
||||
@ -348,7 +348,7 @@ vips_interpolate_bicubic_interpolate( VipsInterpolate *interpolate,
|
||||
#endif /*DEBUG*/
|
||||
|
||||
switch( in->im->BandFmt ) {
|
||||
case IM_BANDFMT_UCHAR:
|
||||
case VIPS_FORMAT_UCHAR:
|
||||
bicubic_int_tab<unsigned char, 0, UCHAR_MAX>(
|
||||
out, p, bands, lskip,
|
||||
cxi, cyi );
|
||||
@ -366,50 +366,50 @@ vips_interpolate_bicubic_interpolate( VipsInterpolate *interpolate,
|
||||
*/
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_CHAR:
|
||||
case VIPS_FORMAT_CHAR:
|
||||
bicubic_int_tab<signed char, SCHAR_MIN, SCHAR_MAX>(
|
||||
out, p, bands, lskip,
|
||||
cxi, cyi );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_USHORT:
|
||||
case VIPS_FORMAT_USHORT:
|
||||
bicubic_int_tab<unsigned short, 0, USHRT_MAX>(
|
||||
out, p, bands, lskip,
|
||||
cxi, cyi );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_SHORT:
|
||||
case VIPS_FORMAT_SHORT:
|
||||
bicubic_int_tab<signed short, SHRT_MIN, SHRT_MAX>(
|
||||
out, p, bands, lskip,
|
||||
cxi, cyi );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_UINT:
|
||||
case VIPS_FORMAT_UINT:
|
||||
bicubic_float_tab<unsigned int>( out, p, bands, lskip,
|
||||
cxf, cyf );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_INT:
|
||||
case VIPS_FORMAT_INT:
|
||||
bicubic_float_tab<signed int>( out, p, bands, lskip,
|
||||
cxf, cyf );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_FLOAT:
|
||||
case VIPS_FORMAT_FLOAT:
|
||||
bicubic_float_tab<float>( out, p, bands, lskip,
|
||||
cxf, cyf );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_DOUBLE:
|
||||
case VIPS_FORMAT_DOUBLE:
|
||||
bicubic_notab<double>( out, p, bands, lskip,
|
||||
x - ix, y - iy );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_COMPLEX:
|
||||
case VIPS_FORMAT_COMPLEX:
|
||||
bicubic_float_tab<float>( out, p, bands * 2, lskip,
|
||||
cxf, cyf );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_DPCOMPLEX:
|
||||
case VIPS_FORMAT_DPCOMPLEX:
|
||||
bicubic_notab<double>( out, p, bands * 2, lskip,
|
||||
x - ix, y - iy );
|
||||
break;
|
||||
|
@ -150,8 +150,8 @@
|
||||
/* Per-call state.
|
||||
*/
|
||||
typedef struct _Affine {
|
||||
IMAGE *in;
|
||||
IMAGE *out;
|
||||
VipsImage *in;
|
||||
VipsImage *out;
|
||||
VipsInterpolate *interpolate;
|
||||
Transformation trn;
|
||||
} Affine;
|
||||
@ -159,7 +159,7 @@ typedef struct _Affine {
|
||||
static int
|
||||
affine_free( Affine *affine )
|
||||
{
|
||||
IM_FREEF( g_object_unref, affine->interpolate );
|
||||
VIPS_FREEF( g_object_unref, affine->interpolate );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -171,7 +171,7 @@ affine_free( Affine *affine )
|
||||
*
|
||||
* 2. This is embedded in a larger image to provide borders for the
|
||||
* interpolator. iarea->left/top give the offset. These are the coordinates we
|
||||
* pass to IM_REGION_ADDR()/im_prepare() for the input image.
|
||||
* pass to VIPS_REGION_ADDR()/im_prepare() for the input image.
|
||||
*
|
||||
* The borders are sized by the interpolator's window_size property and offset
|
||||
* by the interpolator's window_offset property. For example,
|
||||
@ -190,15 +190,15 @@ affine_free( Affine *affine )
|
||||
* can be negative, since a rotated image can go up and left of the origin.
|
||||
*
|
||||
* 5. Output image space. This is the wh of the xywh passed to im_affine()
|
||||
* below. These are the coordinates we pass to IM_REGION_ADDR() for the
|
||||
* below. These are the coordinates we pass to VIPS_REGION_ADDR() for the
|
||||
* output image, and that affinei_gen() is asked for.
|
||||
*/
|
||||
|
||||
static int
|
||||
affinei_gen( REGION *or, void *seq, void *a, void *b )
|
||||
affinei_gen( VipsRegion *or, void *seq, void *a, void *b )
|
||||
{
|
||||
REGION *ir = (REGION *) seq;
|
||||
const IMAGE *in = (IMAGE *) a;
|
||||
VipsRegion *ir = (VipsRegion *) seq;
|
||||
const VipsImage *in = (VipsImage *) a;
|
||||
const Affine *affine = (Affine *) b;
|
||||
const int window_size =
|
||||
vips_interpolate_get_window_size( affine->interpolate );
|
||||
@ -211,14 +211,14 @@ affinei_gen( REGION *or, void *seq, void *a, void *b )
|
||||
*/
|
||||
const Rect *r = &or->valid;
|
||||
const int le = r->left;
|
||||
const int ri = IM_RECT_RIGHT( r );
|
||||
const int ri = VIPS_RECT_RIGHT( r );
|
||||
const int to = r->top;
|
||||
const int bo = IM_RECT_BOTTOM( r );
|
||||
const int bo = VIPS_RECT_BOTTOM( r );
|
||||
|
||||
const Rect *iarea = &affine->trn.iarea;
|
||||
const Rect *oarea = &affine->trn.oarea;
|
||||
|
||||
int ps = IM_IMAGE_SIZEOF_PEL( in );
|
||||
int ps = VIPS_IMAGE_SIZEOF_PEL( in );
|
||||
int x, y, z;
|
||||
|
||||
Rect image, want, need, clipped;
|
||||
@ -327,7 +327,7 @@ affinei_gen( REGION *or, void *seq, void *a, void *b )
|
||||
ix += iarea->left;
|
||||
iy += iarea->top;
|
||||
|
||||
q = IM_REGION_ADDR( or, le, y );
|
||||
q = VIPS_REGION_ADDR( or, le, y );
|
||||
|
||||
for( x = le; x < ri; x++ ) {
|
||||
int fx, fy;
|
||||
@ -356,7 +356,7 @@ affinei_gen( REGION *or, void *seq, void *a, void *b )
|
||||
}
|
||||
|
||||
static int
|
||||
affinei( IMAGE *in, IMAGE *out,
|
||||
affinei( VipsImage *in, VipsImage *out,
|
||||
VipsInterpolate *interpolate, Transformation *trn )
|
||||
{
|
||||
Affine *affine;
|
||||
@ -370,7 +370,7 @@ affinei( IMAGE *in, IMAGE *out,
|
||||
|
||||
/* Need a copy of the params for the lifetime of out.
|
||||
*/
|
||||
if( !(affine = IM_NEW( out, Affine )) )
|
||||
if( !(affine = VIPS_NEW( out, Affine )) )
|
||||
return( -1 );
|
||||
affine->interpolate = NULL;
|
||||
if( im_add_close_callback( out,
|
||||
@ -391,11 +391,11 @@ affinei( IMAGE *in, IMAGE *out,
|
||||
/* Normally SMALLTILE ... except if this is a size up/down affine.
|
||||
*/
|
||||
if( affine->trn.b == 0.0 && affine->trn.c == 0.0 ) {
|
||||
if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) )
|
||||
if( im_demand_hint( out, VIPS_DEMAND_STYLE_FATSTRIP, in, NULL ) )
|
||||
return( -1 );
|
||||
}
|
||||
else {
|
||||
if( im_demand_hint( out, IM_SMALLTILE, in, NULL ) )
|
||||
if( im_demand_hint( out, VIPS_DEMAND_STYLE_SMALLTILE, in, NULL ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
@ -404,8 +404,8 @@ affinei( IMAGE *in, IMAGE *out,
|
||||
*/
|
||||
edge = INT_MAX / VIPS_TRANSFORM_SCALE;
|
||||
if( affine->trn.oarea.left < -edge || affine->trn.oarea.top < -edge ||
|
||||
IM_RECT_RIGHT( &affine->trn.oarea ) > edge ||
|
||||
IM_RECT_BOTTOM( &affine->trn.oarea ) > edge ) {
|
||||
VIPS_RECT_RIGHT( &affine->trn.oarea ) > edge ||
|
||||
VIPS_RECT_BOTTOM( &affine->trn.oarea ) > edge ) {
|
||||
im_error( "im_affinei",
|
||||
"%s", _( "output coordinates out of range" ) );
|
||||
return( -1 );
|
||||
@ -420,13 +420,13 @@ affinei( IMAGE *in, IMAGE *out,
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* As above, but do IM_CODING_LABQ too. And embed the input.
|
||||
/* As above, but do VIPS_CODING_LABQ too. And embed the input.
|
||||
*/
|
||||
static int
|
||||
im__affinei( IMAGE *in, IMAGE *out,
|
||||
im__affinei( VipsImage *in, VipsImage *out,
|
||||
VipsInterpolate *interpolate, Transformation *trn )
|
||||
{
|
||||
IMAGE *t3 = im_open_local( out, "im_affine:3", "p" );
|
||||
VipsImage *t3 = im_open_local( out, "im_affine:3", "p" );
|
||||
const int window_size =
|
||||
vips_interpolate_get_window_size( interpolate );
|
||||
const int window_offset =
|
||||
@ -452,8 +452,8 @@ im__affinei( IMAGE *in, IMAGE *out,
|
||||
im__transform_print( &trn2 );
|
||||
#endif /*DEBUG_GEOMETRY*/
|
||||
|
||||
if( in->Coding == IM_CODING_LABQ ) {
|
||||
IMAGE *t[2];
|
||||
if( in->Coding == VIPS_CODING_LABQ ) {
|
||||
VipsImage *t[2];
|
||||
|
||||
if( im_open_local_array( out, t, 2, "im_affine:2", "p" ) ||
|
||||
im_LabQ2LabS( t3, t[0] ) ||
|
||||
@ -461,7 +461,7 @@ im__affinei( IMAGE *in, IMAGE *out,
|
||||
im_LabS2LabQ( t[1], out ) )
|
||||
return( -1 );
|
||||
}
|
||||
else if( in->Coding == IM_CODING_NONE ) {
|
||||
else if( in->Coding == VIPS_CODING_NONE ) {
|
||||
if( affinei( t3, out, interpolate, &trn2 ) )
|
||||
return( -1 );
|
||||
}
|
||||
@ -514,7 +514,7 @@ im__affinei( IMAGE *in, IMAGE *out,
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
im_affinei( IMAGE *in, IMAGE *out, VipsInterpolate *interpolate,
|
||||
im_affinei( VipsImage *in, VipsImage *out, VipsInterpolate *interpolate,
|
||||
double a, double b, double c, double d, double dx, double dy,
|
||||
int ox, int oy, int ow, int oh )
|
||||
{
|
||||
@ -560,7 +560,7 @@ im_affinei( IMAGE *in, IMAGE *out, VipsInterpolate *interpolate,
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
im_affinei_all( IMAGE *in, IMAGE *out, VipsInterpolate *interpolate,
|
||||
im_affinei_all( VipsImage *in, VipsImage *out, VipsInterpolate *interpolate,
|
||||
double a, double b, double c, double d, double dx, double dy )
|
||||
{
|
||||
Transformation trn;
|
||||
@ -584,7 +584,7 @@ im_affinei_all( IMAGE *in, IMAGE *out, VipsInterpolate *interpolate,
|
||||
/* Still needed by some parts of mosaic.
|
||||
*/
|
||||
int
|
||||
im__affine( IMAGE *in, IMAGE *out, Transformation *trn )
|
||||
im__affine( VipsImage *in, VipsImage *out, Transformation *trn )
|
||||
{
|
||||
return( im__affinei( in, out,
|
||||
vips_interpolate_bilinear_static(), trn ) );
|
||||
|
@ -78,7 +78,7 @@ G_DEFINE_ABSTRACT_TYPE( VipsInterpolate, vips_interpolate, VIPS_TYPE_OBJECT );
|
||||
* @y: interpolate value at this position
|
||||
*
|
||||
* An interpolation function. It should read source pixels from @in with
|
||||
* IM_REGION_ADDR(), it can look left and up from (x, y) by @window_offset
|
||||
* VIPS_REGION_ADDR(), it can look left and up from (x, y) by @window_offset
|
||||
* pixels and it can access pixels in a window of size @window_size.
|
||||
*
|
||||
* The interpolated value should be written to the pixel pointed to by @out.
|
||||
@ -159,7 +159,7 @@ vips_interpolate_real_get_window_offset( VipsInterpolate *interpolate )
|
||||
|
||||
/* Don't go -ve, of course, for window_size 1.
|
||||
*/
|
||||
return( IM_MAX( 0, window_size / 2 - 1 ) );
|
||||
return( VIPS_MAX( 0, window_size / 2 - 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +211,7 @@ vips_interpolate_init( VipsInterpolate *interpolate )
|
||||
*/
|
||||
void
|
||||
vips_interpolate( VipsInterpolate *interpolate,
|
||||
void *out, REGION *in, double x, double y )
|
||||
void *out, VipsRegion *in, double x, double y )
|
||||
{
|
||||
VipsInterpolateClass *class = VIPS_INTERPOLATE_GET_CLASS( interpolate );
|
||||
|
||||
@ -329,14 +329,14 @@ G_DEFINE_TYPE( VipsInterpolateNearest, vips_interpolate_nearest,
|
||||
|
||||
static void
|
||||
vips_interpolate_nearest_interpolate( VipsInterpolate *interpolate,
|
||||
void *out, REGION *in, double x, double y )
|
||||
void *out, VipsRegion *in, double x, double y )
|
||||
{
|
||||
const int ps = IM_IMAGE_SIZEOF_PEL( in->im );
|
||||
const int ps = VIPS_IMAGE_SIZEOF_PEL( in->im );
|
||||
|
||||
const int xi = (int) x;
|
||||
const int yi = (int) y;
|
||||
|
||||
const VipsPel *p = IM_REGION_ADDR( in, xi, yi );
|
||||
const VipsPel *p = VIPS_REGION_ADDR( in, xi, yi );
|
||||
VipsPel *q = (VipsPel *) out;
|
||||
|
||||
int z;
|
||||
@ -479,14 +479,14 @@ G_DEFINE_TYPE( VipsInterpolateBilinear, vips_interpolate_bilinear,
|
||||
*/
|
||||
#define SWITCH_INTERPOLATE( FMT, INT, FLOAT ) { \
|
||||
switch( (FMT) ) { \
|
||||
case IM_BANDFMT_UCHAR: INT( unsigned char ); break; \
|
||||
case IM_BANDFMT_CHAR: INT( char ); break; \
|
||||
case IM_BANDFMT_USHORT: INT( unsigned short ); break; \
|
||||
case IM_BANDFMT_SHORT: INT( short ); break; \
|
||||
case IM_BANDFMT_UINT: FLOAT( unsigned int ); break; \
|
||||
case IM_BANDFMT_INT: FLOAT( int ); break; \
|
||||
case IM_BANDFMT_FLOAT: FLOAT( float ); break; \
|
||||
case IM_BANDFMT_DOUBLE: FLOAT( double ); break; \
|
||||
case VIPS_FORMAT_UCHAR: INT( unsigned char ); break; \
|
||||
case VIPS_FORMAT_CHAR: INT( char ); break; \
|
||||
case VIPS_FORMAT_USHORT:INT( unsigned short ); break; \
|
||||
case VIPS_FORMAT_SHORT: INT( short ); break; \
|
||||
case VIPS_FORMAT_UINT: FLOAT( unsigned int ); break; \
|
||||
case VIPS_FORMAT_INT: FLOAT( int ); break; \
|
||||
case VIPS_FORMAT_FLOAT: FLOAT( float ); break; \
|
||||
case VIPS_FORMAT_DOUBLE:FLOAT( double ); break; \
|
||||
default: \
|
||||
g_assert( FALSE ); \
|
||||
} \
|
||||
@ -494,18 +494,18 @@ G_DEFINE_TYPE( VipsInterpolateBilinear, vips_interpolate_bilinear,
|
||||
|
||||
static void
|
||||
vips_interpolate_bilinear_interpolate( VipsInterpolate *interpolate,
|
||||
void *out, REGION *in, double x, double y )
|
||||
void *out, VipsRegion *in, double x, double y )
|
||||
{
|
||||
/* Pel size and line size.
|
||||
*/
|
||||
const int ps = IM_IMAGE_SIZEOF_PEL( in->im );
|
||||
const int ls = IM_REGION_LSKIP( in );
|
||||
const int ps = VIPS_IMAGE_SIZEOF_PEL( in->im );
|
||||
const int ls = VIPS_REGION_LSKIP( in );
|
||||
const int b = in->im->Bands;
|
||||
|
||||
const int ix = (int) x;
|
||||
const int iy = (int) y;
|
||||
|
||||
const VipsPel *p1 = IM_REGION_ADDR( in, ix, iy );
|
||||
const VipsPel *p1 = VIPS_REGION_ADDR( in, ix, iy );
|
||||
const VipsPel *p2 = p1 + ps;
|
||||
const VipsPel *p3 = p1 + ls;
|
||||
const VipsPel *p4 = p3 + ps;
|
||||
|
@ -581,8 +581,8 @@ lbbicubic( const double c00,
|
||||
*/
|
||||
#define LBB_CONVERSION( conversion ) \
|
||||
template <typename T> static void inline \
|
||||
lbb_ ## conversion( void* restrict pout, \
|
||||
const PEL* restrict pin, \
|
||||
lbb_ ## conversion( void* restrict pout, \
|
||||
const VipsPel* restrict pin, \
|
||||
const int bands, \
|
||||
const int lskip, \
|
||||
const double relative_x, \
|
||||
@ -764,32 +764,24 @@ G_DEFINE_TYPE( VipsInterpolateLbb, vips_interpolate_lbb,
|
||||
static void
|
||||
vips_interpolate_lbb_interpolate( VipsInterpolate* restrict interpolate,
|
||||
void* restrict out,
|
||||
REGION* restrict in,
|
||||
VipsRegion* restrict in,
|
||||
double absolute_x,
|
||||
double absolute_y )
|
||||
{
|
||||
/*
|
||||
* Floor's surrogate FAST_PSEUDO_FLOOR is used to make sure that the
|
||||
* transition through 0 is smooth. If it is known that absolute_x
|
||||
* and absolute_y will never be less than 0, plain cast---that is,
|
||||
* const int ix = absolute_x---should be used instead. Actually,
|
||||
* any function which agrees with floor for non-integer values, and
|
||||
* picks one of the two possibilities for integer values, can be
|
||||
* used. FAST_PSEUDO_FLOOR fits the bill.
|
||||
/* absolute_x and absolute_y are always >= 1.0 (see double-check assert
|
||||
* below), so we don't need floor().
|
||||
*
|
||||
* Then, x is the x-coordinate of the sampling point relative to the
|
||||
* position of the top left corner of the convex hull of the 2x2
|
||||
* block of closest pixels. Similarly for y. Range of values: [0,1).
|
||||
* It's 1 not 0 since have a window_offset of 1.
|
||||
*/
|
||||
const int ix = FAST_PSEUDO_FLOOR( absolute_x );
|
||||
const int iy = FAST_PSEUDO_FLOOR( absolute_y );
|
||||
const int ix = (int) absolute_x;
|
||||
const int iy = (int) absolute_y;
|
||||
|
||||
/*
|
||||
* Move the pointer to (the first band of) the top/left pixel of the
|
||||
* 2x2 group of pixel centers which contains the sampling location
|
||||
* in its convex hull:
|
||||
*/
|
||||
const PEL* restrict p = (PEL *) IM_REGION_ADDR( in, ix, iy );
|
||||
const VipsPel* restrict p = VIPS_REGION_ADDR( in, ix, iy );
|
||||
|
||||
const double relative_x = absolute_x - ix;
|
||||
const double relative_y = absolute_y - iy;
|
||||
@ -797,50 +789,56 @@ vips_interpolate_lbb_interpolate( VipsInterpolate* restrict interpolate,
|
||||
/*
|
||||
* VIPS versions of Nicolas's pixel addressing values.
|
||||
*/
|
||||
const int actual_bands = in->im->Bands;
|
||||
const int lskip = IM_REGION_LSKIP( in ) / IM_IMAGE_SIZEOF_ELEMENT( in->im );
|
||||
const int lskip = VIPS_REGION_LSKIP( in ) /
|
||||
VIPS_IMAGE_SIZEOF_ELEMENT( in->im );
|
||||
/*
|
||||
* Double the bands for complex images to account for the real and
|
||||
* imaginary parts being computed independently:
|
||||
*/
|
||||
const int actual_bands = in->im->Bands;
|
||||
const int bands =
|
||||
vips_bandfmt_iscomplex( in->im->BandFmt ) ? 2 * actual_bands : actual_bands;
|
||||
|
||||
/* Confirm that absolute_x and absolute_y are >= 1, see above.
|
||||
*/
|
||||
g_assert( absolute_x >= 1.0 );
|
||||
g_assert( absolute_y >= 1.0 );
|
||||
|
||||
switch( in->im->BandFmt ) {
|
||||
case IM_BANDFMT_UCHAR:
|
||||
case VIPS_FORMAT_UCHAR:
|
||||
CALL( unsigned char, nosign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_CHAR:
|
||||
case VIPS_FORMAT_CHAR:
|
||||
CALL( signed char, withsign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_USHORT:
|
||||
case VIPS_FORMAT_USHORT:
|
||||
CALL( unsigned short, nosign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_SHORT:
|
||||
case VIPS_FORMAT_SHORT:
|
||||
CALL( signed short, withsign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_UINT:
|
||||
case VIPS_FORMAT_UINT:
|
||||
CALL( unsigned int, nosign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_INT:
|
||||
case VIPS_FORMAT_INT:
|
||||
CALL( signed int, withsign );
|
||||
break;
|
||||
|
||||
/*
|
||||
* Complex images are handled by doubling of bands.
|
||||
*/
|
||||
case IM_BANDFMT_FLOAT:
|
||||
case IM_BANDFMT_COMPLEX:
|
||||
case VIPS_FORMAT_FLOAT:
|
||||
case VIPS_FORMAT_COMPLEX:
|
||||
CALL( float, fptypes );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_DOUBLE:
|
||||
case IM_BANDFMT_DPCOMPLEX:
|
||||
case VIPS_FORMAT_DOUBLE:
|
||||
case VIPS_FORMAT_DPCOMPLEX:
|
||||
CALL( double, fptypes );
|
||||
break;
|
||||
|
||||
|
@ -1480,32 +1480,24 @@ G_DEFINE_TYPE( VipsInterpolateNohalo, vips_interpolate_nohalo,
|
||||
static void
|
||||
vips_interpolate_nohalo_interpolate( VipsInterpolate* restrict interpolate,
|
||||
void* restrict out,
|
||||
REGION* restrict in,
|
||||
VipsRegion* restrict in,
|
||||
double absolute_x,
|
||||
double absolute_y )
|
||||
{
|
||||
/*
|
||||
* Floor's surrogate FAST_PSEUDO_FLOOR is used to make sure that the
|
||||
* transition through 0 is smooth. If it is known that absolute_x
|
||||
* and absolute_y will never be less than 0, plain cast---that is,
|
||||
* const int ix = absolute_x---should be used instead. Actually,
|
||||
* any function which agrees with floor for non-integer values, and
|
||||
* picks one of the two possibilities for integer values, can be
|
||||
* used. FAST_PSEUDO_FLOOR fits the bill.
|
||||
/* absolute_x and absolute_y are always >= 2.0 (see double-check assert
|
||||
* below), so we don't need floor().
|
||||
*
|
||||
* Then, x is the x-coordinate of the sampling point relative to the
|
||||
* position of the center of the convex hull of the 2x2 block of
|
||||
* closest pixels. Similarly for y. Range of values: [-.5,.5).
|
||||
* It's 2 not 0 since we ask for a window_offset of 2 at the bottom.
|
||||
*/
|
||||
const int ix = FAST_PSEUDO_FLOOR( absolute_x + .5 );
|
||||
const int iy = FAST_PSEUDO_FLOOR( absolute_y + .5 );
|
||||
const int ix = (int) absolute_x;
|
||||
const int iy = (int) absolute_y;
|
||||
|
||||
/*
|
||||
* Move the pointer to (the first band of) the top/left pixel of the
|
||||
* 2x2 group of pixel centers which contains the sampling location
|
||||
* in its convex hull:
|
||||
*/
|
||||
const PEL* restrict p = (PEL *) IM_REGION_ADDR( in, ix, iy );
|
||||
const VipsPel* restrict p = VIPS_REGION_ADDR( in, ix, iy );
|
||||
|
||||
const double relative_x = absolute_x - ix;
|
||||
const double relative_y = absolute_y - iy;
|
||||
@ -1513,50 +1505,57 @@ vips_interpolate_nohalo_interpolate( VipsInterpolate* restrict interpolate,
|
||||
/*
|
||||
* VIPS versions of Nicolas's pixel addressing values.
|
||||
*/
|
||||
const int actual_bands = in->im->Bands;
|
||||
const int lskip = IM_REGION_LSKIP( in ) / IM_IMAGE_SIZEOF_ELEMENT( in->im );
|
||||
const int lskip = VIPS_REGION_LSKIP( in ) /
|
||||
VIPS_IMAGE_SIZEOF_ELEMENT( in->im );
|
||||
|
||||
/*
|
||||
* Double the bands for complex images to account for the real and
|
||||
* imaginary parts being computed independently:
|
||||
*/
|
||||
const int actual_bands = in->im->Bands;
|
||||
const int bands =
|
||||
vips_bandfmt_iscomplex( in->im->BandFmt ) ? 2 * actual_bands : actual_bands;
|
||||
|
||||
/* Confirm that absolute_x and absolute_y are >= 2, see above.
|
||||
*/
|
||||
g_assert( absolute_x >= 2.0 );
|
||||
g_assert( absolute_y >= 2.0 );
|
||||
|
||||
switch( in->im->BandFmt ) {
|
||||
case IM_BANDFMT_UCHAR:
|
||||
case VIPS_FORMAT_UCHAR:
|
||||
CALL( unsigned char, nosign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_CHAR:
|
||||
case VIPS_FORMAT_CHAR:
|
||||
CALL( signed char, withsign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_USHORT:
|
||||
case VIPS_FORMAT_USHORT:
|
||||
CALL( unsigned short, nosign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_SHORT:
|
||||
case VIPS_FORMAT_SHORT:
|
||||
CALL( signed short, withsign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_UINT:
|
||||
case VIPS_FORMAT_UINT:
|
||||
CALL( unsigned int, nosign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_INT:
|
||||
case VIPS_FORMAT_INT:
|
||||
CALL( signed int, withsign );
|
||||
break;
|
||||
|
||||
/*
|
||||
* Complex images are handled by doubling of bands.
|
||||
*/
|
||||
case IM_BANDFMT_FLOAT:
|
||||
case IM_BANDFMT_COMPLEX:
|
||||
case VIPS_FORMAT_FLOAT:
|
||||
case VIPS_FORMAT_COMPLEX:
|
||||
CALL( float, fptypes );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_DOUBLE:
|
||||
case IM_BANDFMT_DPCOMPLEX:
|
||||
case VIPS_FORMAT_DOUBLE:
|
||||
case VIPS_FORMAT_DPCOMPLEX:
|
||||
CALL( double, fptypes );
|
||||
break;
|
||||
|
||||
|
@ -178,8 +178,8 @@ typedef struct _VipsInterpolateVsqbsClass {
|
||||
*/
|
||||
#define VSQBS_CONVERSION( conversion ) \
|
||||
template <typename T> static void inline \
|
||||
vsqbs_ ## conversion( void* restrict pout, \
|
||||
const PEL* restrict pin, \
|
||||
vsqbs_ ## conversion( void* restrict pout, \
|
||||
const VipsPel* restrict pin, \
|
||||
const int bands, \
|
||||
const int lskip, \
|
||||
const double x_0, \
|
||||
@ -308,28 +308,20 @@ vips_interpolate_vsqbs_interpolate( VipsInterpolate* restrict interpolate,
|
||||
double absolute_x,
|
||||
double absolute_y )
|
||||
{
|
||||
/*
|
||||
* Floor's surrogate FAST_PSEUDO_FLOOR is used to make sure that the
|
||||
* transition through 0 is smooth. If it is known that absolute_x
|
||||
* and absolute_y will never be less than 0, plain cast---that is,
|
||||
* const int ix = absolute_x---should be used instead. Actually,
|
||||
* any function which agrees with floor for non-integer values, and
|
||||
* picks one of the two possibilities for integer values, can be
|
||||
* used. FAST_PSEUDO_FLOOR fits the bill.
|
||||
/* absolute_x and absolute_y are always >= 1.0 (see double-check assert
|
||||
* below), so we don't need floor().
|
||||
*
|
||||
* Then, x is the x-coordinate of the sampling point relative to the
|
||||
* position of the center of the convex hull of the 2x2 block of
|
||||
* closest pixels. Similarly for y. Range of values: [-.5,.5).
|
||||
* It's 1 not 0 since we ask for a window_offset of 1 at the bottom.
|
||||
*/
|
||||
const int ix = FAST_PSEUDO_FLOOR( absolute_x + .5 );
|
||||
const int iy = FAST_PSEUDO_FLOOR( absolute_y + .5 );
|
||||
const int ix = (int) absolute_x;
|
||||
const int iy = (int) absolute_y;
|
||||
|
||||
/*
|
||||
* Move the pointer to (the first band of) the top/left pixel of the
|
||||
* 2x2 group of pixel centers which contains the sampling location
|
||||
* in its convex hull:
|
||||
*/
|
||||
const PEL* restrict p = (PEL *) IM_REGION_ADDR( in, ix, iy );
|
||||
const VipsPel* restrict p = VIPS_REGION_ADDR( in, ix, iy );
|
||||
|
||||
const double relative_x = absolute_x - ix;
|
||||
const double relative_y = absolute_y - iy;
|
||||
@ -337,50 +329,57 @@ vips_interpolate_vsqbs_interpolate( VipsInterpolate* restrict interpolate,
|
||||
/*
|
||||
* VIPS versions of Nicolas's pixel addressing values.
|
||||
*/
|
||||
const int actual_bands = in->im->Bands;
|
||||
const int lskip = IM_REGION_LSKIP( in ) / IM_IMAGE_SIZEOF_ELEMENT( in->im );
|
||||
const int lskip = VIPS_REGION_LSKIP( in ) /
|
||||
VIPS_IMAGE_SIZEOF_ELEMENT( in->im );
|
||||
|
||||
/*
|
||||
* Double the bands for complex images to account for the real and
|
||||
* imaginary parts being computed independently:
|
||||
*/
|
||||
const int actual_bands = in->im->Bands;
|
||||
const int bands =
|
||||
vips_bandfmt_iscomplex( in->im->BandFmt ) ? 2 * actual_bands : actual_bands;
|
||||
|
||||
/* Confirm that absolute_x and absolute_y are >= 1, see above.
|
||||
*/
|
||||
g_assert( absolute_x >= 1.0 );
|
||||
g_assert( absolute_y >= 1.0 );
|
||||
|
||||
switch( in->im->BandFmt ) {
|
||||
case IM_BANDFMT_UCHAR:
|
||||
case VIPS_FORMAT_UCHAR:
|
||||
CALL( unsigned char, nosign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_CHAR:
|
||||
case VIPS_FORMAT_CHAR:
|
||||
CALL( signed char, withsign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_USHORT:
|
||||
case VIPS_FORMAT_USHORT:
|
||||
CALL( unsigned short, nosign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_SHORT:
|
||||
case VIPS_FORMAT_SHORT:
|
||||
CALL( signed short, withsign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_UINT:
|
||||
case VIPS_FORMAT_UINT:
|
||||
CALL( unsigned int, nosign );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_INT:
|
||||
case VIPS_FORMAT_INT:
|
||||
CALL( signed int, withsign );
|
||||
break;
|
||||
|
||||
/*
|
||||
* Complex images are handled by doubling bands:
|
||||
*/
|
||||
case IM_BANDFMT_FLOAT:
|
||||
case IM_BANDFMT_COMPLEX:
|
||||
case VIPS_FORMAT_FLOAT:
|
||||
case VIPS_FORMAT_COMPLEX:
|
||||
CALL( float, fptypes );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_DOUBLE:
|
||||
case IM_BANDFMT_DPCOMPLEX:
|
||||
case VIPS_FORMAT_DOUBLE:
|
||||
case VIPS_FORMAT_DPCOMPLEX:
|
||||
CALL( double, fptypes );
|
||||
break;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user