~ubuntu-branches/ubuntu/trusty/gavl/trusty

« back to all changes in this revision

Viewing changes to gavl/scale_table.c

  • Committer: Bazaar Package Importer
  • Author(s): Romain Beauxis
  • Date: 2009-01-17 20:38:33 UTC
  • mfrom: (1.1.3 upstream) (4.1.1 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090117203833-t8fq1e1jdquyelmy
Tags: 1.1.0-2
Fixed debian/copyright 

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
#include <stdlib.h>
23
23
#include <stdio.h>
 
24
#include <float.h>
 
25
#include <math.h>
24
26
 
25
27
#include <gavl/gavl.h>
26
28
#include <scale.h>
27
29
 
 
30
#define BLUR_THRESHOLD 5.0e-3
 
31
 
 
32
/* Conversion between src and dst coordinates */
 
33
 
 
34
#define DST_TO_SRC(c) ((double)c)/scale_factor+src_off
 
35
 
 
36
#define ROUND(val) (val >= 0.0) ? (int)(val+0.5):(int)(val-0.5)
 
37
 
 
38
static void shift_borders(gavl_video_scale_table_t * tab, int src_width);
 
39
 
 
40
static void normalize_table(gavl_video_scale_table_t * tab);
 
41
 
 
42
static void alloc_table(gavl_video_scale_table_t * tab,
 
43
                        int num_pixels);
 
44
 
 
45
static void check_clip(gavl_video_scale_table_t * tab);
 
46
 
 
47
static void get_preblur_coeffs(double scale_factor,
 
48
                               gavl_video_options_t * opt,
 
49
                               int * num_ret,
 
50
                               float ** coeffs_ret);
 
51
 
 
52
static void convolve_preblur(float * src_1, int src_len_1,
 
53
                             float * src_2, int src_len_2,
 
54
                             float * dst);
 
55
 
28
56
/*
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.
33
59
 * 
34
60
 * We have 3 values: src_size (double), src_off (double)
35
61
 * and dst_size (int).
58
84
 *   image border
59
85
 *
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.
62
88
 *
63
89
 */
64
 
 
65
 
 
66
 
/* Conversion between src and dst coordinates */
67
 
 
68
 
#define DST_TO_SRC(c) ((double)c)/scale_factor+src_off
69
 
 
70
 
#define ROUND(val) (val >= 0.0) ? (int)(val+0.5):(int)(val-0.5)
71
 
 
72
 
static void shift_borders(gavl_video_scale_table_t * tab, int src_width);
73
 
 
74
 
static void normalize_table(gavl_video_scale_table_t * tab);
75
 
 
76
 
static void alloc_table(gavl_video_scale_table_t * tab,
77
 
                        int num_pixels);
78
 
 
 
90
                    
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)
83
95
  {
 
96
  int widen;
 
97
 
84
98
  double t;
85
99
  int i, j, src_index_min, src_index_nearest;
86
100
  double src_index_f;
87
 
    
 
101
  float widen_factor;
 
102
  float * preblur_factors = (float*)0;
 
103
  int num_preblur_factors = 0;
 
104
  int num_tmp_factors = 0;
 
105
  float * tmp_factors = (float*)0;
 
106
  
88
107
  gavl_video_scale_get_weight weight_func;
89
108
  
90
109
  double scale_factor;
91
 
 
 
110
  scale_factor = (double)(dst_size) / src_size;
 
111
 
 
112
  widen = 0;
 
113
 
 
114
  if(scale_factor < 1.0)
 
115
    {
 
116
    switch(opt->downscale_filter)
 
117
      {
 
118
      case GAVL_DOWNSCALE_FILTER_AUTO: //!< Auto selection based on quality
 
119
        if(opt->quality < 2)
 
120
          break;
 
121
        else
 
122
          {
 
123
          get_preblur_coeffs(scale_factor,
 
124
                             opt,
 
125
                             &num_preblur_factors,
 
126
                             &preblur_factors);
 
127
          }
 
128
        break;
 
129
      case GAVL_DOWNSCALE_FILTER_NONE: //!< Fastest method, might produce heavy aliasing artifacts
 
130
        break;
 
131
      case GAVL_DOWNSCALE_FILTER_WIDE: //!< Widen the filter curve according to the scaling ratio. 
 
132
        if(opt->downscale_blur > BLUR_THRESHOLD)
 
133
          widen = 1;
 
134
        break;
 
135
      case GAVL_DOWNSCALE_FILTER_GAUSS: //!< Do a Gaussian preblur
 
136
        get_preblur_coeffs(scale_factor,
 
137
                           opt,
 
138
                           &num_preblur_factors,
 
139
                           &preblur_factors);
 
140
        break;
 
141
      }
 
142
    }
 
143
  
92
144
  //  src_off = -0.25;
93
145
  
94
146
  /* Get the kernel generator */
96
148
  weight_func =
97
149
    gavl_video_scale_get_weight_func(opt, &(tab->factors_per_pixel));
98
150
 
 
151
  num_tmp_factors = tab->factors_per_pixel;
 
152
  
 
153
  if(num_preblur_factors)
 
154
    {
 
155
    tmp_factors = malloc(sizeof(*tmp_factors) * num_tmp_factors);
 
156
    
 
157
    tab->factors_per_pixel += num_preblur_factors - 1;
 
158
    }
 
159
  
 
160
  if(widen)
 
161
    {
 
162
    widen_factor = ceil(opt->downscale_blur / scale_factor);
 
163
    tab->factors_per_pixel *= (int)(widen_factor);
 
164
    }
 
165
  else
 
166
    widen_factor = 1.0;
 
167
 
 
168
  
99
169
  //  fprintf(stderr, "tab->factors_per_pixel: %d, src_width: %d\n",
100
170
  //          tab->factors_per_pixel, src_width);
101
171
  
 
172
  
102
173
  if(tab->factors_per_pixel > src_width)
103
174
    {
104
175
    switch(src_width)
128
199
 
129
200
  alloc_table(tab, dst_size);
130
201
 
131
 
  scale_factor = (double)(dst_size) / src_size;
132
202
  
133
203
  for(i = 0; i < dst_size; i++)
134
204
    {
146
216
    
147
217
    src_index_nearest = ROUND(src_index_f);
148
218
 
149
 
    src_index_min = src_index_nearest - tab->factors_per_pixel/2;
150
 
    
 
219
    tab->pixels[i].index = src_index_nearest - tab->factors_per_pixel/2;
 
220
    src_index_min = src_index_nearest - num_tmp_factors/2;
 
221
#if 0
151
222
    if(((double)src_index_nearest < src_index_f) && !(tab->factors_per_pixel % 2))
152
223
      {
153
224
      src_index_min++;
 
225
      tab->pixels[i].index++;
154
226
      }
155
 
 
156
 
    tab->pixels[i].index = src_index_min;
157
 
 
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);
 
227
#endif
 
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,
 
231
    //            i);
160
232
    
161
233
    /* For nearest neighbour, we don't need any factors */
162
234
    if(tab->factors_per_pixel == 1)
170
242
    
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;
174
 
    
 
245
 
 
246
    if(num_preblur_factors)
 
247
      {
 
248
      t = (src_index_f - src_index_min)/widen_factor;
 
249
      for(j = 0; j < num_tmp_factors; j++)
 
250
        {
 
251
        tmp_factors[j] = weight_func(opt, t);
 
252
        //        fprintf(stderr, "j: %d, t: %f, w: %f\n", j, t, weight_func(opt, t));
 
253
        t -= 1.0;
 
254
        }
 
255
      
 
256
      convolve_preblur(tmp_factors, num_tmp_factors,
 
257
                       preblur_factors, num_preblur_factors,
 
258
                       tab->pixels[i].factor_f);
 
259
      }
 
260
    else
 
261
      {
 
262
      t = (src_index_f - tab->pixels[i].index)/widen_factor;
 
263
      for(j = 0; j < tab->factors_per_pixel; j++)
 
264
        {
 
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;
 
268
        }
 
269
      }
 
270
#if 0
175
271
    for(j = 0; j < tab->factors_per_pixel; j++)
176
272
      {
177
 
      tab->pixels[i].factor_f[j] = weight_func(opt, t);
178
 
      //      fprintf(stderr, "t: %f, w: %f\n", t, weight_func(opt, t));
179
 
      t -= 1.0;
 
273
      fprintf(stderr, "%d %f\n", j,
 
274
              tab->pixels[i].factor_f[j]);
180
275
      }
 
276
#endif
181
277
    }
182
278
 
183
279
  //  fprintf(stderr, "Before shift\n");
184
280
  //  gavl_video_scale_table_dump(tab);
185
281
  
186
282
  shift_borders(tab, src_width);
187
 
  
188
 
  if(opt->scale_mode == GAVL_SCALE_SINC_LANCZOS)
189
 
    normalize_table(tab);
190
 
  
 
283
  // if(opt->scale_mode == GAVL_SCALE_SINC_LANCZOS)
 
284
  normalize_table(tab);
 
285
  
 
286
  check_clip(tab);
 
287
 
 
288
  if(tmp_factors)
 
289
    free(tmp_factors);
 
290
  if(preblur_factors)
 
291
    free(preblur_factors);
 
292
    
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);
 
296
 
 
297
  
194
298
  
195
299
  }
196
300
 
215
319
 
216
320
  if(opt->conversion_flags & GAVL_CONVOLVE_NORMALIZE)
217
321
    normalize_table(tab);   
 
322
  else
 
323
    tab->normalized = 0;
 
324
  
 
325
  check_clip(tab);
 
326
 
218
327
  //  gavl_video_scale_table_dump(tab);
219
328
  }
220
329
 
258
367
    for(j = 0; j < tab->factors_per_pixel; j++)
259
368
      sum += tab->pixels[i].factor_f[j];
260
369
 
 
370
    /* This is to prevent accidental setting of clipping functions due to
 
371
       rounding errors. For usual applications, it should not be noticable
 
372
    */
 
373
    sum += FLT_EPSILON;
 
374
    
261
375
    // fprintf(stderr, "sum: %f\n", sum);
262
376
    
263
377
    for(j = 0; j < tab->factors_per_pixel; j++)
264
378
      tab->pixels[i].factor_f[j] /= sum;
265
379
    }
 
380
  tab->normalized = 1;
266
381
  }
267
382
 
268
383
/* Shift the borders of the table such that no indices are out of range.
450
565
        }
451
566
      index++;
452
567
      }
453
 
    if(!i)
 
568
   if(!i)
454
569
      fac_i_norm = (int)(sum_f * fac_max_i + 0.5);
455
570
    
456
571
    if(sum_i > fac_i_norm)
490
605
    }
491
606
  }
492
607
 
 
608
static void check_clip(gavl_video_scale_table_t * tab)
 
609
  {
 
610
  int i, j;
 
611
  float sum;
 
612
 
 
613
  tab->do_clip = 0;
 
614
  
 
615
  for(i = 0; i < tab->num_pixels; i++)
 
616
    {
 
617
    sum = 0.0;
 
618
    for(j = 0; j < tab->factors_per_pixel; j++)
 
619
      {
 
620
      sum += tab->pixels[i].factor_f[j];
 
621
      
 
622
      if(tab->pixels[i].factor_f[j] < 0.0 ||
 
623
         tab->pixels[i].factor_f[j] > 1.0)
 
624
        {
 
625
        tab->do_clip = 1;
 
626
        return;
 
627
        }
 
628
      }
 
629
    if(sum > 1.0)
 
630
      {
 
631
      tab->do_clip = 1;
 
632
      return;
 
633
      }
 
634
    }
 
635
  }
 
636
 
 
637
static void get_preblur_coeffs(double scale_factor,
 
638
                               gavl_video_options_t * opt,
 
639
                               int * num_ret,
 
640
                               float ** coeffs_ret)
 
641
  {
 
642
  *num_ret = 0;
 
643
 
 
644
  /* Gaussian lowpass */
 
645
  if(opt->downscale_filter == GAVL_DOWNSCALE_FILTER_GAUSS)
 
646
    {
 
647
    int i;
 
648
    float tmp;
 
649
    float f_co = 0.25 * scale_factor;
 
650
    int n = (int)(ceil(0.398 / f_co));
 
651
 
 
652
    if(n && (opt->downscale_blur >= BLUR_THRESHOLD))
 
653
      {
 
654
      *num_ret = 2 * n + 1;
 
655
      *coeffs_ret = malloc(*num_ret * sizeof(**coeffs_ret));
 
656
      
 
657
      for(i = -n; i <= n; i++)
 
658
        {
 
659
        tmp = 3.011 * f_co * (float)i / opt->downscale_blur;
 
660
        (*coeffs_ret)[i+n] = exp(-M_PI * tmp * tmp);
 
661
        }
 
662
      }
 
663
    }
 
664
  
 
665
  if(!(*num_ret))
 
666
    *coeffs_ret = NULL;
 
667
  
 
668
  }
 
669
 
 
670
static void convolve_preblur(float * src_1, int src_len_1,
 
671
                             float * src_2, int src_len_2,
 
672
                             float * dst)
 
673
  {
 
674
  int m, n, nmax;
 
675
  
 
676
  nmax = src_len_1 + src_len_2 - 1;
 
677
  
 
678
  for(n = 0; n < nmax; n++)
 
679
    {
 
680
    dst[n] = 0.0;
 
681
 
 
682
    for(m = 0; m < src_len_1; m++)
 
683
      {
 
684
      if((n - m >= 0) && (n - m < src_len_2))
 
685
        dst[n] += src_1[m] * src_2[n-m];
 
686
      }
 
687
    
 
688
    }
 
689
  
 
690
  
 
691
  }