1
/*****************************************************************
5
Copyright (c) 2005 by Burkhard Plaum - plaum@ipf.uni-stuttgart.de
7
http://gmerlin.sourceforge.net
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
18
*****************************************************************/
23
#include <gavl/gavl.h>
27
* Creation of the scale tables, the most ugly part.
28
* The tables are for one dimension only, for 2D scaling, we'll have 2 tables.
29
* Nearest neighbour and bilinear scaling routines scale in 2 dimensions at once
30
* using 2 tables. Higher order scaling is done for each dimension separately.
32
* We have 3 values: src_size (double), src_off (double)
35
* The scale factor is dst_size / src_size. src_off is the coordinate of the
36
* first destination pixel in source coordinates.
38
* When src_offset is zero, we'll have a pattern like this
39
* (for upscaling by a factor of 2):
42
* dst: | x | x | x | x |
44
* For a src_offset of -0.25, we'll have
47
* dst: | x | x | x | x |
49
* The table is created in the follwing steps:
51
* - Calculate the floating point filter coefficiens for each destination pixel
53
* - Shift the indixes of the source pixels such that no source pixels are outside
54
* the image. The nonexistant pixels beyond the borders (whose values are needed
55
* for scaling) are assumed to have the same color as the nearest pixel at the
58
* - Convert the floating point coefficients to integer with the specified bit
59
* resolution requsted by the scaling routine.
64
/* Conversion between src and dst coordinates */
66
#define DST_TO_SRC(c) ((double)c)/scale_factor+src_off
68
#define ROUND(val) (val >= 0.0) ? (int)(val+0.5):(int)(val-0.5)
70
static void shift_borders(gavl_video_scale_table_t * tab, int src_width);
72
static void normalize_table(gavl_video_scale_table_t * tab);
74
void gavl_video_scale_table_init(gavl_video_scale_table_t * tab,
75
gavl_video_options_t * opt,
76
double src_off, double src_size,
77
int dst_size, int src_width)
80
int i, j, src_index_min, src_index_nearest;
83
gavl_video_scale_get_weight weight_func;
89
/* Get the kernel generator */
91
// fprintf(stderr, "src_off: %f\n", src_off);
93
weight_func = gavl_video_scale_get_weight_func(opt, &(tab->factors_per_pixel));
95
// fprintf(stderr, "gavl_video_scale_table_init: %f %f %d %d\n",
96
// src_off, src_size, dst_size, tab->factors_per_pixel);
98
/* (Re)allocate memory */
100
if(tab->pixels_alloc < dst_size)
102
tab->pixels_alloc = dst_size + 128;
103
tab->pixels = realloc(tab->pixels, tab->pixels_alloc * sizeof(*(tab->pixels)));
106
tab->num_pixels = dst_size;
108
if(tab->factors_alloc < dst_size * tab->factors_per_pixel)
110
tab->factors_alloc = dst_size * tab->factors_per_pixel + 128;
111
tab->factors = realloc(tab->factors, tab->factors_alloc * sizeof(*(tab->factors)));
114
scale_factor = (double)(dst_size) / src_size;
116
for(i = 0; i < dst_size; i++)
118
/* Set the factor pointers */
119
tab->pixels[i].factor = tab->factors + i * tab->factors_per_pixel;
121
/* src_index_f: Fractional source index */
122
/* src_index_nearest: Nearest integer source index */
124
src_index_f = DST_TO_SRC((double)i);
126
// fprintf(stderr, "dst: %d -> src: %f (offset: s: %.2f)\n", i, src_index_f,
129
// if(src_index_f > src_size - 1.0)
130
// src_index_f = src_size - 1.0;
132
src_index_nearest = ROUND(src_index_f);
134
src_index_min = src_index_nearest - tab->factors_per_pixel/2;
136
if(((double)src_index_nearest < src_index_f) && !(tab->factors_per_pixel % 2))
141
tab->pixels[i].index = src_index_min;
143
// fprintf(stderr, "src_index_f: %f, src_index_nearest: %d, src_index_min: %d, dst_index: %d\n",
144
// src_index_f, src_index_nearest, src_index_min, i);
146
/* For nearest neighbour, we don't need any factors */
147
if(tab->factors_per_pixel == 1)
149
if(tab->pixels[i].index < 0)
150
tab->pixels[i].index = 0;
151
if(tab->pixels[i].index > src_width - 1)
152
tab->pixels[i].index = src_width - 1;
156
/* Normalized distance of the destination pixel to the first source pixel
157
in src coordinates */
158
t = src_index_f - src_index_min;
160
for(j = 0; j < tab->factors_per_pixel; j++)
162
tab->pixels[i].factor[j].fac_f = weight_func(opt, t);
163
// fprintf(stderr, "t: %f, w: %f\n", t, weight_func(opt, t));
168
// fprintf(stderr, "Before shift\n");
169
// gavl_video_scale_table_dump(tab);
171
shift_borders(tab, src_width);
173
if(opt->scale_mode == GAVL_SCALE_SINC_LANCZOS)
174
normalize_table(tab);
176
// fprintf(stderr, "After shift %d\n", src_width);
177
//if(deinterlace || (total_fields == 2))
178
// gavl_video_scale_table_dump(tab);
182
static void normalize_table(gavl_video_scale_table_t * tab)
187
for(i = 0; i < tab->num_pixels; i++)
190
for(j = 0; j < tab->factors_per_pixel; j++)
191
sum += tab->pixels[i].factor[j].fac_f;
193
for(j = 0; j < tab->factors_per_pixel; j++)
194
tab->pixels[i].factor[j].fac_f /= sum;
198
/* Shift the borders of the table such that no indices are out of range.
199
The values in the pixels beyond the border are assumed to be the same as
202
/* shift_up() for shift = 2, num = 5
204
| f0 | f1 | f2 | f3 | f4 |
208
| S | f3 | f4 | 0 | 0 |
210
with S = f0 + f1 + f2
214
static void shift_up(gavl_video_scale_factor_t * fac, int num, int shift)
217
/* Add all out-of-range coefficients up into the first
218
coefficient of the new array */
219
for(j = 0; j < shift; j++)
220
fac[shift].fac_f += fac[j].fac_f;
222
/* Move Coefficients to new locations */
223
for(j = 0; j < num - shift; j++)
224
fac[j].fac_f = fac[j + shift].fac_f;
226
/* Zero unused entries */
227
for(j = num - shift; j < num; j++)
231
/* shift_down() for shift = 2, num = 5
233
| f0 | f1 | f2 | f3 | f4 |
237
| 0 | 0 | f0 | f1 | S |
239
with S = f2 + f3 + f4
243
static void shift_down(gavl_video_scale_factor_t * fac, int num, int shift)
246
// fprintf(stderr, "Shift down 1 %d\n", shift);
247
/* Add all out-of-range coefficients up into the first
248
coefficient of the new array */
249
for(j = num - shift; j < num; j++)
250
fac[num - shift - 1].fac_f += fac[j].fac_f;
252
/* Move Coefficients to new locations */
253
for(j = num - 1; j >= shift; j--)
254
fac[j].fac_f = fac[j-shift].fac_f;
256
/* Zero unused entries */
257
for(j = 0; j < shift; j++)
261
static void shift_borders(gavl_video_scale_table_t * tab, int src_width)
265
for(i = 0; i < tab->num_pixels; i++)
267
// fprintf(stderr, "Shift borders1 %d %d %d\n", tab->pixels[i].index,
268
// tab->factors_per_pixel, src_width);
269
if(tab->pixels[i].index < 0)
271
shift = -tab->pixels[i].index;
272
shift_up(tab->pixels[i].factor, tab->factors_per_pixel, shift);
273
tab->pixels[i].index = 0;
276
if(tab->pixels[i].index + tab->factors_per_pixel > src_width)
278
shift = tab->pixels[i].index + tab->factors_per_pixel - src_width;
279
shift_down(tab->pixels[i].factor, tab->factors_per_pixel, shift);
280
tab->pixels[i].index = src_width - tab->factors_per_pixel;
282
// fprintf(stderr, "Shift borders2 %d %d %d\n", tab->pixels[i].index,
283
// tab->factors_per_pixel, src_width);
289
void gavl_video_scale_table_dump(gavl_video_scale_table_t * tab)
293
fprintf(stderr, "Scale table:\n");
294
for(i = 0; i < tab->num_pixels; i++)
297
fprintf(stderr, " dst: %d", i);
299
for(j = 0; j < tab->factors_per_pixel; j++)
301
// fprintf(stderr, ", fac[%d]: %f [%d]", tab->pixels[i].index + j, tab->pixels[i].factor[j].fac_f,
302
// tab->pixels[i].factor[j].fac_i);
304
fprintf(stderr, ", fac[%d]: %f ", tab->pixels[i].index + j, tab->pixels[i].factor[j].fac_f);
306
sum += tab->pixels[i].factor[j].fac_f;
309
fprintf(stderr, ", sum: %f\n", sum);
314
void gavl_video_scale_table_init_int(gavl_video_scale_table_t * tab,
317
int fac_max_i, i, imax;
319
// fprintf(stderr, "gavl_video_scale_table_init_int: %d\n", bits);
320
imax = tab->num_pixels * tab->factors_per_pixel;
322
fac_max_i = (1<<bits) - 1;
323
fac_max_f = (float)(fac_max_i);
325
for(i = 0; i < imax; i++)
327
tab->factors[i].fac_i = (int)(fac_max_f * tab->factors[i].fac_f+0.5);
328
// fprintf(stderr, "%f -> %d\n", tab->factors[i].fac_f, tab->factors[i].fac_i);
332
void gavl_video_scale_table_cleanup(gavl_video_scale_table_t * tab)
340
void gavl_video_scale_table_get_src_indices(gavl_video_scale_table_t * tab,
341
int * start, int * size)
343
*start = tab->pixels[0].index;
344
*size = tab->pixels[tab->num_pixels-1].index + tab->factors_per_pixel - *start;
347
void gavl_video_scale_table_shift_indices(gavl_video_scale_table_t * tab,
353
for(i = 0; i < tab->num_pixels; i++)
355
tab->pixels[tab->num_pixels].index += shift;