[FFmpeg-cvslog] libavfilter: image transform code

danielgtaylor git at videolan.org
Tue Oct 4 02:29:50 CEST 2011


ffmpeg | branch: master | danielgtaylor <dan at programmer-art.org> | Tue Oct  4 02:10:18 2011 +0200| [7985381e236a95c711a5315a83c891eef0c56d3b] | committer: Michael Niedermayer

libavfilter: image transform code

Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=7985381e236a95c711a5315a83c891eef0c56d3b
---

 libavfilter/transform.c |  182 +++++++++++++++++++++++++++++++++++++++++++++++
 libavfilter/transform.h |  125 ++++++++++++++++++++++++++++++++
 2 files changed, 307 insertions(+), 0 deletions(-)

diff --git a/libavfilter/transform.c b/libavfilter/transform.c
new file mode 100644
index 0000000..c3f7939
--- /dev/null
+++ b/libavfilter/transform.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2010 Georg Martius <georg.martius at web.de>
+ * Copyright (C) 2010 Daniel G. Taylor <dan at programmer-art.org>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file libavfilter/transform.c
+ * transform input video
+ */
+
+#include "libavutil/common.h"
+
+#include "transform.h"
+
+#define INTERPOLATE_METHOD(name) \
+    static uint8_t name(float x, float y, const uint8_t *src, \
+                        int width, int height, int stride, uint8_t def)
+
+#define PIXEL(img, x, y, w, h, stride, def) \
+    ((x) < 0 || (y) < 0) ? (def) : \
+    (((x) >= (w) || (y) >= (h)) ? (def) : \
+    img[(x) + (y) * (stride)])
+
+/**
+ * Nearest neighbor interpolation
+ */
+INTERPOLATE_METHOD(interpolate_nearest)
+{
+    return PIXEL(src, (int)(x + 0.5), (int)(y + 0.5), width, height, stride, def);
+}
+
+/**
+ * Bilinear interpolation
+ */
+INTERPOLATE_METHOD(interpolate_bilinear)
+{
+    int x_c, x_f, y_c, y_f;
+    int v1, v2, v3, v4;
+
+    if (x < -1 || x > width || y < -1 || y > height) {
+        return def;
+    } else {
+        x_f = (int)x;
+        x_c = x_f + 1;
+
+        y_f = (int)y;
+        y_c = y_f + 1;
+
+        v1 = PIXEL(src, x_c, y_c, width, height, stride, def);
+        v2 = PIXEL(src, x_c, y_f, width, height, stride, def);
+        v3 = PIXEL(src, x_f, y_c, width, height, stride, def);
+        v4 = PIXEL(src, x_f, y_f, width, height, stride, def);
+
+        return (v1*(x - x_f)*(y - y_f) + v2*((x - x_f)*(y_c - y)) +
+                v3*(x_c - x)*(y - y_f) + v4*((x_c - x)*(y_c - y)));
+    }
+}
+
+/**
+ * Biquadratic interpolation
+ */
+INTERPOLATE_METHOD(interpolate_biquadratic)
+{
+    int     x_c, x_f, y_c, y_f;
+    uint8_t v1,  v2,  v3,  v4;
+    float   f1,  f2,  f3,  f4;
+
+    if (x < - 1 || x > width || y < -1 || y > height)
+        return def;
+    else {
+        x_f = (int)x;
+        x_c = x_f + 1;
+        y_f = (int)y;
+        y_c = y_f + 1;
+
+        v1 = PIXEL(src, x_c, y_c, width, height, stride, def);
+        v2 = PIXEL(src, x_c, y_f, width, height, stride, def);
+        v3 = PIXEL(src, x_f, y_c, width, height, stride, def);
+        v4 = PIXEL(src, x_f, y_f, width, height, stride, def);
+
+        f1 = 1 - sqrt((x_c - x) * (y_c - y));
+        f2 = 1 - sqrt((x_c - x) * (y - y_f));
+        f3 = 1 - sqrt((x - x_f) * (y_c - y));
+        f4 = 1 - sqrt((x - x_f) * (y - y_f));
+        return (v1 * f1 + v2 * f2 + v3 * f3 + v4 * f4) / (f1 + f2 + f3 + f4);
+    }
+}
+
+void avfilter_get_matrix(float x_shift, float y_shift, float angle, float zoom, float *matrix) {
+    matrix[0] = zoom * cos(angle);
+    matrix[1] = -sin(angle);
+    matrix[2] = x_shift;
+    matrix[3] = -matrix[1];
+    matrix[4] = matrix[0];
+    matrix[5] = y_shift;
+    matrix[6] = 0;
+    matrix[7] = 0;
+    matrix[8] = 1;
+}
+
+void avfilter_add_matrix(const float *m1, const float *m2, float *result)
+{
+    for (int i = 0; i < 9; i++)
+        result[i] = m1[i] + m2[i];
+}
+
+void avfilter_sub_matrix(const float *m1, const float *m2, float *result)
+{
+    for (int i = 0; i < 9; i++)
+        result[i] = m1[i] - m2[i];
+}
+
+void avfilter_mul_matrix(const float *m1, float scalar, float *result)
+{
+    for (int i = 0; i < 9; i++)
+        result[i] = m1[i] * scalar;
+}
+
+void avfilter_transform(const uint8_t *src, uint8_t *dst,
+                        int src_stride, int dst_stride,
+                        int width, int height, const float *matrix,
+                        enum InterpolateMethod interpolate,
+                        enum FillMethod fill)
+{
+    int x, y;
+    float x_s, y_s;
+    uint8_t def = 0;
+    uint8_t (*func)(float, float, const uint8_t *, int, int, int, uint8_t) = NULL;
+
+    switch(interpolate) {
+        case INTERPOLATE_NEAREST:
+            func = interpolate_nearest;
+            break;
+        case INTERPOLATE_BILINEAR:
+            func = interpolate_bilinear;
+            break;
+        case INTERPOLATE_BIQUADRATIC:
+            func = interpolate_biquadratic;
+            break;
+    }
+
+    for (y = 0; y < height; y++) {
+        for(x = 0; x < width; x++) {
+            x_s = x * matrix[0] + y * matrix[1] + matrix[2];
+            y_s = x * matrix[3] + y * matrix[4] + matrix[5];
+
+            switch(fill) {
+                case FILL_ORIGINAL:
+                    def = src[y * src_stride + x];
+                    break;
+                case FILL_CLAMP:
+                    y_s = av_clipf(y_s, 0, height - 1);
+                    x_s = av_clipf(x_s, 0, width - 1);
+                    def = src[(int)y_s * src_stride + (int)x_s];
+                    break;
+                case FILL_MIRROR:
+                    y_s = (y_s < 0) ? -y_s : (y_s >= height) ? (height + height - y_s) : y_s;
+                    x_s = (x_s < 0) ? -x_s : (x_s >= width) ? (width + width - x_s) : x_s;
+                    def = src[(int)y_s * src_stride + (int)x_s];
+            }
+
+            dst[y * dst_stride + x] = func(x_s, y_s, src, width, height, src_stride, def);
+        }
+    }
+}
+
diff --git a/libavfilter/transform.h b/libavfilter/transform.h
new file mode 100644
index 0000000..2d5cf37
--- /dev/null
+++ b/libavfilter/transform.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2010 Georg Martius <georg.martius at web.de>
+ * Copyright (C) 2010 Daniel G. Taylor <dan at programmer-art.org>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file libavfilter/transform.h
+ * transform input video
+ *
+ * All matrices are defined as a single 9-item block of contiguous memory. For
+ * example, the identity matrix would be:
+ *
+ *     float *matrix = {1, 0, 0,
+ *                      0, 1, 0,
+ *                      0, 0, 1};
+ */
+
+enum InterpolateMethod {
+    INTERPOLATE_NEAREST,        //< Nearest-neighbor (fast)
+    INTERPOLATE_BILINEAR,       //< Bilinear
+    INTERPOLATE_BIQUADRATIC,    //< Biquadratic (best)
+    INTERPOLATE_COUNT,          //< Number of interpolation methods
+};
+
+// Shortcuts for the fastest and best interpolation methods
+#define INTERPOLATE_DEFAULT INTERPOLATE_BILINEAR
+#define INTERPOLATE_FAST    INTERPOLATE_NEAREST
+#define INTERPOLATE_BEST    INTERPOLATE_BIQUADRATIC
+
+enum FillMethod {
+    FILL_BLANK,         //< Fill zeroes at blank locations
+    FILL_ORIGINAL,      //< Original image at blank locations
+    FILL_CLAMP,         //< Extruded edge value at blank locations
+    FILL_MIRROR,        //< Mirrored edge at blank locations
+    FILL_COUNT,         //< Number of edge fill methods
+};
+
+// Shortcuts for fill methods
+#define FILL_DEFAULT FILL_ORIGINAL
+
+/**
+ * Get an affine transformation matrix from a given translation, rotation, and
+ * zoom factor. The matrix will look like:
+ *
+ * [ zoom * cos(angle),           -sin(angle),     x_shift,
+ *          sin(angle),     zoom * cos(angle),     y_shift,
+                     0,                     0,           1 ]
+ *
+ * Paramters:
+ *  x_shift: Horizontal translation
+ *  y_shift: Vertical translation
+ *    angle: Rotation in radians
+ *     zoom: Scale percent (1.0 = 100%)
+ *   matrix: 9-item affine transformation matrix
+ */
+void avfilter_get_matrix(float x_shift, float y_shift, float angle, float zoom, float *matrix);
+
+/**
+ * Add two matrices together. result = m1 + m2.
+ *
+ * Parameters:
+ *      m1: 9-item transformation matrix
+ *      m2: 9-item transformation matrix
+ *  result: 9-item transformation matrix
+ */
+void avfilter_add_matrix(const float *m1, const float *m2, float *result);
+
+/**
+ * Subtract one matrix from another. result = m1 - m2.
+ *
+ * Parameters:
+ *      m1: 9-item transformation matrix
+ *      m2: 9-item transformation matrix
+ *  result: 9-item transformation matrix
+ */
+void avfilter_sub_matrix(const float *m1, const float *m2, float *result);
+
+/**
+ * Multiply a matrix by a scalar value. result = m1 * scalar.
+ *
+ * Parameters:
+ *      m1: 9-item transformation matrix
+ *  scalar: A number
+ *  result: 9-item transformation matrix
+ */
+void avfilter_mul_matrix(const float *m1, float scalar, float *result);
+
+/**
+ * Do an affine transformation with the given interpolation method. This
+ * multiplies each vector [x,y,1] by the matrix and then interpolates to
+ * get the final value.
+ *
+ * Parameters:
+ *          src: Source image
+ *          dst: Destination image
+ *   src_stride: Source image line size in bytes
+ *   dst_stride: Destination image line size in bytes
+ *        width: Image width in pixels
+ *       height: Image height in pixels
+ *       matrix: 9-item affine transformation matrix
+ *  interpolate: Pixel interpolation method
+ *         fill: Edge fill method
+ */
+void avfilter_transform(const uint8_t *src, uint8_t *dst,
+                        int src_stride, int dst_stride,
+                        int width, int height, const float *matrix,
+                        enum InterpolateMethod interpolate,
+                        enum FillMethod fill);
+



More information about the ffmpeg-cvslog mailing list