20#define resampler_assert assert
30#define max(a,b) (((a) > (b)) ? (a) : (b))
34#define min(a,b) (((a) < (b)) ? (a) : (b))
45#define RESAMPLER_DEBUG 0
47#define M_PI 3.14159265358979323846
56static inline int posmod(
int x,
int y)
75#define BOX_FILTER_SUPPORT (0.5f)
79 if ((t >= -0.5f) && (t < 0.5f))
85#define TENT_FILTER_SUPPORT (1.0f)
97#define BELL_SUPPORT (1.5f)
104 return (.75f - (t * t));
109 return (.5f * (t * t));
115#define B_SPLINE_SUPPORT (2.0f)
126 return ((.5f * tt * t) - tt + (2.0f / 3.0f));
131 return ((1.0f / 6.0f) * (t * t * t));
138#define QUADRATIC_SUPPORT 1.5f
147 return (-2.0f * R) * tt + .5f * (R + 1.0f);
149 return (R * tt) + (-2.0f * R - .5f) * t + (3.0f / 4.0f) * (R + 1.0f);
189 t = (((12.0f - 9.0f * B - 6.0f * C) * (t * tt))
190 + ((-18.0f + 12.0f * B + 6.0f * C) * tt)
191 + (6.0f - 2.0f * B));
197 t = (((-1.0f * B - 6.0f * C) * (t * tt))
198 + ((6.0f * B + 30.0f * C) * tt)
199 + ((-12.0f * B - 48.0f * C) * t)
200 + (8.0f * B + 24.0f * C));
208#define MITCHELL_SUPPORT (2.0f)
211 return mitchell(t, 1.0f / 3.0f, 1.0f / 3.0f);
214#define CATMULL_ROM_SUPPORT (2.0f)
224 if ((x < 0.01f) && (x > -0.01f))
225 return 1.0f + x * x * (-1.0f / 6.0f + x * x * 1.0f / 120.0f);
233 if (fabs(t) < EPSILON)
245 return 0.42659071f + 0.49656062f * cos(
M_PI * x) + 0.07684867f * cos(2.0f *
M_PI * x);
248#define BLACKMAN_SUPPORT (3.0f)
261#define GAUSSIAN_SUPPORT (1.25f)
273#define LANCZOS3_SUPPORT (3.0f)
285#define LANCZOS4_SUPPORT (4.0f)
297#define LANCZOS6_SUPPORT (6.0f)
309#define LANCZOS12_SUPPORT (12.0f)
323 const double EPSILON_RATIO = 1E-16;
324 double xh, sum, pow, ds;
332 while (ds > sum * EPSILON_RATIO)
335 pow = pow * (xh / k);
344static double kaiser(
double alpha,
double half_width,
double x)
346 const double ratio = (x / half_width);
350#define KAISER_SUPPORT 3
421 n = (src_x - j) + (src_x - 1);
453 int i, j, k, n, left, right;
459 Contrib_Bounds* Pcontrib_bounds;
464 Pcontrib_bounds = (Contrib_Bounds*)calloc(dst_x,
sizeof(Contrib_Bounds));
465 if (!Pcontrib_bounds)
486 half_width = (filter_support / xscale) * filter_scale;
490 for (i = 0, n = 0; i < dst_x; i++)
500 Pcontrib_bounds[i].center = center;
501 Pcontrib_bounds[i].left = left;
502 Pcontrib_bounds[i].right = right;
504 n += (right - left + 1);
509 if ((n == 0) || ((Pcpool = (
Contrib*)calloc(n,
sizeof(
Contrib))) == NULL))
512 free(Pcontrib_bounds);
517 Pcpool_next = Pcpool;
523 for (i = 0; i < dst_x; i++)
528 center = Pcontrib_bounds[i].center;
529 left = Pcontrib_bounds[i].left;
530 right = Pcontrib_bounds[i].right;
533 Pcontrib[i].
p = Pcpool_next;
534 Pcpool_next += (right - left + 1);
539 for (j = left; j <= right; j++)
540 total_weight += (*Pfilter)((center - (
Resample_Real)j) * xscale * oo_filter_scale);
549 for (j = left; j <= right; j++)
551 weight = (*Pfilter)((center - (
Resample_Real)j) * xscale * oo_filter_scale) * norm;
555 n =
reflect(j, src_x, boundary_op);
558 printf(
"%i(%f), ", n, weight);
568 Pcontrib[i].
p[k].
pixel = (
unsigned short)(n);
569 Pcontrib[i].
p[k].
weight = weight;
571 total_weight += weight;
586 if ((max_k == -1) || (Pcontrib[i].n == 0))
590 free(Pcontrib_bounds);
594 if (total_weight != 1.0f)
595 Pcontrib[i].
p[max_k].
weight += 1.0f - total_weight;
605 half_width = filter_support * filter_scale;
609 for (i = 0, n = 0; i < dst_x; i++)
619 Pcontrib_bounds[i].center = center;
620 Pcontrib_bounds[i].left = left;
621 Pcontrib_bounds[i].right = right;
623 n += (right - left + 1);
629 if ((total == 0) || ((Pcpool = (
Contrib*)calloc(total,
sizeof(
Contrib))) == NULL))
632 free(Pcontrib_bounds);
636 Pcpool_next = Pcpool;
642 for (i = 0; i < dst_x; i++)
647 center = Pcontrib_bounds[i].center;
648 left = Pcontrib_bounds[i].left;
649 right = Pcontrib_bounds[i].right;
652 Pcontrib[i].
p = Pcpool_next;
653 Pcpool_next += (right - left + 1);
657 for (j = left; j <= right; j++)
658 total_weight += (*Pfilter)((center - (
Resample_Real)j) * oo_filter_scale);
668 for (j = left; j <= right; j++)
670 weight = (*Pfilter)((center - (
Resample_Real)j) * oo_filter_scale) * norm;
674 n =
reflect(j, src_x, boundary_op);
677 printf(
"%i(%f), ", n, weight);
687 Pcontrib[i].
p[k].
pixel = (
unsigned short)(n);
688 Pcontrib[i].
p[k].
weight = weight;
690 total_weight += weight;
706 if ((max_k == -1) || (Pcontrib[i].n == 0))
710 free(Pcontrib_bounds);
714 if (total_weight != 1.0f)
715 Pcontrib[i].
p[max_k].
weight += 1.0f - total_weight;
723 free(Pcontrib_bounds);
740#if RESAMPLER_DEBUG_OPS
744 for (j = Pclist->
n, p = Pclist->
p, total = 0; j > 0; j--, p++)
759#if RESAMPLER_DEBUG_OPS
764 for (i = dst_x; i > 0; i--)
765 *Ptmp++ = *Psrc++ * weight;
770#if RESAMPLER_DEBUG_OPS
774 for (
int i = dst_x; i > 0; i--)
775 (*Ptmp++) += *Psrc++ * weight;
799 for (i = 0; i < Pclist->
n; i++)
955#if RESAMPLER_DEBUG_OPS
1032 int dst_x,
int dst_y,
1035 const char* Pfilter_name,
1051#if RESAMPLER_DEBUG_OPS
1086 if (Pfilter_name == NULL)
1181#if RESAMPLER_DEBUG_OPS
1184 printf(
"x_ops: %i\n", x_ops);
1185 printf(
"y_ops: %i\n", y_ops);
1186 printf(
"xy_ops: %i\n", xy_ops);
1187 printf(
"yx_ops: %i\n", yx_ops);
1192 if ((xy_ops > yx_ops) ||
1204#if RESAMPLER_DEBUG_OPS
1235 if ((filter_num < 0) || (filter_num >=
NUM_FILTERS))
Contrib_List * m_Pclist_x
void get_clists(Contrib_List **ptr_clist_x, Contrib_List **ptr_clist_y)
static int get_filter_num()
const Sample * get_line()
Resample_Real clamp_sample(Resample_Real f) const
Boundary_Op m_boundary_op
int count_ops(Contrib_List *Pclist, int k)
Contrib_List * make_clist(int src_x, int dst_x, Boundary_Op boundary_op, Resample_Real(*Pfilter)(Resample_Real), Resample_Real filter_support, Resample_Real filter_scale, Resample_Real src_ofs)
Contrib_List * m_Pclist_y
static char * get_filter_name(int filter_num)
void scale_y_add(Sample *Ptmp, const Sample *Psrc, Resample_Real weight, int dst_x)
bool put_line(const Sample *Psrc)
void scale_y_mov(Sample *Ptmp, const Sample *Psrc, Resample_Real weight, int dst_x)
unsigned char * m_Psrc_y_flag
int reflect(const int j, const int src_x, const Boundary_Op boundary_op)
void clamp(Sample *Pdst, int n)
void resample_x(Sample *Pdst, const Sample *Psrc)
@ STATUS_SCAN_BUFFER_FULL
void resample_y(Sample *Pdst)
CONSTCD14 std::enable_if< detail::no_overflow< Period, typenameTo::period >::value, To >::type floor(const std::chrono::duration< Rep, Period > &d)
CONSTCD14 To ceil(const std::chrono::duration< Rep, Period > &d)
bool isnan(const value_type &v)
static Resample_Real box_filter(Resample_Real t)
static int resampler_range_check(int v, int h)
static Resample_Real B_spline_filter(Resample_Real t)
static Resample_Real lanczos3_filter(Resample_Real t)
static Resample_Real mitchell_filter(Resample_Real t)
static Resample_Real lanczos6_filter(Resample_Real t)
static Resample_Real bell_filter(Resample_Real t)
#define BOX_FILTER_SUPPORT
static int cast_to_int(Resample_Real i)
static Resample_Real clean(double t)
static Resample_Real quadratic_interp_filter(Resample_Real t)
static double sinc(double x)
static Resample_Real mitchell(Resample_Real t, const Resample_Real B, const Resample_Real C)
#define TENT_FILTER_SUPPORT
static double blackman_exact_window(double x)
static Resample_Real kaiser_filter(Resample_Real t)
#define LANCZOS12_SUPPORT
static Resample_Real quadratic_mix_filter(Resample_Real t)
#define CATMULL_ROM_SUPPORT
static Resample_Real lanczos4_filter(Resample_Real t)
static Resample_Real catmull_rom_filter(Resample_Real t)
static double kaiser(double alpha, double half_width, double x)
static Resample_Real lanczos12_filter(Resample_Real t)
static Resample_Real blackman_filter(Resample_Real t)
static int posmod(int x, int y)
static const int NUM_FILTERS
static const Resample_Real KAISER_ALPHA
static double bessel0(double x)
static Resample_Real gaussian_filter(Resample_Real t)
static Resample_Real quadratic(Resample_Real t, const Resample_Real R)
static struct @9 g_filters[]
Resample_Real(* func)(Resample_Real t)
static Resample_Real quadratic_approx_filter(Resample_Real t)
static Resample_Real tent_filter(Resample_Real t)
#define QUADRATIC_SUPPORT
#define RESAMPLER_DEFAULT_FILTER
int scan_buf_y[MAX_SCAN_BUF_SIZE]
Sample * scan_buf_l[MAX_SCAN_BUF_SIZE]