22
22
#include <stdlib.h>
25
27
#include <gavl/gavl.h>
30
#define BLUR_THRESHOLD 5.0e-3
32
/* Conversion between src and dst coordinates */
34
#define DST_TO_SRC(c) ((double)c)/scale_factor+src_off
36
#define ROUND(val) (val >= 0.0) ? (int)(val+0.5):(int)(val-0.5)
38
static void shift_borders(gavl_video_scale_table_t * tab, int src_width);
40
static void normalize_table(gavl_video_scale_table_t * tab);
42
static void alloc_table(gavl_video_scale_table_t * tab,
45
static void check_clip(gavl_video_scale_table_t * tab);
47
static void get_preblur_coeffs(double scale_factor,
48
gavl_video_options_t * opt,
52
static void convolve_preblur(float * src_1, int src_len_1,
53
float * src_2, int src_len_2,
29
57
* Creation of the scale tables, the most ugly part.
30
58
* The tables are for one dimension only, for 2D scaling, we'll have 2 tables.
31
* Nearest neighbour and bilinear scaling routines scale in 2 dimensions at once
32
* using 2 tables. Higher order scaling is done for each dimension separately.
34
60
* We have 3 values: src_size (double), src_off (double)
35
61
* and dst_size (int).
60
86
* - Convert the floating point coefficients to integer with the specified bit
61
* resolution requsted by the scaling routine.
87
* resolution requested by the scaling routine.
66
/* Conversion between src and dst coordinates */
68
#define DST_TO_SRC(c) ((double)c)/scale_factor+src_off
70
#define ROUND(val) (val >= 0.0) ? (int)(val+0.5):(int)(val-0.5)
72
static void shift_borders(gavl_video_scale_table_t * tab, int src_width);
74
static void normalize_table(gavl_video_scale_table_t * tab);
76
static void alloc_table(gavl_video_scale_table_t * tab,
79
91
void gavl_video_scale_table_init(gavl_video_scale_table_t * tab,
80
92
gavl_video_options_t * opt,
81
93
double src_off, double src_size,
82
94
int dst_size, int src_width)
85
99
int i, j, src_index_min, src_index_nearest;
86
100
double src_index_f;
102
float * preblur_factors = (float*)0;
103
int num_preblur_factors = 0;
104
int num_tmp_factors = 0;
105
float * tmp_factors = (float*)0;
88
107
gavl_video_scale_get_weight weight_func;
90
109
double scale_factor;
110
scale_factor = (double)(dst_size) / src_size;
114
if(scale_factor < 1.0)
116
switch(opt->downscale_filter)
118
case GAVL_DOWNSCALE_FILTER_AUTO: //!< Auto selection based on quality
123
get_preblur_coeffs(scale_factor,
125
&num_preblur_factors,
129
case GAVL_DOWNSCALE_FILTER_NONE: //!< Fastest method, might produce heavy aliasing artifacts
131
case GAVL_DOWNSCALE_FILTER_WIDE: //!< Widen the filter curve according to the scaling ratio.
132
if(opt->downscale_blur > BLUR_THRESHOLD)
135
case GAVL_DOWNSCALE_FILTER_GAUSS: //!< Do a Gaussian preblur
136
get_preblur_coeffs(scale_factor,
138
&num_preblur_factors,
92
144
// src_off = -0.25;
94
146
/* Get the kernel generator */
97
149
gavl_video_scale_get_weight_func(opt, &(tab->factors_per_pixel));
151
num_tmp_factors = tab->factors_per_pixel;
153
if(num_preblur_factors)
155
tmp_factors = malloc(sizeof(*tmp_factors) * num_tmp_factors);
157
tab->factors_per_pixel += num_preblur_factors - 1;
162
widen_factor = ceil(opt->downscale_blur / scale_factor);
163
tab->factors_per_pixel *= (int)(widen_factor);
99
169
// fprintf(stderr, "tab->factors_per_pixel: %d, src_width: %d\n",
100
170
// tab->factors_per_pixel, src_width);
102
173
if(tab->factors_per_pixel > src_width)
104
175
switch(src_width)
147
217
src_index_nearest = ROUND(src_index_f);
149
src_index_min = src_index_nearest - tab->factors_per_pixel/2;
219
tab->pixels[i].index = src_index_nearest - tab->factors_per_pixel/2;
220
src_index_min = src_index_nearest - num_tmp_factors/2;
151
222
if(((double)src_index_nearest < src_index_f) && !(tab->factors_per_pixel % 2))
225
tab->pixels[i].index++;
156
tab->pixels[i].index = src_index_min;
158
// fprintf(stderr, "src_index_f: %f, src_index_nearest: %d, src_index_min: %d, dst_index: %d\n",
159
// src_index_f, src_index_nearest, src_index_min, i);
228
// fprintf(stderr, "src_index_f: %f, src_index_nearest: %d, src_index_min: %d, pixel.index: %d, dst_index: %d\n",
229
// src_index_f, src_index_nearest, src_index_min,
230
// tab->pixels[i].index,
161
233
/* For nearest neighbour, we don't need any factors */
162
234
if(tab->factors_per_pixel == 1)
171
243
/* Normalized distance of the destination pixel to the first source pixel
172
244
in src coordinates */
173
t = src_index_f - src_index_min;
246
if(num_preblur_factors)
248
t = (src_index_f - src_index_min)/widen_factor;
249
for(j = 0; j < num_tmp_factors; j++)
251
tmp_factors[j] = weight_func(opt, t);
252
// fprintf(stderr, "j: %d, t: %f, w: %f\n", j, t, weight_func(opt, t));
256
convolve_preblur(tmp_factors, num_tmp_factors,
257
preblur_factors, num_preblur_factors,
258
tab->pixels[i].factor_f);
262
t = (src_index_f - tab->pixels[i].index)/widen_factor;
263
for(j = 0; j < tab->factors_per_pixel; j++)
265
tab->pixels[i].factor_f[j] = weight_func(opt, t);
266
// fprintf(stderr, "j: %d, t: %f, w: %f\n", j, t, weight_func(opt, t));
267
t -= 1.0 /widen_factor;
175
271
for(j = 0; j < tab->factors_per_pixel; j++)
177
tab->pixels[i].factor_f[j] = weight_func(opt, t);
178
// fprintf(stderr, "t: %f, w: %f\n", t, weight_func(opt, t));
273
fprintf(stderr, "%d %f\n", j,
274
tab->pixels[i].factor_f[j]);
183
279
// fprintf(stderr, "Before shift\n");
184
280
// gavl_video_scale_table_dump(tab);
186
282
shift_borders(tab, src_width);
188
if(opt->scale_mode == GAVL_SCALE_SINC_LANCZOS)
189
normalize_table(tab);
283
// if(opt->scale_mode == GAVL_SCALE_SINC_LANCZOS)
284
normalize_table(tab);
291
free(preblur_factors);
191
293
// fprintf(stderr, "After shift %d\n", src_width);
192
294
//if(deinterlace || (total_fields == 2))
193
295
// gavl_video_scale_table_dump(tab);
258
367
for(j = 0; j < tab->factors_per_pixel; j++)
259
368
sum += tab->pixels[i].factor_f[j];
370
/* This is to prevent accidental setting of clipping functions due to
371
rounding errors. For usual applications, it should not be noticable
261
375
// fprintf(stderr, "sum: %f\n", sum);
263
377
for(j = 0; j < tab->factors_per_pixel; j++)
264
378
tab->pixels[i].factor_f[j] /= sum;
268
383
/* Shift the borders of the table such that no indices are out of range.
608
static void check_clip(gavl_video_scale_table_t * tab)
615
for(i = 0; i < tab->num_pixels; i++)
618
for(j = 0; j < tab->factors_per_pixel; j++)
620
sum += tab->pixels[i].factor_f[j];
622
if(tab->pixels[i].factor_f[j] < 0.0 ||
623
tab->pixels[i].factor_f[j] > 1.0)
637
static void get_preblur_coeffs(double scale_factor,
638
gavl_video_options_t * opt,
644
/* Gaussian lowpass */
645
if(opt->downscale_filter == GAVL_DOWNSCALE_FILTER_GAUSS)
649
float f_co = 0.25 * scale_factor;
650
int n = (int)(ceil(0.398 / f_co));
652
if(n && (opt->downscale_blur >= BLUR_THRESHOLD))
654
*num_ret = 2 * n + 1;
655
*coeffs_ret = malloc(*num_ret * sizeof(**coeffs_ret));
657
for(i = -n; i <= n; i++)
659
tmp = 3.011 * f_co * (float)i / opt->downscale_blur;
660
(*coeffs_ret)[i+n] = exp(-M_PI * tmp * tmp);
670
static void convolve_preblur(float * src_1, int src_len_1,
671
float * src_2, int src_len_2,
676
nmax = src_len_1 + src_len_2 - 1;
678
for(n = 0; n < nmax; n++)
682
for(m = 0; m < src_len_1; m++)
684
if((n - m >= 0) && (n - m < src_len_2))
685
dst[n] += src_1[m] * src_2[n-m];