libavfilter/transform.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2010 Georg Martius <georg.martius@web.de>
00003  * Copyright (C) 2010 Daniel G. Taylor <dan@programmer-art.org>
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00027 #include "libavutil/common.h"
00028 
00029 #include "transform.h"
00030 
00031 #define INTERPOLATE_METHOD(name) \
00032     static uint8_t name(float x, float y, const uint8_t *src, \
00033                         int width, int height, int stride, uint8_t def)
00034 
00035 #define PIXEL(img, x, y, w, h, stride, def) \
00036     ((x) < 0 || (y) < 0) ? (def) : \
00037     (((x) >= (w) || (y) >= (h)) ? (def) : \
00038     img[(x) + (y) * (stride)])
00039 
00043 INTERPOLATE_METHOD(interpolate_nearest)
00044 {
00045     return PIXEL(src, (int)(x + 0.5), (int)(y + 0.5), width, height, stride, def);
00046 }
00047 
00051 INTERPOLATE_METHOD(interpolate_bilinear)
00052 {
00053     int x_c, x_f, y_c, y_f;
00054     int v1, v2, v3, v4;
00055 
00056     if (x < -1 || x > width || y < -1 || y > height) {
00057         return def;
00058     } else {
00059         x_f = (int)x;
00060         x_c = x_f + 1;
00061 
00062         y_f = (int)y;
00063         y_c = y_f + 1;
00064 
00065         v1 = PIXEL(src, x_c, y_c, width, height, stride, def);
00066         v2 = PIXEL(src, x_c, y_f, width, height, stride, def);
00067         v3 = PIXEL(src, x_f, y_c, width, height, stride, def);
00068         v4 = PIXEL(src, x_f, y_f, width, height, stride, def);
00069 
00070         return (v1*(x - x_f)*(y - y_f) + v2*((x - x_f)*(y_c - y)) +
00071                 v3*(x_c - x)*(y - y_f) + v4*((x_c - x)*(y_c - y)));
00072     }
00073 }
00074 
00078 INTERPOLATE_METHOD(interpolate_biquadratic)
00079 {
00080     int     x_c, x_f, y_c, y_f;
00081     uint8_t v1,  v2,  v3,  v4;
00082     float   f1,  f2,  f3,  f4;
00083 
00084     if (x < - 1 || x > width || y < -1 || y > height)
00085         return def;
00086     else {
00087         x_f = (int)x;
00088         x_c = x_f + 1;
00089         y_f = (int)y;
00090         y_c = y_f + 1;
00091 
00092         v1 = PIXEL(src, x_c, y_c, width, height, stride, def);
00093         v2 = PIXEL(src, x_c, y_f, width, height, stride, def);
00094         v3 = PIXEL(src, x_f, y_c, width, height, stride, def);
00095         v4 = PIXEL(src, x_f, y_f, width, height, stride, def);
00096 
00097         f1 = 1 - sqrt((x_c - x) * (y_c - y));
00098         f2 = 1 - sqrt((x_c - x) * (y - y_f));
00099         f3 = 1 - sqrt((x - x_f) * (y_c - y));
00100         f4 = 1 - sqrt((x - x_f) * (y - y_f));
00101         return (v1 * f1 + v2 * f2 + v3 * f3 + v4 * f4) / (f1 + f2 + f3 + f4);
00102     }
00103 }
00104 
00105 void avfilter_get_matrix(float x_shift, float y_shift, float angle, float zoom, float *matrix) {
00106     matrix[0] = zoom * cos(angle);
00107     matrix[1] = -sin(angle);
00108     matrix[2] = x_shift;
00109     matrix[3] = -matrix[1];
00110     matrix[4] = matrix[0];
00111     matrix[5] = y_shift;
00112     matrix[6] = 0;
00113     matrix[7] = 0;
00114     matrix[8] = 1;
00115 }
00116 
00117 void avfilter_add_matrix(const float *m1, const float *m2, float *result)
00118 {
00119     int i;
00120     for (i = 0; i < 9; i++)
00121         result[i] = m1[i] + m2[i];
00122 }
00123 
00124 void avfilter_sub_matrix(const float *m1, const float *m2, float *result)
00125 {
00126     int i;
00127     for (i = 0; i < 9; i++)
00128         result[i] = m1[i] - m2[i];
00129 }
00130 
00131 void avfilter_mul_matrix(const float *m1, float scalar, float *result)
00132 {
00133     int i;
00134     for (i = 0; i < 9; i++)
00135         result[i] = m1[i] * scalar;
00136 }
00137 
00138 void avfilter_transform(const uint8_t *src, uint8_t *dst,
00139                         int src_stride, int dst_stride,
00140                         int width, int height, const float *matrix,
00141                         enum InterpolateMethod interpolate,
00142                         enum FillMethod fill)
00143 {
00144     int x, y;
00145     float x_s, y_s;
00146     uint8_t def = 0;
00147     uint8_t (*func)(float, float, const uint8_t *, int, int, int, uint8_t) = NULL;
00148 
00149     switch(interpolate) {
00150         case INTERPOLATE_NEAREST:
00151             func = interpolate_nearest;
00152             break;
00153         case INTERPOLATE_BILINEAR:
00154             func = interpolate_bilinear;
00155             break;
00156         case INTERPOLATE_BIQUADRATIC:
00157             func = interpolate_biquadratic;
00158             break;
00159     }
00160 
00161     for (y = 0; y < height; y++) {
00162         for(x = 0; x < width; x++) {
00163             x_s = x * matrix[0] + y * matrix[1] + matrix[2];
00164             y_s = x * matrix[3] + y * matrix[4] + matrix[5];
00165 
00166             switch(fill) {
00167                 case FILL_ORIGINAL:
00168                     def = src[y * src_stride + x];
00169                     break;
00170                 case FILL_CLAMP:
00171                     y_s = av_clipf(y_s, 0, height - 1);
00172                     x_s = av_clipf(x_s, 0, width - 1);
00173                     def = src[(int)y_s * src_stride + (int)x_s];
00174                     break;
00175                 case FILL_MIRROR:
00176                     y_s = (y_s < 0) ? -y_s : (y_s >= height) ? (height + height - y_s) : y_s;
00177                     x_s = (x_s < 0) ? -x_s : (x_s >= width) ? (width + width - x_s) : x_s;
00178                     def = src[(int)y_s * src_stride + (int)x_s];
00179             }
00180 
00181             dst[y * dst_stride + x] = func(x_s, y_s, src, width, height, src_stride, def);
00182         }
00183     }
00184 }
00185