~ubuntu-branches/ubuntu/lucid/gavl/lucid

« back to all changes in this revision

Viewing changes to gavl/scale_table.c

  • Committer: Bazaar Package Importer
  • Author(s): Free Ekanayaka
  • Date: 2006-05-17 14:24:46 UTC
  • Revision ID: james.westby@ubuntu.com-20060517142446-iqm0jgfbkmy27n5w
Tags: upstream-0.2.3
ImportĀ upstreamĀ versionĀ 0.2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************
 
2
 
 
3
  scale_table.c
 
4
 
 
5
  Copyright (c) 2005 by Burkhard Plaum - plaum@ipf.uni-stuttgart.de
 
6
 
 
7
  http://gmerlin.sourceforge.net
 
8
 
 
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.
 
13
 
 
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.
 
17
 
 
18
*****************************************************************/
 
19
 
 
20
#include <stdlib.h>
 
21
#include <stdio.h>
 
22
 
 
23
#include <gavl/gavl.h>
 
24
#include <scale.h>
 
25
 
 
26
/*
 
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.
 
31
 * 
 
32
 * We have 3 values: src_size (double), src_off (double)
 
33
 * and dst_size (int).
 
34
 *
 
35
 * The scale factor is dst_size / src_size. src_off is the coordinate of the
 
36
 * first destination pixel in source coordinates.
 
37
 *
 
38
 * When src_offset is zero, we'll have a pattern like this
 
39
 * (for upscaling by a factor of 2):
 
40
 *
 
41
 * src: | x     | x     |
 
42
 * dst: | x | x | x | x |
 
43
 * 
 
44
 * For a src_offset of -0.25, we'll have
 
45
 *
 
46
 * src: |   x   |   x   |
 
47
 * dst: | x | x | x | x |
 
48
 *
 
49
 * The table is created in the follwing steps:
 
50
 *
 
51
 * - Calculate the floating point filter coefficiens for each destination pixel
 
52
 *   
 
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
 
56
 *   image border
 
57
 *
 
58
 * - Convert the floating point coefficients to integer with the specified bit
 
59
 *   resolution requsted by the scaling routine.
 
60
 *
 
61
 */
 
62
 
 
63
 
 
64
/* Conversion between src and dst coordinates */
 
65
 
 
66
#define DST_TO_SRC(c) ((double)c)/scale_factor+src_off
 
67
 
 
68
#define ROUND(val) (val >= 0.0) ? (int)(val+0.5):(int)(val-0.5)
 
69
 
 
70
static void shift_borders(gavl_video_scale_table_t * tab, int src_width);
 
71
 
 
72
static void normalize_table(gavl_video_scale_table_t * tab);
 
73
 
 
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)
 
78
  {
 
79
  double t;
 
80
  int i, j, src_index_min, src_index_nearest;
 
81
  double src_index_f;
 
82
    
 
83
  gavl_video_scale_get_weight weight_func;
 
84
  
 
85
  double scale_factor;
 
86
 
 
87
  //  src_off = -0.25;
 
88
  
 
89
  /* Get the kernel generator */
 
90
 
 
91
  //  fprintf(stderr, "src_off: %f\n", src_off);
 
92
  
 
93
  weight_func = gavl_video_scale_get_weight_func(opt, &(tab->factors_per_pixel));
 
94
 
 
95
  //  fprintf(stderr, "gavl_video_scale_table_init: %f %f %d %d\n", 
 
96
  //          src_off, src_size, dst_size, tab->factors_per_pixel);
 
97
  
 
98
  /* (Re)allocate memory */
 
99
 
 
100
  if(tab->pixels_alloc < dst_size)
 
101
    {
 
102
    tab->pixels_alloc = dst_size + 128;
 
103
    tab->pixels = realloc(tab->pixels, tab->pixels_alloc * sizeof(*(tab->pixels)));
 
104
    }
 
105
 
 
106
  tab->num_pixels = dst_size;
 
107
  
 
108
  if(tab->factors_alloc < dst_size * tab->factors_per_pixel)
 
109
    {
 
110
    tab->factors_alloc =  dst_size * tab->factors_per_pixel + 128;
 
111
    tab->factors = realloc(tab->factors, tab->factors_alloc * sizeof(*(tab->factors)));
 
112
    }
 
113
  
 
114
  scale_factor = (double)(dst_size) / src_size;
 
115
  
 
116
  for(i = 0; i < dst_size; i++)
 
117
    {
 
118
    /* Set the factor pointers */
 
119
    tab->pixels[i].factor = tab->factors + i * tab->factors_per_pixel;
 
120
 
 
121
    /* src_index_f:       Fractional source index */
 
122
    /* src_index_nearest: Nearest integer source index */
 
123
    
 
124
    src_index_f = DST_TO_SRC((double)i);
 
125
 
 
126
    //    fprintf(stderr, "dst: %d -> src: %f (offset: s: %.2f)\n", i, src_index_f,
 
127
    //            src_off);
 
128
    
 
129
    //    if(src_index_f > src_size - 1.0)
 
130
    //      src_index_f = src_size - 1.0;
 
131
    
 
132
    src_index_nearest = ROUND(src_index_f);
 
133
 
 
134
    src_index_min = src_index_nearest - tab->factors_per_pixel/2;
 
135
    
 
136
    if(((double)src_index_nearest < src_index_f) && !(tab->factors_per_pixel % 2))
 
137
      {
 
138
      src_index_min++;
 
139
      }
 
140
 
 
141
    tab->pixels[i].index = src_index_min;
 
142
 
 
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);
 
145
    
 
146
    /* For nearest neighbour, we don't need any factors */
 
147
    if(tab->factors_per_pixel == 1)
 
148
      {
 
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;
 
153
      continue;
 
154
      }
 
155
    
 
156
    /* Normalized distance of the destination pixel to the first source pixel
 
157
       in src coordinates */    
 
158
    t = src_index_f - src_index_min;
 
159
    
 
160
    for(j = 0; j < tab->factors_per_pixel; j++)
 
161
      {
 
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));
 
164
      t -= 1.0;
 
165
      }
 
166
    }
 
167
 
 
168
  //  fprintf(stderr, "Before shift\n");
 
169
  //  gavl_video_scale_table_dump(tab);
 
170
  
 
171
  shift_borders(tab, src_width);
 
172
  
 
173
  if(opt->scale_mode == GAVL_SCALE_SINC_LANCZOS)
 
174
    normalize_table(tab);
 
175
  
 
176
  //  fprintf(stderr, "After shift %d\n", src_width);
 
177
  //if(deinterlace || (total_fields == 2))
 
178
  //      gavl_video_scale_table_dump(tab);
 
179
  
 
180
  }
 
181
 
 
182
static void normalize_table(gavl_video_scale_table_t * tab)
 
183
  {
 
184
  int i, j;
 
185
  float sum;
 
186
  
 
187
  for(i = 0; i < tab->num_pixels; i++)
 
188
    {
 
189
    sum = 0.0;
 
190
    for(j = 0; j < tab->factors_per_pixel; j++)
 
191
      sum += tab->pixels[i].factor[j].fac_f;
 
192
 
 
193
    for(j = 0; j < tab->factors_per_pixel; j++)
 
194
      tab->pixels[i].factor[j].fac_f /= sum;
 
195
    }
 
196
  }
 
197
 
 
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
 
200
   the border pixel. */
 
201
 
 
202
/* shift_up() for shift = 2, num = 5
 
203
   
 
204
   | f0 | f1 | f2 | f3 | f4 |
 
205
 
 
206
   ->
 
207
 
 
208
   | S  | f3 | f4 |  0 |  0 |
 
209
 
 
210
   with S = f0 + f1 + f2
 
211
   
 
212
*/
 
213
   
 
214
static void shift_up(gavl_video_scale_factor_t * fac, int num, int shift)
 
215
  {
 
216
  int j;
 
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;
 
221
 
 
222
  /* Move Coefficients to new locations */
 
223
  for(j = 0; j < num - shift; j++)
 
224
    fac[j].fac_f = fac[j + shift].fac_f;
 
225
  
 
226
  /* Zero unused entries */
 
227
  for(j = num - shift; j < num; j++)
 
228
    fac[j].fac_f = 0.0;
 
229
  }
 
230
 
 
231
/* shift_down() for shift = 2, num = 5
 
232
   
 
233
   | f0 | f1 | f2 | f3 | f4 |
 
234
 
 
235
   ->
 
236
 
 
237
   | 0  |  0 | f0 | f1 | S  |
 
238
 
 
239
   with S = f2 + f3 + f4
 
240
   
 
241
*/
 
242
 
 
243
static void shift_down(gavl_video_scale_factor_t * fac, int num, int shift)
 
244
  {
 
245
  int j;
 
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;
 
251
 
 
252
  /* Move Coefficients to new locations */
 
253
  for(j = num - 1; j >= shift; j--)
 
254
    fac[j].fac_f = fac[j-shift].fac_f;
 
255
  
 
256
  /* Zero unused entries */
 
257
  for(j = 0; j < shift; j++)
 
258
    fac[j].fac_f = 0.0;
 
259
  }
 
260
 
 
261
static void shift_borders(gavl_video_scale_table_t * tab, int src_width)
 
262
  {
 
263
  int i, shift;
 
264
  
 
265
  for(i = 0; i < tab->num_pixels; i++)
 
266
    {
 
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)
 
270
      {
 
271
      shift = -tab->pixels[i].index;
 
272
      shift_up(tab->pixels[i].factor, tab->factors_per_pixel, shift);
 
273
      tab->pixels[i].index = 0;
 
274
      }
 
275
 
 
276
    if(tab->pixels[i].index + tab->factors_per_pixel > src_width)
 
277
      {
 
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;
 
281
      }
 
282
    //    fprintf(stderr, "Shift borders2 %d %d %d\n", tab->pixels[i].index,
 
283
    //            tab->factors_per_pixel, src_width);
 
284
    
 
285
    }
 
286
  
 
287
  }
 
288
 
 
289
void gavl_video_scale_table_dump(gavl_video_scale_table_t * tab)
 
290
  {
 
291
  int i, j;
 
292
  float sum;
 
293
  fprintf(stderr, "Scale table:\n");
 
294
  for(i = 0; i < tab->num_pixels; i++)
 
295
    {
 
296
    sum = 0.0;
 
297
    fprintf(stderr, " dst: %d", i);
 
298
 
 
299
    for(j = 0; j < tab->factors_per_pixel; j++)
 
300
      {
 
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);
 
303
 
 
304
      fprintf(stderr, ", fac[%d]: %f ", tab->pixels[i].index + j, tab->pixels[i].factor[j].fac_f);
 
305
      
 
306
      sum += tab->pixels[i].factor[j].fac_f;
 
307
      }
 
308
    
 
309
    fprintf(stderr, ", sum: %f\n", sum);
 
310
    }
 
311
  }
 
312
 
 
313
 
 
314
void gavl_video_scale_table_init_int(gavl_video_scale_table_t * tab,
 
315
                                     int bits)
 
316
  {
 
317
  int fac_max_i, i, imax;
 
318
  float fac_max_f;
 
319
  //  fprintf(stderr, "gavl_video_scale_table_init_int: %d\n", bits);
 
320
  imax = tab->num_pixels * tab->factors_per_pixel;
 
321
 
 
322
  fac_max_i = (1<<bits) - 1;
 
323
  fac_max_f = (float)(fac_max_i);
 
324
    
 
325
  for(i = 0; i < imax; i++)
 
326
    {
 
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);
 
329
    }
 
330
  }
 
331
 
 
332
void gavl_video_scale_table_cleanup(gavl_video_scale_table_t * tab)
 
333
  {
 
334
  if(tab->pixels)
 
335
    free(tab->pixels);
 
336
  if(tab->factors)
 
337
    free(tab->factors);
 
338
  }
 
339
 
 
340
void gavl_video_scale_table_get_src_indices(gavl_video_scale_table_t * tab,
 
341
                                            int * start, int * size)
 
342
  {
 
343
  *start = tab->pixels[0].index;
 
344
  *size = tab->pixels[tab->num_pixels-1].index + tab->factors_per_pixel - *start;
 
345
  }
 
346
 
 
347
void gavl_video_scale_table_shift_indices(gavl_video_scale_table_t * tab,
 
348
                                          int shift)
 
349
  {
 
350
  int i;
 
351
  if(!shift)
 
352
    return;
 
353
  for(i = 0; i < tab->num_pixels; i++)
 
354
    {
 
355
    tab->pixels[tab->num_pixels].index += shift;
 
356
    }
 
357
  }
 
358