00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00027 #include "libavutil/common.h"
00028 #include "libavutil/avassert.h"
00029 
00030 #include "transform.h"
00031 
00032 #define INTERPOLATE_METHOD(name) \
00033     static uint8_t name(float x, float y, const uint8_t *src, \
00034                         int width, int height, int stride, uint8_t def)
00035 
00036 #define PIXEL(img, x, y, w, h, stride, def) \
00037     ((x) < 0 || (y) < 0) ? (def) : \
00038     (((x) >= (w) || (y) >= (h)) ? (def) : \
00039     img[(x) + (y) * (stride)])
00040 
00044 INTERPOLATE_METHOD(interpolate_nearest)
00045 {
00046     return PIXEL(src, (int)(x + 0.5), (int)(y + 0.5), width, height, stride, def);
00047 }
00048 
00052 INTERPOLATE_METHOD(interpolate_bilinear)
00053 {
00054     int x_c, x_f, y_c, y_f;
00055     int v1, v2, v3, v4;
00056 
00057     if (x < -1 || x > width || y < -1 || y > height) {
00058         return def;
00059     } else {
00060         x_f = (int)x;
00061         x_c = x_f + 1;
00062 
00063         y_f = (int)y;
00064         y_c = y_f + 1;
00065 
00066         v1 = PIXEL(src, x_c, y_c, width, height, stride, def);
00067         v2 = PIXEL(src, x_c, y_f, width, height, stride, def);
00068         v3 = PIXEL(src, x_f, y_c, width, height, stride, def);
00069         v4 = PIXEL(src, x_f, y_f, width, height, stride, def);
00070 
00071         return (v1*(x - x_f)*(y - y_f) + v2*((x - x_f)*(y_c - y)) +
00072                 v3*(x_c - x)*(y - y_f) + v4*((x_c - x)*(y_c - y)));
00073     }
00074 }
00075 
00079 INTERPOLATE_METHOD(interpolate_biquadratic)
00080 {
00081     int     x_c, x_f, y_c, y_f;
00082     uint8_t v1,  v2,  v3,  v4;
00083     float   f1,  f2,  f3,  f4;
00084 
00085     if (x < - 1 || x > width || y < -1 || y > height)
00086         return def;
00087     else {
00088         x_f = (int)x;
00089         x_c = x_f + 1;
00090         y_f = (int)y;
00091         y_c = y_f + 1;
00092 
00093         v1 = PIXEL(src, x_c, y_c, width, height, stride, def);
00094         v2 = PIXEL(src, x_c, y_f, width, height, stride, def);
00095         v3 = PIXEL(src, x_f, y_c, width, height, stride, def);
00096         v4 = PIXEL(src, x_f, y_f, width, height, stride, def);
00097 
00098         f1 = 1 - sqrt((x_c - x) * (y_c - y));
00099         f2 = 1 - sqrt((x_c - x) * (y - y_f));
00100         f3 = 1 - sqrt((x - x_f) * (y_c - y));
00101         f4 = 1 - sqrt((x - x_f) * (y - y_f));
00102         return (v1 * f1 + v2 * f2 + v3 * f3 + v4 * f4) / (f1 + f2 + f3 + f4);
00103     }
00104 }
00105 
00106 void avfilter_get_matrix(float x_shift, float y_shift, float angle, float zoom, float *matrix) {
00107     matrix[0] = zoom * cos(angle);
00108     matrix[1] = -sin(angle);
00109     matrix[2] = x_shift;
00110     matrix[3] = -matrix[1];
00111     matrix[4] = matrix[0];
00112     matrix[5] = y_shift;
00113     matrix[6] = 0;
00114     matrix[7] = 0;
00115     matrix[8] = 1;
00116 }
00117 
00118 void avfilter_add_matrix(const float *m1, const float *m2, float *result)
00119 {
00120     int i;
00121     for (i = 0; i < 9; i++)
00122         result[i] = m1[i] + m2[i];
00123 }
00124 
00125 void avfilter_sub_matrix(const float *m1, const float *m2, float *result)
00126 {
00127     int i;
00128     for (i = 0; i < 9; i++)
00129         result[i] = m1[i] - m2[i];
00130 }
00131 
00132 void avfilter_mul_matrix(const float *m1, float scalar, float *result)
00133 {
00134     int i;
00135     for (i = 0; i < 9; i++)
00136         result[i] = m1[i] * scalar;
00137 }
00138 
00139 static inline int mirror(int v, int m)
00140 {
00141     while ((unsigned)v > (unsigned)m) {
00142         v = -v;
00143         if (v < 0)
00144             v += 2 * m;
00145     }
00146     return v;
00147 }
00148 
00149 void avfilter_transform(const uint8_t *src, uint8_t *dst,
00150                         int src_stride, int dst_stride,
00151                         int width, int height, const float *matrix,
00152                         enum InterpolateMethod interpolate,
00153                         enum FillMethod fill)
00154 {
00155     int x, y;
00156     float x_s, y_s;
00157     uint8_t def = 0;
00158     uint8_t (*func)(float, float, const uint8_t *, int, int, int, uint8_t) = NULL;
00159 
00160     switch(interpolate) {
00161         case INTERPOLATE_NEAREST:
00162             func = interpolate_nearest;
00163             break;
00164         case INTERPOLATE_BILINEAR:
00165             func = interpolate_bilinear;
00166             break;
00167         case INTERPOLATE_BIQUADRATIC:
00168             func = interpolate_biquadratic;
00169             break;
00170     }
00171 
00172     for (y = 0; y < height; y++) {
00173         for(x = 0; x < width; x++) {
00174             x_s = x * matrix[0] + y * matrix[1] + matrix[2];
00175             y_s = x * matrix[3] + y * matrix[4] + matrix[5];
00176 
00177             switch(fill) {
00178                 case FILL_ORIGINAL:
00179                     def = src[y * src_stride + x];
00180                     break;
00181                 case FILL_CLAMP:
00182                     y_s = av_clipf(y_s, 0, height - 1);
00183                     x_s = av_clipf(x_s, 0, width - 1);
00184                     def = src[(int)y_s * src_stride + (int)x_s];
00185                     break;
00186                 case FILL_MIRROR:
00187                     x_s = mirror(x_s,  width-1);
00188                     y_s = mirror(y_s, height-1);
00189 
00190                     av_assert2(x_s >= 0 && y_s >= 0);
00191                     av_assert2(x_s < width && y_s < height);
00192                     def = src[(int)y_s * src_stride + (int)x_s];
00193             }
00194 
00195             dst[y * dst_stride + x] = func(x_s, y_s, src, width, height, src_stride, def);
00196         }
00197     }
00198 }
00199