Streamtools: Refactor rescaling code
[jpcrr.git] / streamtools / rescalers / lanczos.cpp
blob96add40951186c4fa2cb7f5bf3bb99d18b75d575
1 #include "rescalers/linear-separable.hpp"
2 #include <stdint.h>
3 #include <cmath>
4 #include <stdexcept>
6 namespace
8 double pi = 3.1415926535897932384626;
10 //num / denum = x * swidth / twidth
11 // swidth = n * twidth => x * n
12 // twdith = n * swidth => x / n
14 void compute_coefficients_lanczos(float* coeffs, position_t num, position_t denum, position_t width,
15 position_t twidth, unsigned& count, unsigned& base, int a)
17 if(a == 0)
18 throw std::runtime_error("Parameter alpha must be positive in lanczos rescaler");
20 if(2 * a + 1 <= a)
21 throw std::runtime_error("Parameter alpha way too large in lanczos rescaler");
23 if(2 * a + 1 > MAXCOEFFICIENTS)
24 throw std::runtime_error("Parameter alpha value would require more coefficients than "
25 "supported");
27 count = 0;
28 base = 0;
29 bool base_set = false;
30 position_t centralpoint = num / denum;
31 for(int i = -a + 1; i <= a; i++) {
32 position_t point = centralpoint + i;
34 if(point < 0 || point >= width)
35 continue; //Out of range.
36 if(!base_set) {
37 base_set = true;
38 base = (unsigned)point;
40 double x = point + 0.5 - (double)num / denum - 0.5 * width / twidth;
41 if(x < -1e-10 || x > 1e-10) {
42 double xpi = x * pi;
43 coeffs[count++] = a * sin(xpi) * sin(xpi / a) / ((xpi) * (xpi));
44 } else {
45 coeffs[count++] = 1;
50 void compute_coefficients_average(float* coeffs, position_t num, position_t denum, position_t width,
51 position_t twidth, unsigned& count, unsigned& base)
53 signed lowbound, highbound, scan;
55 lowbound = num;
56 highbound = num + width;
57 scan = lowbound - lowbound % denum;
59 if((width + denum - 1) / denum > MAXCOEFFICIENTS)
60 throw std::runtime_error("Conversion would require more coefficients than supported");
62 base = scan / denum;
63 *coeffs = (scan + denum) - lowbound;
64 count = 1;
65 scan = scan + denum;
66 while(scan < highbound) {
67 if(scan + denum > highbound)
68 coeffs[count++] = highbound - scan;
69 else
70 coeffs[count++] = denum;
72 scan = scan + denum;
76 simple_rescaler_linear_separable r_average("average", make_bound_method(compute_coefficients_average));
77 simple_rescaler_linear_separable r_lanczos1("lanczos1", bind_last<void, int, float*, position_t, position_t,
78 position_t, position_t, unsigned&, unsigned&>(make_bound_method(compute_coefficients_lanczos), 1));
79 simple_rescaler_linear_separable r_lanczos2("lanczos2", bind_last<void, int, float*, position_t, position_t,
80 position_t, position_t, unsigned&, unsigned&>(make_bound_method(compute_coefficients_lanczos), 2));
81 simple_rescaler_linear_separable r_lanczos3("lanczos3", bind_last<void, int, float*, position_t, position_t,
82 position_t, position_t, unsigned&, unsigned&>(make_bound_method(compute_coefficients_lanczos), 3));
83 simple_rescaler_linear_separable r_lanczos4("lanczos4", bind_last<void, int, float*, position_t, position_t,
84 position_t, position_t, unsigned&, unsigned&>(make_bound_method(compute_coefficients_lanczos), 4));
85 simple_rescaler_linear_separable r_lanczos5("lanczos5", bind_last<void, int, float*, position_t, position_t,
86 position_t, position_t, unsigned&, unsigned&>(make_bound_method(compute_coefficients_lanczos), 5));