add signed int bicubic path
better rounding for 8- and 16-bit signed int bicubic
This commit is contained in:
parent
2e3baa1bef
commit
2b086cfe6e
2
TODO
2
TODO
@ -1,5 +1,3 @@
|
||||
- bicubic needs a signed int lut path with rounding in the other direction
|
||||
for negatives
|
||||
|
||||
- vips_object_unref_outputs() needs docs ... bindings will need it
|
||||
|
||||
|
@ -104,9 +104,10 @@ G_DEFINE_TYPE( VipsInterpolateBicubic, vips_interpolate_bicubic,
|
||||
|
||||
/* Fixed-point version, for 8 and 16-bit types.
|
||||
*/
|
||||
template <typename T, int min_value, int max_value>
|
||||
|
||||
template <typename T, int max_value>
|
||||
static void inline
|
||||
bicubic_int_tab( void *pout, const VipsPel *pin,
|
||||
bicubic_unsigned_int_tab( void *pout, const VipsPel *pin,
|
||||
const int bands, const int lskip,
|
||||
const int *cx, const int *cy )
|
||||
{
|
||||
@ -152,7 +153,73 @@ bicubic_int_tab( void *pout, const VipsPel *pin,
|
||||
const T qua_thr = in[l3_plus_b2];
|
||||
const T qua_fou = in[l3_plus_b3];
|
||||
|
||||
int bicubic = bicubic_int<T>(
|
||||
int bicubic = bicubic_unsigned_int<T>(
|
||||
uno_one, uno_two, uno_thr, uno_fou,
|
||||
dos_one, dos_two, dos_thr, dos_fou,
|
||||
tre_one, tre_two, tre_thr, tre_fou,
|
||||
qua_one, qua_two, qua_thr, qua_fou,
|
||||
cx, cy );
|
||||
|
||||
if( bicubic < 0 )
|
||||
bicubic = 0;
|
||||
else if( bicubic > max_value )
|
||||
bicubic = max_value;
|
||||
|
||||
out[z] = bicubic;
|
||||
|
||||
in += 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, int min_value, int max_value>
|
||||
static void inline
|
||||
bicubic_signed_int_tab( void *pout, const VipsPel *pin,
|
||||
const int bands, const int lskip,
|
||||
const int *cx, const int *cy )
|
||||
{
|
||||
T* restrict out = (T *) pout;
|
||||
const T* restrict in = (T *) pin;
|
||||
|
||||
const int b1 = bands;
|
||||
const int b2 = b1 + b1;
|
||||
const int b3 = b1 + b2;
|
||||
|
||||
const int l1 = lskip / sizeof( T );
|
||||
const int l2 = l1 + l1;
|
||||
const int l3 = l1 + l2;
|
||||
|
||||
const int l1_plus_b1 = l1 + b1;
|
||||
const int l1_plus_b2 = l1 + b2;
|
||||
const int l1_plus_b3 = l1 + b3;
|
||||
const int l2_plus_b1 = l2 + b1;
|
||||
const int l2_plus_b2 = l2 + b2;
|
||||
const int l2_plus_b3 = l2 + b3;
|
||||
const int l3_plus_b1 = l3 + b1;
|
||||
const int l3_plus_b2 = l3 + b2;
|
||||
const int l3_plus_b3 = l3 + b3;
|
||||
|
||||
for( int z = 0; z < bands; z++ ) {
|
||||
const T uno_one = in[0];
|
||||
const T uno_two = in[b1];
|
||||
const T uno_thr = in[b2];
|
||||
const T uno_fou = in[b3];
|
||||
|
||||
const T dos_one = in[l1];
|
||||
const T dos_two = in[l1_plus_b1];
|
||||
const T dos_thr = in[l1_plus_b2];
|
||||
const T dos_fou = in[l1_plus_b3];
|
||||
|
||||
const T tre_one = in[l2];
|
||||
const T tre_two = in[l2_plus_b1];
|
||||
const T tre_thr = in[l2_plus_b2];
|
||||
const T tre_fou = in[l2_plus_b3];
|
||||
|
||||
const T qua_one = in[l3];
|
||||
const T qua_two = in[l3_plus_b1];
|
||||
const T qua_thr = in[l3_plus_b2];
|
||||
const T qua_fou = in[l3_plus_b3];
|
||||
|
||||
int bicubic = bicubic_signed_int<T>(
|
||||
uno_one, uno_two, uno_thr, uno_fou,
|
||||
dos_one, dos_two, dos_thr, dos_fou,
|
||||
tre_one, tre_two, tre_thr, tre_fou,
|
||||
@ -350,7 +417,7 @@ vips_interpolate_bicubic_interpolate( VipsInterpolate *interpolate,
|
||||
|
||||
switch( in->im->BandFmt ) {
|
||||
case VIPS_FORMAT_UCHAR:
|
||||
bicubic_int_tab<unsigned char, 0, UCHAR_MAX>(
|
||||
bicubic_unsigned_int_tab<unsigned char, UCHAR_MAX>(
|
||||
out, p, bands, lskip,
|
||||
cxi, cyi );
|
||||
|
||||
@ -371,19 +438,19 @@ vips_interpolate_bicubic_interpolate( VipsInterpolate *interpolate,
|
||||
break;
|
||||
|
||||
case VIPS_FORMAT_CHAR:
|
||||
bicubic_int_tab<signed char, SCHAR_MIN, SCHAR_MAX>(
|
||||
bicubic_signed_int_tab<signed char, SCHAR_MIN, SCHAR_MAX>(
|
||||
out, p, bands, lskip,
|
||||
cxi, cyi );
|
||||
break;
|
||||
|
||||
case VIPS_FORMAT_USHORT:
|
||||
bicubic_int_tab<unsigned short, 0, USHRT_MAX>(
|
||||
bicubic_unsigned_int_tab<unsigned short, USHRT_MAX>(
|
||||
out, p, bands, lskip,
|
||||
cxi, cyi );
|
||||
break;
|
||||
|
||||
case VIPS_FORMAT_SHORT:
|
||||
bicubic_int_tab<signed short, SHRT_MIN, SHRT_MAX>(
|
||||
bicubic_signed_int_tab<signed short, SHRT_MIN, SHRT_MAX>(
|
||||
out, p, bands, lskip,
|
||||
cxi, cyi );
|
||||
break;
|
||||
|
@ -169,49 +169,103 @@ bilinear_nosign(
|
||||
* Bicubic (Catmull-Rom) interpolation templates:
|
||||
*/
|
||||
|
||||
static int inline
|
||||
unsigned_fixed_round( int v )
|
||||
{
|
||||
const int round_by = VIPS_INTERPOLATE_SCALE >> 1;
|
||||
|
||||
return( (v + round_by) >> VIPS_INTERPOLATE_SHIFT );
|
||||
}
|
||||
|
||||
/* Fixed-point integer bicubic, used for 8 and 16-bit types.
|
||||
*/
|
||||
template <typename T> static int inline
|
||||
bicubic_int(
|
||||
bicubic_unsigned_int(
|
||||
const T uno_one, const T uno_two, const T uno_thr, const T uno_fou,
|
||||
const T dos_one, const T dos_two, const T dos_thr, const T dos_fou,
|
||||
const T tre_one, const T tre_two, const T tre_thr, const T tre_fou,
|
||||
const T qua_one, const T qua_two, const T qua_thr, const T qua_fou,
|
||||
const int* restrict cx, const int* restrict cy )
|
||||
{
|
||||
const int r0 =
|
||||
(cx[0] * uno_one +
|
||||
cx[1] * uno_two +
|
||||
cx[2] * uno_thr +
|
||||
cx[3] * uno_fou +
|
||||
(VIPS_INTERPOLATE_SCALE >> 1)) >> VIPS_INTERPOLATE_SHIFT;
|
||||
const int r0 = unsigned_fixed_round(
|
||||
cx[0] * uno_one +
|
||||
cx[1] * uno_two +
|
||||
cx[2] * uno_thr +
|
||||
cx[3] * uno_fou );
|
||||
|
||||
const int r1 =
|
||||
(cx[0] * dos_one +
|
||||
cx[1] * dos_two +
|
||||
cx[2] * dos_thr +
|
||||
cx[3] * dos_fou +
|
||||
(VIPS_INTERPOLATE_SCALE >> 1)) >> VIPS_INTERPOLATE_SHIFT;
|
||||
const int r1 = unsigned_fixed_round(
|
||||
cx[0] * dos_one +
|
||||
cx[1] * dos_two +
|
||||
cx[2] * dos_thr +
|
||||
cx[3] * dos_fou );
|
||||
|
||||
const int r2 =
|
||||
(cx[0] * tre_one +
|
||||
cx[1] * tre_two +
|
||||
cx[2] * tre_thr +
|
||||
cx[3] * tre_fou +
|
||||
(VIPS_INTERPOLATE_SCALE >> 1)) >> VIPS_INTERPOLATE_SHIFT;
|
||||
const int r2 = unsigned_fixed_round(
|
||||
cx[0] * tre_one +
|
||||
cx[1] * tre_two +
|
||||
cx[2] * tre_thr +
|
||||
cx[3] * tre_fou );
|
||||
|
||||
const int r3 =
|
||||
(cx[0] * qua_one +
|
||||
cx[1] * qua_two +
|
||||
cx[2] * qua_thr +
|
||||
cx[3] * qua_fou +
|
||||
(VIPS_INTERPOLATE_SCALE >> 1)) >> VIPS_INTERPOLATE_SHIFT;
|
||||
const int r3 = unsigned_fixed_round(
|
||||
cx[0] * qua_one +
|
||||
cx[1] * qua_two +
|
||||
cx[2] * qua_thr +
|
||||
cx[3] * qua_fou );
|
||||
|
||||
return( (cy[0] * r0 +
|
||||
cy[1] * r1 +
|
||||
cy[2] * r2 +
|
||||
cy[3] * r3 +
|
||||
(VIPS_INTERPOLATE_SCALE >> 1)) >> VIPS_INTERPOLATE_SHIFT );
|
||||
return( unsigned_fixed_round(
|
||||
cy[0] * r0 +
|
||||
cy[1] * r1 +
|
||||
cy[2] * r2 +
|
||||
cy[3] * r3 ) );
|
||||
}
|
||||
|
||||
static int inline
|
||||
signed_fixed_round( int v )
|
||||
{
|
||||
const int sign_of_v = 2 * (v > 0) - 1;
|
||||
const int round_by = sign_of_v * (VIPS_INTERPOLATE_SCALE >> 1);
|
||||
|
||||
return( (v + round_by) >> VIPS_INTERPOLATE_SHIFT );
|
||||
}
|
||||
|
||||
/* Fixed-point integer bicubic, used for 8 and 16-bit types.
|
||||
*/
|
||||
template <typename T> static int inline
|
||||
bicubic_signed_int(
|
||||
const T uno_one, const T uno_two, const T uno_thr, const T uno_fou,
|
||||
const T dos_one, const T dos_two, const T dos_thr, const T dos_fou,
|
||||
const T tre_one, const T tre_two, const T tre_thr, const T tre_fou,
|
||||
const T qua_one, const T qua_two, const T qua_thr, const T qua_fou,
|
||||
const int* restrict cx, const int* restrict cy )
|
||||
{
|
||||
const int r0 = signed_fixed_round(
|
||||
cx[0] * uno_one +
|
||||
cx[1] * uno_two +
|
||||
cx[2] * uno_thr +
|
||||
cx[3] * uno_fou );
|
||||
|
||||
const int r1 = signed_fixed_round(
|
||||
cx[0] * dos_one +
|
||||
cx[1] * dos_two +
|
||||
cx[2] * dos_thr +
|
||||
cx[3] * dos_fou );
|
||||
|
||||
const int r2 = signed_fixed_round(
|
||||
cx[0] * tre_one +
|
||||
cx[1] * tre_two +
|
||||
cx[2] * tre_thr +
|
||||
cx[3] * tre_fou );
|
||||
|
||||
const int r3 = signed_fixed_round(
|
||||
cx[0] * qua_one +
|
||||
cx[1] * qua_two +
|
||||
cx[2] * qua_thr +
|
||||
cx[3] * qua_fou );
|
||||
|
||||
return( signed_fixed_round(
|
||||
cy[0] * r0 +
|
||||
cy[1] * r1 +
|
||||
cy[2] * r2 +
|
||||
cy[3] * r3 ) );
|
||||
}
|
||||
|
||||
/* Floating-point bicubic, used for int/float/double types.
|
||||
|
Loading…
x
Reference in New Issue
Block a user