reordered code to move branches far from what they depend on and cleaned comments

This commit is contained in:
Nicolas Robidoux 2009-03-18 00:41:57 +00:00
parent ca1bdeda29
commit 85a28bf941
1 changed files with 77 additions and 70 deletions

View File

@ -1,7 +1,7 @@
/* nohalo interpolator
/* nohalo level 1 interpolator
*
* Hacked for vips by J. Cupitt, 20/1/09
* Tweaks by N. Robidoux and J. Cupitt 5-15/03/09
* Tweaks by N. Robidoux and J. Cupitt 3/09
*
* 16/3/09
* - rename as nohalo1
@ -53,7 +53,8 @@
*
* "Nohalo" is a family of parameterized resamplers with a mission:
* smoothly straightening oblique lines without undesirable
* side-effects.
* side-effects. In particular, without much blurring and with
* absolutely no added haloing.
*
* The key parameter, which may be described as a "quality" parameter,
* is an integer which specifies the number of "levels" of binary
@ -93,12 +94,12 @@
* Nohalo is co-monotone (this is why it's called "nohalo")
* ========================================================
*
* What monotonicity means here is that the resampled value is in the
* range of the four closest input values. Consequently, nohalo does
* not add haloing. It also means that clamping is unnecessary
* (provided abyss values are within the range of acceptable values,
* which is always the case). (Note: plain vanilla bilinear is also
* co-monotone.)
* What monotonicity more or less means here is that the resampled
* value is in the range of the four closest input values. This
* property is why there is no added haloing. It also implies that
* clamping is unnecessary (provided abyss values are within the range
* of acceptable values, which is always the case). (Note: plain
* vanilla bilinear is also co-monotone.)
*
* Note: If the abyss policy is an extrapolating one---for example,
* linear or bilinear extrapolation---clamping is still unnecessary
@ -290,37 +291,44 @@ nohalo1( const double uno_two,
* Nohalo's stencil is the same as, say, Catmull-Rom, with the
* exception that the four corner values are not used:
*
* (ix-1,iy-2) (ix,iy-2)
* (ix,iy-1) (ix+1,iy-1)
* = uno_two = uno_thr
*
* (ix-2,iy-1) (ix-1,iy-1) (ix,iy-1) (ix+1,iy-1)
* (ix-1,iy) (ix,iy) (ix+1,iy) (ix+2,iy)
* = dos_one = dos_two = dos_thr = dos_fou
*
* (ix-2,iy) (ix-1,iy) (ix,iy) (ix+1,iy)
* (ix-1,iy+1) (ix,iy+1) (ix+1,iy+1) (ix+2,iy+1)
* = tre_one = tre_two = tre_thr = tre_fou
*
* (ix-1,iy+1) (ix,iy+1)
* (ix,iy+2) (ix+1,iy+2)
* = qua_two = qua_thr
*
* The indices associated with the values shown above are in the
* case that the resampling point is closer to (ix-1,iy-1) than the
* other three central positions. Pointer arithmetic is used to
* implicitly reflect the input stencil in the other three cases,
* For example, if the sampling position is closer to dos_two (that
* is, if relative_x_is_rite = 1 but relative_y_is_down = 0 below),
* then dos_two corresponds to (ix,iy-1), dos_thr corresponds to
* (ix-1,iy-1) etc. Consequently, the three missing double density
* values are halfway between dos_two and dos_thr, halfway between
* Here, ix is the floor of the requested left-to-right location, iy
* is the floor of the requested up-to-down location.
*
* Pointer arithmetic is used to implicitly reflect the input
* stencil so that the requested pixel location is closer to
* dos_two, The above consequently corresponds to the case in which
* absolute_x is closer to ix than ix+1, and absolute_y is closer to
* iy than iy+1. For example, if relative_x_is_rite = 1 but
* relative_y_is_down = 0 (see below), then dos_two corresponds to
* (ix+1,iy), dos_thr corresponds to (ix,iy) etc. Consequently, the
* three missing double density values (corresponding to r1, r2 and
* r3) are halfway between dos_two and dos_thr, halfway between
* dos_two and tre_two, and at the average of the four central
* positions.
*
* The following code assumes that the stencil reflection has
* already been performed.
*/
/*
* Computation of the nonlinear slopes: If two consecutive pixel
* value differences have the same sign, the smallest one (in
* absolute value) is taken to be the corresponding slope; if the
* two consecutive pixel value differences don't have the same sign,
* the corresponding slope is set to 0. (In other words, apply
* minmod to comsecutive slopes.)
* the corresponding slope is set to 0. In other words, apply minmod
* to comsecutive differences.
*/
/*
* Dos(s) horizontal differences:
@ -348,13 +356,7 @@ nohalo1( const double uno_two,
const double troi_thr = qua_thr - tre_thr;
/*
* Useful sums:
*/
const double dos_two_plus_dos_thr = dos_two + dos_thr;
const double dos_two_plus_tre_two = dos_two + tre_two;
/*
* Products useful for minmod:
* Products and differences useful for minmod:
*/
const double deux_prem_dos = deux_dos * prem_dos;
const double deux_deux_dos = deux_dos * deux_dos;
@ -364,6 +366,12 @@ nohalo1( const double uno_two,
const double deux_deux_two = deux_two * deux_two;
const double deux_troi_two = deux_two * troi_two;
const double deux_prem_minus_deux_deux_dos = deux_prem_dos - deux_deux_dos;
const double deux_troi_minus_deux_deux_dos = deux_troi_dos - deux_deux_dos;
const double deux_prem_minus_deux_deux_two = deux_prem_two - deux_deux_two;
const double deux_troi_minus_deux_deux_two = deux_troi_two - deux_deux_two;
const double deux_prem_tre = deux_tre * prem_tre;
const double deux_deux_tre = deux_tre * deux_tre;
const double deux_troi_tre = deux_tre * troi_tre;
@ -372,26 +380,19 @@ nohalo1( const double uno_two,
const double deux_deux_thr = deux_thr * deux_thr;
const double deux_troi_thr = deux_thr * troi_thr;
/*
* Useful sum:
*/
const double deux_thr_plus_deux_dos = deux_thr + deux_dos;
/*
* Differences useful for minmod:
*/
const double deux_prem_minus_deux_deux_dos = deux_prem_dos - deux_deux_dos;
const double deux_troi_minus_deux_deux_dos = deux_troi_dos - deux_deux_dos;
const double deux_prem_minus_deux_deux_two = deux_prem_two - deux_deux_two;
const double deux_troi_minus_deux_deux_two = deux_troi_two - deux_deux_two;
const double deux_prem_minus_deux_deux_tre = deux_prem_tre - deux_deux_tre;
const double deux_troi_minus_deux_deux_tre = deux_troi_tre - deux_deux_tre;
const double deux_prem_minus_deux_deux_thr = deux_prem_thr - deux_deux_thr;
const double deux_troi_minus_deux_deux_thr = deux_troi_thr - deux_deux_thr;
/*
* Useful sums:
*/
const double dos_two_plus_dos_thr = dos_two + dos_thr;
const double dos_two_plus_tre_two = dos_two + tre_two;
const double deux_thr_plus_deux_dos = deux_thr + deux_dos;
/*
* Compute the needed "right" (at the boundary between one input
* pixel areas) double resolution pixel value:
@ -429,14 +430,14 @@ nohalo1( const double uno_two,
2. * deux_thr_plus_deux_dos;
const double eight_times_dostre_twothr =
piece_of_eight_times_dostre_twothr
+
FAST_MINMOD( deux_tre, prem_tre, deux_prem_tre,
deux_prem_minus_deux_deux_tre )
-
FAST_MINMOD( deux_tre, troi_tre, deux_troi_tre,
deux_troi_minus_deux_deux_tre )
+
piece_of_eight_times_dostre_twothr
+
FAST_MINMOD( deux_thr, prem_thr, deux_prem_thr,
deux_prem_minus_deux_deux_thr )
-
@ -466,42 +467,45 @@ nohalo1( const double uno_two,
{ \
T* restrict out = (T *) pout; \
\
const int relative_x_is_rite = ( relative_x >= 0. ); \
const int relative_y_is_down = ( relative_y >= 0. ); \
const int relative_x_is_rite = ( relative_x >= 0. ); \
\
const int sign_of_relative_x = 2 * relative_x_is_rite - 1; \
const int sign_of_relative_y = 2 * relative_y_is_down - 1; \
const int sign_of_relative_x = 2 * relative_x_is_rite - 1; \
\
const int corner_reflection_shift = \
relative_x_is_rite * bands + relative_y_is_down * lskip; \
relative_y_is_down * lskip + relative_x_is_rite * bands; \
\
const int shift_1_row = sign_of_relative_y * lskip; \
const int shift_1_pixel = sign_of_relative_x * bands; \
\
const T* restrict in = ( (T *) pin ) + corner_reflection_shift; \
\
const int shift_1_pixel = sign_of_relative_x * bands; \
const int shift_1_row = sign_of_relative_y * lskip; \
\
const double w = ( 2 * sign_of_relative_x ) * relative_x; \
const double z = ( 2 * sign_of_relative_y ) * relative_y; \
\
const int uno_two_shift = shift_1_row; \
const int uno_thr_shift = shift_1_row - shift_1_pixel; \
\
const int dos_one_shift = shift_1_pixel; \
const int dos_two_shift = 0; \
const int dos_thr_shift = -shift_1_pixel; \
const int dos_fou_shift = -2 * shift_1_pixel; \
\
const double w = ( 2 * sign_of_relative_x ) * relative_x; \
const double z = ( 2 * sign_of_relative_y ) * relative_y; \
\
const int dos_fou_shift = 2 * dos_thr_shift; \
\
const double x = 1. - w; \
\
const int tre_one_shift = dos_one_shift - shift_1_row; \
const int tre_two_shift = -shift_1_row; \
const int tre_thr_shift = dos_thr_shift - shift_1_row; \
const int tre_fou_shift = dos_fou_shift - shift_1_row; \
\
const double w_times_z = w * z; \
const double x_times_z = x * z; \
\
const int qua_two_shift = tre_two_shift - shift_1_row; \
const int qua_thr_shift = tre_thr_shift - shift_1_row; \
\
const double x = 1. - w; \
const double w_times_z = w * z; \
const double x_times_z = x * z; \
const double w_times_y_over_4 = .25 * ( w - w_times_z ); \
const double x_times_z_over_4 = .25 * x_times_z; \
const double x_times_y_over_8 = .125 * ( x - x_times_z ); \
@ -559,14 +563,13 @@ vips_interpolate_nohalo1_interpolate( VipsInterpolate* restrict interpolate,
double absolute_y )
{
/*
* VIPS versions of Nicolas's pixel addressing values. Double bands for
* complex images.
* 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 bands_actual = in->im->Bands;
const int bands =
( im_iscomplex( in->im ) ? 2 * bands_actual : bands_actual );
const double absolute_y_minus_half = absolute_y - .5;
const double absolute_x_minus_half = absolute_x - .5;
/*
* 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
@ -580,20 +583,24 @@ vips_interpolate_nohalo1_interpolate( VipsInterpolate* restrict interpolate,
* position of the center of the convex hull of the 2x2 block of
* closest pixels. Similarly for y. Range of values: [-.5,.5).
*/
const double absolute_y_minus_half = absolute_y - .5;
const double absolute_x_minus_half = absolute_x - .5;
const int iy = FAST_PSEUDO_FLOOR (absolute_y);
const double relative_y = absolute_y_minus_half - iy;
const int ix = FAST_PSEUDO_FLOOR (absolute_x);
const double relative_x = absolute_x_minus_half - ix;
/*
* 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:
* 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 );
/*
* Double bands for complex images:
*/
const int bands =
( im_iscomplex( in->im ) ? 2 * actual_bands : actual_bands );
#define CALL( T, inter ) \
nohalo1_ ## inter<T>( out, \
p, \