gst_plugins_base/gst/videoscale/vs_4tap.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /*
       
     2  * Image Scaling Functions (4 tap)
       
     3  * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
       
     4  * All rights reserved.
       
     5  *
       
     6  * Redistribution and use in source and binary forms, with or without
       
     7  * modification, are permitted provided that the following conditions
       
     8  * are met:
       
     9  * 1. Redistributions of source code must retain the above copyright
       
    10  *    notice, this list of conditions and the following disclaimer.
       
    11  * 2. Redistributions in binary form must reproduce the above copyright
       
    12  *    notice, this list of conditions and the following disclaimer in the
       
    13  *    documentation and/or other materials provided with the distribution.
       
    14  * 
       
    15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
       
    16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
       
    19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
       
    20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
       
    21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
       
    22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
       
    23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
       
    24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
       
    25  * POSSIBILITY OF SUCH DAMAGE.
       
    26  */
       
    27 
       
    28 #include "vs_image.h"
       
    29 #include "vs_scanline.h"
       
    30 
       
    31 #include "vs_4tap.h"
       
    32 
       
    33 #include <gst/liboil.h>
       
    34 #include <math.h>
       
    35 
       
    36 
       
    37 
       
    38 
       
    39 #define SHIFT 10
       
    40 
       
    41 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
       
    42 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
       
    43 #define CLAMP(x,a,b) MAX(MIN((x),(b)),(a))
       
    44 
       
    45 #ifndef M_PI
       
    46 #define M_PI  3.14159265358979323846
       
    47 #endif
       
    48 
       
    49 #ifdef WIN32
       
    50 #define rint(x) (floor((x)+0.5))
       
    51 #endif
       
    52 
       
    53 static int16_t vs_4tap_taps[256][4];
       
    54 
       
    55 static double
       
    56 vs_4tap_func (double x)
       
    57 {
       
    58 #if 0
       
    59   if (x < -1)
       
    60     return 0;
       
    61   if (x > 1)
       
    62     return 0;
       
    63   if (x < 0)
       
    64     return 1 + x;
       
    65   return 1 - x;
       
    66 #endif
       
    67 #if 0
       
    68   if (x == 0)
       
    69     return 1;
       
    70   return sin (M_PI * x) / (M_PI * x) * (1 - 0.25 * x * x);
       
    71 #endif
       
    72 #if 1
       
    73   if (x == 0)
       
    74     return 1;
       
    75   return sin (M_PI * x) / (M_PI * x);
       
    76 #endif
       
    77 }
       
    78 #ifdef __SYMBIAN32__
       
    79 EXPORT_C
       
    80 #endif
       
    81 
       
    82 
       
    83 void
       
    84 vs_4tap_init (void)
       
    85 {
       
    86   int i;
       
    87   double a, b, c, d;
       
    88   double sum;
       
    89 
       
    90   for (i = 0; i < 256; i++) {
       
    91     a = vs_4tap_func (-1 - i / 256.0);
       
    92     b = vs_4tap_func (0 - i / 256.0);
       
    93     c = vs_4tap_func (1 - i / 256.0);
       
    94     d = vs_4tap_func (2 - i / 256.0);
       
    95     sum = a + b + c + d;
       
    96 
       
    97     vs_4tap_taps[i][0] = rint ((1 << SHIFT) * (a / sum));
       
    98     vs_4tap_taps[i][1] = rint ((1 << SHIFT) * (b / sum));
       
    99     vs_4tap_taps[i][2] = rint ((1 << SHIFT) * (c / sum));
       
   100     vs_4tap_taps[i][3] = rint ((1 << SHIFT) * (d / sum));
       
   101   }
       
   102 }
       
   103 #ifdef __SYMBIAN32__
       
   104 EXPORT_C
       
   105 #endif
       
   106 
       
   107 
       
   108 
       
   109 void
       
   110 vs_scanline_resample_4tap_Y (uint8_t * dest, uint8_t * src,
       
   111     int n, int src_width, int *xacc, int increment)
       
   112 {
       
   113   int i;
       
   114   int j;
       
   115   int acc;
       
   116   int x;
       
   117   int y;
       
   118 
       
   119   acc = *xacc;
       
   120   for (i = 0; i < n; i++) {
       
   121     j = acc >> 16;
       
   122     x = (acc & 0xff00) >> 8;
       
   123     if (j - 1 >= 0 && j + 2 < src_width) {
       
   124       y = vs_4tap_taps[x][0] * src[MAX (j - 1, 0)];
       
   125       y += vs_4tap_taps[x][1] * src[j];
       
   126       y += vs_4tap_taps[x][2] * src[j + 1];
       
   127       y += vs_4tap_taps[x][3] * src[j + 2];
       
   128     } else {
       
   129       y = vs_4tap_taps[x][0] * src[CLAMP (j - 1, 0, src_width - 1)];
       
   130       y += vs_4tap_taps[x][1] * src[CLAMP (j, 0, src_width - 1)];
       
   131       y += vs_4tap_taps[x][2] * src[CLAMP (j + 1, 0, src_width - 1)];
       
   132       y += vs_4tap_taps[x][3] * src[CLAMP (j + 2, 0, src_width - 1)];
       
   133     }
       
   134     y += (1 << (SHIFT - 1));
       
   135     dest[i] = CLAMP (y >> SHIFT, 0, 255);
       
   136     acc += increment;
       
   137   }
       
   138   *xacc = acc;
       
   139 }
       
   140 #ifdef __SYMBIAN32__
       
   141 EXPORT_C
       
   142 #endif
       
   143 
       
   144 
       
   145 void
       
   146 vs_scanline_merge_4tap_Y (uint8_t * dest, uint8_t * src1, uint8_t * src2,
       
   147     uint8_t * src3, uint8_t * src4, int n, int acc)
       
   148 {
       
   149   int i;
       
   150   int y;
       
   151   int a, b, c, d;
       
   152 
       
   153   acc = (acc >> 8) & 0xff;
       
   154   a = vs_4tap_taps[acc][0];
       
   155   b = vs_4tap_taps[acc][1];
       
   156   c = vs_4tap_taps[acc][2];
       
   157   d = vs_4tap_taps[acc][3];
       
   158   for (i = 0; i < n; i++) {
       
   159     y = a * src1[i];
       
   160     y += b * src2[i];
       
   161     y += c * src3[i];
       
   162     y += d * src4[i];
       
   163     y += (1 << (SHIFT - 1));
       
   164     dest[i] = CLAMP (y >> SHIFT, 0, 255);
       
   165   }
       
   166 }
       
   167 #ifdef __SYMBIAN32__
       
   168 EXPORT_C
       
   169 #endif
       
   170 
       
   171 
       
   172 
       
   173 void
       
   174 vs_image_scale_4tap_Y (const VSImage * dest, const VSImage * src,
       
   175     uint8_t * tmpbuf)
       
   176 {
       
   177   int yacc;
       
   178   int y_increment;
       
   179   int x_increment;
       
   180   int i;
       
   181   int j;
       
   182   int xacc;
       
   183   int k;
       
   184 
       
   185   y_increment = ((src->height - 1) << 16) / (dest->height - 1);
       
   186   x_increment = ((src->width - 1) << 16) / (dest->width - 1);
       
   187 
       
   188   k = 0;
       
   189   for (i = 0; i < 4; i++) {
       
   190     xacc = 0;
       
   191     vs_scanline_resample_4tap_Y (tmpbuf + i * dest->width,
       
   192         src->pixels + i * src->stride, dest->width, src->width,
       
   193         &xacc, x_increment);
       
   194   }
       
   195 
       
   196   yacc = 0;
       
   197   for (i = 0; i < dest->height; i++) {
       
   198     uint8_t *t0, *t1, *t2, *t3;
       
   199 
       
   200     j = yacc >> 16;
       
   201 
       
   202     while (j > k) {
       
   203       k++;
       
   204       if (k + 3 < src->height) {
       
   205         xacc = 0;
       
   206         vs_scanline_resample_4tap_Y (tmpbuf + ((k + 3) & 3) * dest->width,
       
   207             src->pixels + (k + 3) * src->stride,
       
   208             dest->width, src->width, &xacc, x_increment);
       
   209       }
       
   210     }
       
   211 
       
   212     t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->width;
       
   213     t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->width;
       
   214     t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->width;
       
   215     t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->width;
       
   216     vs_scanline_merge_4tap_Y (dest->pixels + i * dest->stride,
       
   217         t0, t1, t2, t3, dest->width, yacc & 0xffff);
       
   218 
       
   219     yacc += y_increment;
       
   220   }
       
   221 }