oops
This commit is contained in:
parent
2935369e06
commit
b4e79ccb5a
@ -316,6 +316,9 @@ nohalo1(
|
||||
double *r3,
|
||||
double *r4 )
|
||||
{
|
||||
/* Start of copy-paste from Nicolas's source.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The potentially needed input pixel values are described by the
|
||||
* following stencil, where (ix,iy) are the coordinates of the
|
||||
@ -340,10 +343,11 @@ nohalo1(
|
||||
* (ix-1,iy+2) (ix,iy+2) (ix+1,iy+2)
|
||||
* = cin_two = cin_thr = cin_fou
|
||||
*
|
||||
* Once symmetry has been used to assume that the sampling point is
|
||||
* to the right and bottom of tre_thr---this is done by implicitly
|
||||
* reflecting the data if this is not initially the case---the
|
||||
* needed input values are named thus:
|
||||
* The above is the "enlarged" stencil: about half the values will
|
||||
* not be used. Once symmetry has been used to assume that the
|
||||
* sampling point is to the right and bottom of tre_thr---this is
|
||||
* done by implicitly reflecting the data if this is not initially
|
||||
* the case---the actually used input values are named thus:
|
||||
*
|
||||
* dos_thr dos_fou
|
||||
*
|
||||
@ -355,11 +359,11 @@ nohalo1(
|
||||
*
|
||||
* (If, for exammple, relative_x_is_left is 1 but relative_y_is___up
|
||||
* = 0, then dos_fou in this post-reflexion reduced stencil really
|
||||
* corresponds to dos_two in the unreduced one, etc.)
|
||||
* corresponds to dos_two in the "enlarged" one, etc.)
|
||||
*
|
||||
* Given that the reflexions are performed "outside of the
|
||||
* Given that the reflexions are performed "outside of the nohalo1
|
||||
* function," the above 12 input values are the only ones "seen" by
|
||||
* this function.
|
||||
* it.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -369,7 +373,6 @@ nohalo1(
|
||||
* two consecutive pixel value differences don't have the same sign,
|
||||
* the corresponding slope is set to 0.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tre(s) horizontal differences:
|
||||
*/
|
||||
@ -398,27 +401,27 @@ nohalo1(
|
||||
/*
|
||||
* Tre:
|
||||
*/
|
||||
const int sign_deux_tre = 2 * (deux_tre >= 0.) - 1;
|
||||
const int sign_troi_tre = 2 * (troi_tre >= 0.) - 1;
|
||||
const int sign_quat_tre = 2 * (quat_tre >= 0.) - 1;
|
||||
const int sign_deux_tre = 2 * ( deux_tre >= 0. ) - 1;
|
||||
const int sign_troi_tre = 2 * ( troi_tre >= 0. ) - 1;
|
||||
const int sign_quat_tre = 2 * ( quat_tre >= 0. ) - 1;
|
||||
/*
|
||||
* Qua:
|
||||
*/
|
||||
const int sign_deux_qua = 2 * (deux_qua >= 0.) - 1;
|
||||
const int sign_troi_qua = 2 * (troi_qua >= 0.) - 1;
|
||||
const int sign_quat_qua = 2 * (quat_qua >= 0.) - 1;
|
||||
const int sign_deux_qua = 2 * ( deux_qua >= 0. ) - 1;
|
||||
const int sign_troi_qua = 2 * ( troi_qua >= 0. ) - 1;
|
||||
const int sign_quat_qua = 2 * ( quat_qua >= 0. ) - 1;
|
||||
/*
|
||||
* Thr:
|
||||
*/
|
||||
const int sign_deux_thr = 2 * (deux_thr >= 0.) - 1;
|
||||
const int sign_troi_thr = 2 * (troi_thr >= 0.) - 1;
|
||||
const int sign_quat_thr = 2 * (quat_thr >= 0.) - 1;
|
||||
const int sign_deux_thr = 2 * ( deux_thr >= 0. ) - 1;
|
||||
const int sign_troi_thr = 2 * ( troi_thr >= 0. ) - 1;
|
||||
const int sign_quat_thr = 2 * ( quat_thr >= 0. ) - 1;
|
||||
/*
|
||||
* Fou:
|
||||
*/
|
||||
const int sign_deux_fou = 2 * (deux_fou >= 0.) - 1;
|
||||
const int sign_troi_fou = 2 * (troi_fou >= 0.) - 1;
|
||||
const int sign_quat_fou = 2 * (quat_fou >= 0.) - 1;
|
||||
const int sign_deux_fou = 2 * ( deux_fou >= 0. ) - 1;
|
||||
const int sign_troi_fou = 2 * ( troi_fou >= 0. ) - 1;
|
||||
const int sign_quat_fou = 2 * ( quat_fou >= 0. ) - 1;
|
||||
|
||||
/*
|
||||
* Tre:
|
||||
@ -449,60 +452,92 @@ nohalo1(
|
||||
* Tre:
|
||||
*/
|
||||
const double twice_tre_thr_horizo =
|
||||
(1 + sign_deux_tre * sign_troi_tre) * (
|
||||
(abs_deux_tre <= abs_troi_tre) *
|
||||
(deux_tre - troi_tre) +
|
||||
( 1 + sign_deux_tre * sign_troi_tre )
|
||||
*
|
||||
(
|
||||
( abs_deux_tre <= abs_troi_tre )
|
||||
*
|
||||
( deux_tre - troi_tre )
|
||||
+
|
||||
troi_tre
|
||||
);
|
||||
const double twice_tre_fou_horizo =
|
||||
(1 + sign_troi_tre * sign_quat_tre) * (
|
||||
(abs_troi_tre <= abs_quat_tre) *
|
||||
(troi_tre - quat_tre) +
|
||||
( 1 + sign_troi_tre * sign_quat_tre )
|
||||
*
|
||||
(
|
||||
( abs_troi_tre <= abs_quat_tre )
|
||||
*
|
||||
( troi_tre - quat_tre )
|
||||
+
|
||||
quat_tre
|
||||
);
|
||||
/*
|
||||
* Qua:
|
||||
*/
|
||||
const double twice_qua_thr_horizo =
|
||||
(1 + sign_deux_qua * sign_troi_qua) * (
|
||||
(abs_deux_qua <= abs_troi_qua) *
|
||||
(deux_qua - troi_qua) +
|
||||
( 1 + sign_deux_qua * sign_troi_qua )
|
||||
*
|
||||
(
|
||||
( abs_deux_qua <= abs_troi_qua )
|
||||
*
|
||||
( deux_qua - troi_qua )
|
||||
+
|
||||
troi_qua
|
||||
);
|
||||
const double twice_qua_fou_horizo =
|
||||
(1 + sign_troi_qua * sign_quat_qua) * (
|
||||
(abs_troi_qua <= abs_quat_qua) *
|
||||
(troi_qua - quat_qua) +
|
||||
( 1 + sign_troi_qua * sign_quat_qua )
|
||||
*
|
||||
(
|
||||
( abs_troi_qua <= abs_quat_qua )
|
||||
*
|
||||
( troi_qua - quat_qua )
|
||||
+
|
||||
quat_qua
|
||||
);
|
||||
/*
|
||||
* Thr:
|
||||
*/
|
||||
const double twice_tre_thr_vertic =
|
||||
(1 + sign_deux_thr * sign_troi_thr) * (
|
||||
(abs_deux_thr <= abs_troi_thr) *
|
||||
(deux_thr - troi_thr) +
|
||||
( 1 + sign_deux_thr * sign_troi_thr )
|
||||
*
|
||||
(
|
||||
( abs_deux_thr <= abs_troi_thr )
|
||||
*
|
||||
( deux_thr - troi_thr )
|
||||
+
|
||||
troi_thr
|
||||
);
|
||||
const double twice_qua_thr_vertic =
|
||||
(1 + sign_troi_thr * sign_quat_thr) * (
|
||||
(abs_troi_thr <= abs_quat_thr) *
|
||||
(troi_thr - quat_thr) +
|
||||
( 1 + sign_troi_thr * sign_quat_thr )
|
||||
*
|
||||
(
|
||||
( abs_troi_thr <= abs_quat_thr )
|
||||
*
|
||||
( troi_thr - quat_thr )
|
||||
+
|
||||
quat_thr
|
||||
);
|
||||
/*
|
||||
* Fou:
|
||||
*/
|
||||
const double twice_tre_fou_vertic =
|
||||
(1 + sign_deux_fou * sign_troi_fou) * (
|
||||
(abs_deux_fou <= abs_troi_fou) *
|
||||
(deux_fou - troi_fou) +
|
||||
( 1 + sign_deux_fou * sign_troi_fou )
|
||||
*
|
||||
(
|
||||
( abs_deux_fou <= abs_troi_fou )
|
||||
*
|
||||
( deux_fou - troi_fou )
|
||||
+
|
||||
troi_fou
|
||||
);
|
||||
const double twice_qua_fou_vertic =
|
||||
(1 + sign_troi_fou * sign_quat_fou) * (
|
||||
(abs_troi_fou <= abs_quat_fou) *
|
||||
(troi_fou - quat_fou) +
|
||||
( 1 + sign_troi_fou * sign_quat_fou )
|
||||
*
|
||||
(
|
||||
( abs_troi_fou <= abs_quat_fou )
|
||||
*
|
||||
( troi_fou - quat_fou )
|
||||
+
|
||||
quat_fou
|
||||
);
|
||||
|
||||
@ -514,8 +549,9 @@ nohalo1(
|
||||
* Tre:
|
||||
*/
|
||||
const double tre_thrfou =
|
||||
.5 * (tre_thr + tre_fou) +
|
||||
.125 * (twice_tre_thr_horizo - twice_tre_fou_horizo);
|
||||
.5 * ( tre_thr + tre_fou )
|
||||
+
|
||||
.125 * ( twice_tre_thr_horizo - twice_tre_fou_horizo );
|
||||
|
||||
/*
|
||||
* Compute the needed "vertical" double resolution pixel value:
|
||||
@ -524,132 +560,143 @@ nohalo1(
|
||||
* Thr:
|
||||
*/
|
||||
const double trequa_thr =
|
||||
.5 * (tre_thr + qua_thr) +
|
||||
.125 * (twice_tre_thr_vertic - twice_qua_thr_vertic);
|
||||
.5 * ( tre_thr + qua_thr )
|
||||
+
|
||||
.125 * ( twice_tre_thr_vertic - twice_qua_thr_vertic );
|
||||
|
||||
/*
|
||||
* Compute the "diagonal" (at the boundary between four input pixel
|
||||
* areas) double resolution pixel value:
|
||||
*/
|
||||
const double trequa_thrfou =
|
||||
.25 * (qua_fou - tre_thr) +
|
||||
.5 * (tre_thrfou + trequa_thr) +
|
||||
.0625 * (
|
||||
(twice_qua_thr_horizo + twice_tre_fou_vertic) -
|
||||
(twice_qua_fou_horizo + twice_qua_fou_vertic)
|
||||
.25 * ( qua_fou - tre_thr )
|
||||
+
|
||||
.5 * ( tre_thrfou + trequa_thr )
|
||||
+
|
||||
.0625
|
||||
*
|
||||
(
|
||||
( twice_qua_thr_horizo + twice_tre_fou_vertic )
|
||||
-
|
||||
( twice_qua_fou_horizo + twice_qua_fou_vertic )
|
||||
);
|
||||
|
||||
/* End of copy-paste from Nicolas's source.
|
||||
*/
|
||||
|
||||
*r1 = tre_thr;
|
||||
*r2 = tre_thrfou;
|
||||
*r3 = trequa_thr;
|
||||
*r4 = trequa_thrfou;
|
||||
}
|
||||
|
||||
/* Interpolate for float and double types.
|
||||
/* Float/double version.
|
||||
*/
|
||||
template <typename IN_AND_OUT_TYPE> static IN_AND_OUT_TYPE inline
|
||||
interpolate_float(
|
||||
template <typename T> static void inline
|
||||
nohalo_float( PEL *pout, const PEL *pin,
|
||||
const int bands, const int lskip,
|
||||
const double w_times_z,
|
||||
const double x_times_z,
|
||||
const double w_times_y,
|
||||
const double x_times_y,
|
||||
const double tre_thr,
|
||||
const double tre_thrfou,
|
||||
const double trequa_thr,
|
||||
const double trequa_thrfou )
|
||||
const double x_times_y )
|
||||
{
|
||||
const IN_AND_OUT_TYPE newval =
|
||||
w_times_z * tre_thr +
|
||||
x_times_z * tre_thrfou +
|
||||
w_times_y * trequa_thr +
|
||||
x_times_y * trequa_thrfou;
|
||||
T* restrict out = (T *) pout;
|
||||
const T* restrict in = (T *) pin;
|
||||
|
||||
return( newval );
|
||||
}
|
||||
const int b1 = bands;
|
||||
const int b2 = 2 * b1;
|
||||
const int b3 = 3 * b1;
|
||||
|
||||
/* Interpolate for signed integer types.
|
||||
*/
|
||||
template <typename IN_AND_OUT_TYPE> static IN_AND_OUT_TYPE inline
|
||||
nohalo_signed(
|
||||
const double w_times_z,
|
||||
const double x_times_z,
|
||||
const double w_times_y,
|
||||
const double x_times_y,
|
||||
const double tre_thr,
|
||||
const double tre_thrfou,
|
||||
const double trequa_thr,
|
||||
const double trequa_thrfou )
|
||||
{
|
||||
const double val =
|
||||
(w_times_z / 16) * tre_thr +
|
||||
(x_times_z / 16) * tre_thrfou +
|
||||
(w_times_y / 16) * trequa_thr +
|
||||
(x_times_y / 16) * trequa_thrfou;
|
||||
const int l1 = lskip / sizeof( T );
|
||||
const int l2 = 2 * l1;
|
||||
const int l3 = 3 * l1;
|
||||
|
||||
const int sign_of_val = 2 * ( val >= 0. ) - 1;
|
||||
for( int z = 0; z < bands; z++ ) {
|
||||
|
||||
const int rounded_abs_val = .5 + sign_of_val * val;
|
||||
const T dos_two = in[b1];
|
||||
const T dos_thr = in[b2];
|
||||
|
||||
const IN_AND_OUT_TYPE newval = sign_of_val * rounded_abs_val;
|
||||
const T tre_one = in[l1];
|
||||
const T tre_two = in[b1 + l1];
|
||||
const T tre_thr = in[b2 + l1];
|
||||
const T tre_fou = in[b3 + l1];
|
||||
|
||||
return( newval );
|
||||
}
|
||||
const T qua_one = in[l2];
|
||||
const T qua_two = in[b1 + l2];
|
||||
const T qua_thr = in[b2 + l2];
|
||||
const T qua_fou = in[b3 + l2];
|
||||
|
||||
/* Interpolate for unsigned integer types.
|
||||
*/
|
||||
template <typename IN_AND_OUT_TYPE> static IN_AND_OUT_TYPE inline
|
||||
nohalo_unsigned(
|
||||
const double w_times_z,
|
||||
const double x_times_z,
|
||||
const double w_times_y,
|
||||
const double x_times_y,
|
||||
const double tre_thr,
|
||||
const double tre_thrfou,
|
||||
const double trequa_thr,
|
||||
const double trequa_thrfou )
|
||||
{
|
||||
const IN_AND_OUT_TYPE newval =
|
||||
(w_times_z / 16) * tre_thr +
|
||||
(x_times_z / 16) * tre_thrfou +
|
||||
(w_times_y / 16) * trequa_thr +
|
||||
(x_times_y / 16) * trequa_thrfou +
|
||||
0.5
|
||||
const T cin_two = in[b1 + l3];
|
||||
const T cin_thr = in[b2 + l3];
|
||||
|
||||
return( newval );
|
||||
double tre_thr;
|
||||
double tre_thrfou;
|
||||
double trequa_thr;
|
||||
double trequa_thrfou;
|
||||
|
||||
nohalo1(
|
||||
dos_thr, dos_fou,
|
||||
tre_two, tre_thr, tre_fou, tre_fiv,
|
||||
qua_two, qua_thr, qua_fou, qua_fiv,
|
||||
cin_thr, cin_fou,
|
||||
&tre_thr,
|
||||
&tre_thrfou,
|
||||
&trequa_thr,
|
||||
&trequa_thrfou );
|
||||
|
||||
const T result = bilinear_float<T>(
|
||||
w_times_z,
|
||||
x_times_z,
|
||||
w_times_y,
|
||||
x_times_y,
|
||||
tre_thr,
|
||||
tre_thrfou,
|
||||
trequa_thr,
|
||||
trequa_thrfou );
|
||||
|
||||
*out = result;
|
||||
|
||||
in += 1;
|
||||
out += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gegl_sampler_yafr_get ( GeglSampler* restrict self,
|
||||
const gdouble absolute_x,
|
||||
const gdouble absolute_y,
|
||||
void* restrict output)
|
||||
vips_interpolate_nohalo_interpolate( VipsInterpolate *interpolate,
|
||||
PEL *out, REGION *in, double absolute_x, double absolute_y )
|
||||
{
|
||||
/*
|
||||
* NEEDED CONSTANTS RELATED TO THE INPUT PIXEL POINTER:
|
||||
VipsInterpolateNohaloClass *nohalo_class =
|
||||
VIPS_INTERPOLATE_NOHALO_GET_CLASS( interpolate );
|
||||
VipsInterpolateNohalo *nohalo = VIPS_INTERPOLATE_NOHALO( interpolate );
|
||||
|
||||
/* VIPS versions of Nicolas's pixel addressing values.
|
||||
*/
|
||||
const int channels_per_pixel = in->im->Bands;
|
||||
const int values_per_tile_row =
|
||||
IM_REGION_LSKIP( in ) / IM_IMAGE_SIZEOF_ELEMENT( in );
|
||||
|
||||
/* Copy-paste of Nicolas's pixel addressing code starts.
|
||||
*/
|
||||
const gint channels_per_pixel = 4;
|
||||
const gint pixels_per_tile_row = 64;
|
||||
const gint values_per_tile_row = channels_per_pixel * pixels_per_tile_row;
|
||||
|
||||
/*
|
||||
* 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 -.5, plain cast---that is,
|
||||
* const gint ix = absolute_x + .5---should be used instead. Any
|
||||
* const int ix = absolute_x + .5---should be used instead. Any
|
||||
* function which agrees with floor for non-integer values, and
|
||||
* picks one of the two possibilities for integer values, can be
|
||||
* used.
|
||||
*/
|
||||
const gint ix = FAST_PSEUDO_FLOOR (absolute_x + .5);
|
||||
const gint iy = FAST_PSEUDO_FLOOR (absolute_y + .5);
|
||||
const int ix = FAST_PSEUDO_FLOOR (absolute_x + .5);
|
||||
const int iy = FAST_PSEUDO_FLOOR (absolute_y + .5);
|
||||
|
||||
/*
|
||||
* x is the x-coordinate of the sampling point relative to the
|
||||
* position of the tre_thr pixel center. Similarly for y. Range of
|
||||
* values: [-.5,.5].
|
||||
*/
|
||||
const gdouble relative_x = absolute_x - ix;
|
||||
const gdouble relative_y = absolute_y - iy;
|
||||
const double relative_x = absolute_x - ix;
|
||||
const double relative_y = absolute_y - iy;
|
||||
|
||||
/*
|
||||
* "DIRTY" TRICK: In order to minimize the number of computed
|
||||
@ -657,14 +704,90 @@ gegl_sampler_yafr_get ( GeglSampler* restrict self,
|
||||
* the data." (An alternative approach is to "compute everything and
|
||||
* select by zeroing coefficients.")
|
||||
*/
|
||||
const gint relative_x_is_left = ( relative_x < 0. );
|
||||
const gint relative_y_is___up = ( relative_y < 0. );
|
||||
const int relative_x_is_left = ( relative_x < 0. );
|
||||
const int relative_y_is___up = ( relative_y < 0. );
|
||||
|
||||
const gint basic_x_reflexion_shift = ( 5 - 1 ) * channels_per_pixel;
|
||||
const gint basic_y_reflexion_shift = ( 5 - 1 ) * values_per_tile_row;
|
||||
const int basic_x_reflexion_shift = ( 5 - 1 ) * channels_per_pixel;
|
||||
const int basic_y_reflexion_shift = ( 5 - 1 ) * values_per_tile_row;
|
||||
|
||||
const gint x_reflexion_shift = basic_x_reflexion_shift * relative_x_is_left;
|
||||
const gint y_reflexion_shift = basic_y_reflexion_shift * relative_y_is___up;
|
||||
const int x_reflexion_shift = basic_x_reflexion_shift * relative_x_is_left;
|
||||
const int y_reflexion_shift = basic_y_reflexion_shift * relative_y_is___up;
|
||||
|
||||
/*
|
||||
* The direction of movement within the (extended) possibly
|
||||
* reflected stencil is then determined by the following signs:
|
||||
*/
|
||||
const int sign_of_relative_x = 1 - 2 * relative_x_is_left;
|
||||
const int sign_of_relative_y = 1 - 2 * relative_y_is___up;
|
||||
|
||||
/*
|
||||
* Unit shifts:
|
||||
*/
|
||||
const int shift_1_pixel = sign_of_relative_x * channels_per_pixel;
|
||||
const int shift_1_row = sign_of_relative_y * values_per_tile_row;
|
||||
|
||||
/*
|
||||
* POST REFLEXION/POST RESCALING "DOUBLE DENSITY" COORDINATES:
|
||||
*
|
||||
* With the appropriate reflexions, we can assume that the
|
||||
* coordinates are positive (that we are in the bottom right
|
||||
* quadrant (in quadrant III) relative to tre_thr). It is also
|
||||
* convenient to scale things by 2, so that the "double density
|
||||
* pixels" are 1---instead of 1/2---apart:
|
||||
*/
|
||||
const double x = ( 2 * sign_of_relative_x ) * relative_x;
|
||||
const double y = ( 2 * sign_of_relative_y ) * relative_y;
|
||||
|
||||
/*
|
||||
* Basic shifts:
|
||||
*/
|
||||
const int shift_2_pixels = 2 * shift_1_pixel;
|
||||
const int shift_2_rows = 2 * shift_1_row;
|
||||
|
||||
/*
|
||||
* FIRST BILINEAR WEIGHT:
|
||||
*/
|
||||
const double x_times_y = x * y;
|
||||
|
||||
/*
|
||||
* More basic shifts:
|
||||
*/
|
||||
const int shift_3_pixels = shift_2_pixels + shift_1_pixel;
|
||||
const int shift_3_rows = shift_2_rows + shift_1_row;
|
||||
const int shift_4_rows = 2 * shift_2_rows;
|
||||
const int shift_4_pixels = 2 * shift_2_pixels;
|
||||
|
||||
/*
|
||||
* SECOND AND THIRD BILINEAR WEIGHTS:
|
||||
*
|
||||
* (Note: w = 1-x and z = 1-y.)
|
||||
*/
|
||||
const double w_times_y = y - x_times_y;
|
||||
const double x_times_z = x - x_times_y;
|
||||
|
||||
/*
|
||||
* OVERALL SHIFTS:
|
||||
*/
|
||||
const int dos_thr_shift = shift_1_row + shift_2_pixels;
|
||||
const int dos_fou_shift = shift_1_row + shift_3_pixels;
|
||||
|
||||
const int tre_two_shift = shift_2_rows + shift_1_pixel;
|
||||
const int tre_thr_shift = shift_2_rows + shift_2_pixels;
|
||||
const int tre_fou_shift = shift_2_rows + shift_3_pixels;
|
||||
const int tre_fiv_shift = shift_2_rows + shift_4_pixels;
|
||||
|
||||
const int qua_two_shift = shift_3_rows + shift_1_pixel;
|
||||
const int qua_thr_shift = shift_3_rows + shift_2_pixels;
|
||||
const int qua_fou_shift = shift_3_rows + shift_3_pixels;
|
||||
const int qua_fiv_shift = shift_3_rows + shift_4_pixels;
|
||||
|
||||
const int cin_thr_shift = shift_4_rows + shift_2_pixels;
|
||||
const int cin_fou_shift = shift_4_rows + shift_3_pixels;
|
||||
|
||||
/*
|
||||
* LAST BILINEAR WEIGHT:
|
||||
*/
|
||||
const double w_times_z = 1. - ( x + w_times_y );
|
||||
|
||||
/*
|
||||
* gegl_sampler_get_ptr (self, ix-2, iy-2) should give me access to
|
||||
@ -678,8 +801,8 @@ gegl_sampler_yafr_get ( GeglSampler* restrict self,
|
||||
* left of the five by five stencil, will bring it to the desired
|
||||
* corner:
|
||||
*/
|
||||
const IN_AND_OUT_TYPE* restrict uno_one_input_bptr =
|
||||
gegl_sampler_get_ptr (self, ix-2, iy-2)
|
||||
const PEL * restrict in =
|
||||
IM_REGION_ADDR (self, ix-2, iy-2)
|
||||
+
|
||||
(
|
||||
x_reflexion_shift
|
||||
@ -687,190 +810,64 @@ gegl_sampler_yafr_get ( GeglSampler* restrict self,
|
||||
y_reflexion_shift
|
||||
);
|
||||
|
||||
switch( in->im->BandFmt ) {
|
||||
/*
|
||||
* The direction of movement within the (extended) possibly
|
||||
* reflected stencil is then determined by the following signs:
|
||||
case IM_BANDFMT_UCHAR:
|
||||
nohalo_unsigned<unsigned char>( out, p, bands, lskip,
|
||||
w_times_z, x_times_z, w_times_y, x_times_y );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_CHAR:
|
||||
nohalo_signed<signed char>( out, p, bands, lskip,
|
||||
w_times_z, x_times_z, w_times_y, x_times_y );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_USHORT:
|
||||
nohalo_unsigned<unsigned short>( out, p, bands, lskip,
|
||||
w_times_z, x_times_z, w_times_y, x_times_y );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_SHORT:
|
||||
nohalo_signed<signed short>( out, p, bands, lskip,
|
||||
w_times_z, x_times_z, w_times_y, x_times_y );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_UINT:
|
||||
nohalo_unsigned<unsigned int>( out, p, bands, lskip,
|
||||
w_times_z, x_times_z, w_times_y, x_times_y );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_INT:
|
||||
nohalo_signed<signed int>( out, p, bands, lskip,
|
||||
w_times_z, x_times_z, w_times_y, x_times_y );
|
||||
break;
|
||||
*/
|
||||
const gint sign_of_relative_x = 1 - 2 * relative_x_is_left;
|
||||
const gint sign_of_relative_y = 1 - 2 * relative_y_is___up;
|
||||
|
||||
case IM_BANDFMT_FLOAT:
|
||||
nohalo_float<float>( out, p, bands, lskip,
|
||||
w_times_z, x_times_z, w_times_y, x_times_y );
|
||||
break;
|
||||
|
||||
/*
|
||||
* Unit shifts:
|
||||
case IM_BANDFMT_DOUBLE:
|
||||
nohalo_float<double>( out, p, bands, lskip,
|
||||
w_times_z, x_times_z, w_times_y, x_times_y );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_COMPLEX:
|
||||
nohalo_float<float>( out, p, bands * 2, lskip,
|
||||
w_times_z, x_times_z, w_times_y, x_times_y );
|
||||
break;
|
||||
|
||||
case IM_BANDFMT_DPCOMPLEX:
|
||||
nohalo_float<double>( out, p, bands * 2, lskip,
|
||||
w_times_z, x_times_z, w_times_y, x_times_y );
|
||||
break;
|
||||
*/
|
||||
const gint shift_1_pixel = sign_of_relative_x * channels_per_pixel;
|
||||
const gint shift_1_row = sign_of_relative_y * values_per_tile_row;
|
||||
|
||||
/*
|
||||
* POST REFLEXION/POST RESCALING "DOUBLE DENSITY" COORDINATES:
|
||||
*
|
||||
* With the appropriate reflexions, we can assume that the
|
||||
* coordinates are positive (that we are in the bottom right
|
||||
* quadrant (in quadrant III) relative to tre_thr). It is also
|
||||
* convenient to scale things by 2, so that the "double density
|
||||
* pixels" are 1---instead of 1/2---apart:
|
||||
*/
|
||||
const gdouble x = ( 2 * sign_of_relative_x ) * relative_x;
|
||||
const gdouble y = ( 2 * sign_of_relative_y ) * relative_y;
|
||||
|
||||
/*
|
||||
* Basic shifts:
|
||||
*/
|
||||
const gint shift_2_pixels = 2 * shift_1_pixel;
|
||||
const gint shift_2_rows = 2 * shift_1_row;
|
||||
|
||||
/*
|
||||
* FIRST BILINEAR WEIGHT:
|
||||
*/
|
||||
const gdouble x_times_y = x * y;
|
||||
|
||||
/*
|
||||
* More basic shifts:
|
||||
*/
|
||||
const gint shift_3_pixels = shift_2_pixels + shift_1_pixel;
|
||||
const gint shift_3_rows = shift_2_rows + shift_1_row;
|
||||
const gint shift_4_rows = 2 * shift_2_rows;
|
||||
const gint shift_4_pixels = 2 * shift_2_pixels;
|
||||
|
||||
/*
|
||||
* SECOND AND THIRD BILINEAR WEIGHTS:
|
||||
*
|
||||
* (Note: w = 1-x and z = 1-y.)
|
||||
*/
|
||||
const gdouble w_times_y = y - x_times_y;
|
||||
const gdouble x_times_z = x - x_times_y;
|
||||
|
||||
/*
|
||||
* OVERALL SHIFTS:
|
||||
*/
|
||||
const gint dos_thr_shift = shift_1_row + shift_2_pixels;
|
||||
const gint dos_fou_shift = shift_1_row + shift_3_pixels;
|
||||
|
||||
const gint tre_two_shift = shift_2_rows + shift_1_pixel;
|
||||
const gint tre_thr_shift = shift_2_rows + shift_2_pixels;
|
||||
const gint tre_fou_shift = shift_2_rows + shift_3_pixels;
|
||||
const gint tre_fiv_shift = shift_2_rows + shift_4_pixels;
|
||||
|
||||
const gint qua_two_shift = shift_3_rows + shift_1_pixel;
|
||||
const gint qua_thr_shift = shift_3_rows + shift_2_pixels;
|
||||
const gint qua_fou_shift = shift_3_rows + shift_3_pixels;
|
||||
const gint qua_fiv_shift = shift_3_rows + shift_4_pixels;
|
||||
|
||||
const gint cin_thr_shift = shift_4_rows + shift_2_pixels;
|
||||
const gint cin_fou_shift = shift_4_rows + shift_3_pixels;
|
||||
|
||||
/*
|
||||
* LAST BILINEAR WEIGHT:
|
||||
*/
|
||||
const gdouble w_times_z = 1. - ( x + w_times_y );
|
||||
|
||||
/*
|
||||
* The newval array will contain the four (one per channel)
|
||||
* computed resampled values:
|
||||
*/
|
||||
IN_AND_OUT_TYPE newval[4];
|
||||
|
||||
/*
|
||||
* COMPUTATION OF EACH CHANNEL'S RESAMPLED PIXEL VALUE:
|
||||
*/
|
||||
/*
|
||||
* First channel:
|
||||
*/
|
||||
newval[0] = nohalo1 (w_times_z,
|
||||
x_times_z,
|
||||
w_times_y,
|
||||
x_times_y,
|
||||
uno_one_input_bptr[ dos_thr_shift ],
|
||||
uno_one_input_bptr[ dos_fou_shift ],
|
||||
uno_one_input_bptr[ tre_two_shift ],
|
||||
uno_one_input_bptr[ tre_thr_shift ],
|
||||
uno_one_input_bptr[ tre_fou_shift ],
|
||||
uno_one_input_bptr[ tre_fiv_shift ],
|
||||
uno_one_input_bptr[ qua_two_shift ],
|
||||
uno_one_input_bptr[ qua_thr_shift ],
|
||||
uno_one_input_bptr[ qua_fou_shift ],
|
||||
uno_one_input_bptr[ qua_fiv_shift ],
|
||||
uno_one_input_bptr[ cin_thr_shift ],
|
||||
uno_one_input_bptr[ cin_fou_shift ]);
|
||||
|
||||
/*
|
||||
* Shift input pointer by one channel:
|
||||
*/
|
||||
uno_one_input_bptr++;
|
||||
|
||||
/*
|
||||
* Second channel:
|
||||
*/
|
||||
newval[1] = nohalo1 (w_times_z,
|
||||
x_times_z,
|
||||
w_times_y,
|
||||
x_times_y,
|
||||
uno_one_input_bptr[ dos_thr_shift ],
|
||||
uno_one_input_bptr[ dos_fou_shift ],
|
||||
uno_one_input_bptr[ tre_two_shift ],
|
||||
uno_one_input_bptr[ tre_thr_shift ],
|
||||
uno_one_input_bptr[ tre_fou_shift ],
|
||||
uno_one_input_bptr[ tre_fiv_shift ],
|
||||
uno_one_input_bptr[ qua_two_shift ],
|
||||
uno_one_input_bptr[ qua_thr_shift ],
|
||||
uno_one_input_bptr[ qua_fou_shift ],
|
||||
uno_one_input_bptr[ qua_fiv_shift ],
|
||||
uno_one_input_bptr[ cin_thr_shift ],
|
||||
uno_one_input_bptr[ cin_fou_shift ]);
|
||||
|
||||
uno_one_input_bptr++;
|
||||
|
||||
newval[2] = nohalo1 (w_times_z,
|
||||
x_times_z,
|
||||
w_times_y,
|
||||
x_times_y,
|
||||
uno_one_input_bptr[ dos_thr_shift ],
|
||||
uno_one_input_bptr[ dos_fou_shift ],
|
||||
uno_one_input_bptr[ tre_two_shift ],
|
||||
uno_one_input_bptr[ tre_thr_shift ],
|
||||
uno_one_input_bptr[ tre_fou_shift ],
|
||||
uno_one_input_bptr[ tre_fiv_shift ],
|
||||
uno_one_input_bptr[ qua_two_shift ],
|
||||
uno_one_input_bptr[ qua_thr_shift ],
|
||||
uno_one_input_bptr[ qua_fou_shift ],
|
||||
uno_one_input_bptr[ qua_fiv_shift ],
|
||||
uno_one_input_bptr[ cin_thr_shift ],
|
||||
uno_one_input_bptr[ cin_fou_shift ]);
|
||||
|
||||
uno_one_input_bptr++;
|
||||
|
||||
newval[3] = nohalo1 (w_times_z,
|
||||
x_times_z,
|
||||
w_times_y,
|
||||
x_times_y,
|
||||
uno_one_input_bptr[ dos_thr_shift ],
|
||||
uno_one_input_bptr[ dos_fou_shift ],
|
||||
uno_one_input_bptr[ tre_two_shift ],
|
||||
uno_one_input_bptr[ tre_thr_shift ],
|
||||
uno_one_input_bptr[ tre_fou_shift ],
|
||||
uno_one_input_bptr[ tre_fiv_shift ],
|
||||
uno_one_input_bptr[ qua_two_shift ],
|
||||
uno_one_input_bptr[ qua_thr_shift ],
|
||||
uno_one_input_bptr[ qua_fou_shift ],
|
||||
uno_one_input_bptr[ qua_fiv_shift ],
|
||||
uno_one_input_bptr[ cin_thr_shift ],
|
||||
uno_one_input_bptr[ cin_fou_shift ]);
|
||||
|
||||
/*
|
||||
* Ship out the newval (computed new pixel values):
|
||||
*/
|
||||
babl_process (babl_fish (self->interpolate_format, self->format),
|
||||
newval,
|
||||
output,
|
||||
1);
|
||||
}
|
||||
|
||||
static void
|
||||
vips_interpolate_nohalo_interpolate( VipsInterpolate *interpolate,
|
||||
PEL *out, REGION *in, double x, double y )
|
||||
{
|
||||
VipsInterpolateNohaloClass *nohalo_class =
|
||||
VIPS_INTERPOLATE_NOHALO_GET_CLASS( interpolate );
|
||||
VipsInterpolateNohalo *nohalo = VIPS_INTERPOLATE_NOHALO( interpolate );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We need C linkage for this.
|
||||
|
@ -43,6 +43,79 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Bilinear for float and double types.
|
||||
*/
|
||||
template <typename T> static T inline
|
||||
bilinear_float(
|
||||
const double w_times_z,
|
||||
const double x_times_z,
|
||||
const double w_times_y,
|
||||
const double x_times_y,
|
||||
const double tre_thr,
|
||||
const double tre_thrfou,
|
||||
const double trequa_thr,
|
||||
const double trequa_thrfou )
|
||||
{
|
||||
const T newval =
|
||||
w_times_z * tre_thr +
|
||||
x_times_z * tre_thrfou +
|
||||
w_times_y * trequa_thr +
|
||||
x_times_y * trequa_thrfou;
|
||||
|
||||
return( newval );
|
||||
}
|
||||
|
||||
/* Interpolate for signed integer types.
|
||||
*/
|
||||
template <typename T> static T inline
|
||||
bilinear_signed(
|
||||
const double w_times_z,
|
||||
const double x_times_z,
|
||||
const double w_times_y,
|
||||
const double x_times_y,
|
||||
const double tre_thr,
|
||||
const double tre_thrfou,
|
||||
const double trequa_thr,
|
||||
const double trequa_thrfou )
|
||||
{
|
||||
const double val =
|
||||
(w_times_z / 16) * tre_thr +
|
||||
(x_times_z / 16) * tre_thrfou +
|
||||
(w_times_y / 16) * trequa_thr +
|
||||
(x_times_y / 16) * trequa_thrfou;
|
||||
|
||||
const int sign_of_val = 2 * ( val >= 0. ) - 1;
|
||||
|
||||
const int rounded_abs_val = .5 + sign_of_val * val;
|
||||
|
||||
const T newval = sign_of_val * rounded_abs_val;
|
||||
|
||||
return( newval );
|
||||
}
|
||||
|
||||
/* Interpolate for unsigned integer types.
|
||||
*/
|
||||
template <typename T> static T inline
|
||||
bilinear_unsigned(
|
||||
const double w_times_z,
|
||||
const double x_times_z,
|
||||
const double w_times_y,
|
||||
const double x_times_y,
|
||||
const double tre_thr,
|
||||
const double tre_thrfou,
|
||||
const double trequa_thr,
|
||||
const double trequa_thrfou )
|
||||
{
|
||||
const T newval =
|
||||
(w_times_z / 16) * tre_thr +
|
||||
(x_times_z / 16) * tre_thrfou +
|
||||
(w_times_y / 16) * trequa_thr +
|
||||
(x_times_y / 16) * trequa_thrfou +
|
||||
0.5;
|
||||
|
||||
return( newval );
|
||||
}
|
||||
|
||||
/* Fixed-point integer bicubic, used for 8 and 16-bit types.
|
||||
*/
|
||||
template <typename T> static int inline
|
||||
@ -117,7 +190,7 @@ bicubic_float(
|
||||
|
||||
/* Given an offset in [0,1] (we can have x == 1 when building tables),
|
||||
* calculate c0, c1, c2, c3, the catmull-rom coefficients. This is called
|
||||
* from the interpolator, as well as from the table builder.
|
||||
* from the interpolator as well as from the table builder.
|
||||
*/
|
||||
static void inline
|
||||
calculate_coefficients_catmull( const double x, double c[4] )
|
||||
|
Loading…
x
Reference in New Issue
Block a user