yading@10
|
1 /*
|
yading@10
|
2 * Copyright (C) 2010 Georg Martius <georg.martius@web.de>
|
yading@10
|
3 * Copyright (C) 2010 Daniel G. Taylor <dan@programmer-art.org>
|
yading@10
|
4 *
|
yading@10
|
5 * This file is part of FFmpeg.
|
yading@10
|
6 *
|
yading@10
|
7 * FFmpeg is free software; you can redistribute it and/or
|
yading@10
|
8 * modify it under the terms of the GNU Lesser General Public
|
yading@10
|
9 * License as published by the Free Software Foundation; either
|
yading@10
|
10 * version 2.1 of the License, or (at your option) any later version.
|
yading@10
|
11 *
|
yading@10
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
yading@10
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@10
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@10
|
15 * Lesser General Public License for more details.
|
yading@10
|
16 *
|
yading@10
|
17 * You should have received a copy of the GNU Lesser General Public
|
yading@10
|
18 * License along with FFmpeg; if not, write to the Free Software
|
yading@10
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@10
|
20 */
|
yading@10
|
21
|
yading@10
|
22 /**
|
yading@10
|
23 * @file
|
yading@10
|
24 * transform input video
|
yading@10
|
25 */
|
yading@10
|
26
|
yading@10
|
27 #include "libavutil/common.h"
|
yading@10
|
28 #include "libavutil/avassert.h"
|
yading@10
|
29
|
yading@10
|
30 #include "transform.h"
|
yading@10
|
31
|
yading@10
|
32 #define INTERPOLATE_METHOD(name) \
|
yading@10
|
33 static uint8_t name(float x, float y, const uint8_t *src, \
|
yading@10
|
34 int width, int height, int stride, uint8_t def)
|
yading@10
|
35
|
yading@10
|
36 #define PIXEL(img, x, y, w, h, stride, def) \
|
yading@10
|
37 ((x) < 0 || (y) < 0) ? (def) : \
|
yading@10
|
38 (((x) >= (w) || (y) >= (h)) ? (def) : \
|
yading@10
|
39 img[(x) + (y) * (stride)])
|
yading@10
|
40
|
yading@10
|
41 /**
|
yading@10
|
42 * Nearest neighbor interpolation
|
yading@10
|
43 */
|
yading@10
|
44 INTERPOLATE_METHOD(interpolate_nearest)
|
yading@10
|
45 {
|
yading@10
|
46 return PIXEL(src, (int)(x + 0.5), (int)(y + 0.5), width, height, stride, def);
|
yading@10
|
47 }
|
yading@10
|
48
|
yading@10
|
49 /**
|
yading@10
|
50 * Bilinear interpolation
|
yading@10
|
51 */
|
yading@10
|
52 INTERPOLATE_METHOD(interpolate_bilinear)
|
yading@10
|
53 {
|
yading@10
|
54 int x_c, x_f, y_c, y_f;
|
yading@10
|
55 int v1, v2, v3, v4;
|
yading@10
|
56
|
yading@10
|
57 if (x < -1 || x > width || y < -1 || y > height) {
|
yading@10
|
58 return def;
|
yading@10
|
59 } else {
|
yading@10
|
60 x_f = (int)x;
|
yading@10
|
61 x_c = x_f + 1;
|
yading@10
|
62
|
yading@10
|
63 y_f = (int)y;
|
yading@10
|
64 y_c = y_f + 1;
|
yading@10
|
65
|
yading@10
|
66 v1 = PIXEL(src, x_c, y_c, width, height, stride, def);
|
yading@10
|
67 v2 = PIXEL(src, x_c, y_f, width, height, stride, def);
|
yading@10
|
68 v3 = PIXEL(src, x_f, y_c, width, height, stride, def);
|
yading@10
|
69 v4 = PIXEL(src, x_f, y_f, width, height, stride, def);
|
yading@10
|
70
|
yading@10
|
71 return (v1*(x - x_f)*(y - y_f) + v2*((x - x_f)*(y_c - y)) +
|
yading@10
|
72 v3*(x_c - x)*(y - y_f) + v4*((x_c - x)*(y_c - y)));
|
yading@10
|
73 }
|
yading@10
|
74 }
|
yading@10
|
75
|
yading@10
|
76 /**
|
yading@10
|
77 * Biquadratic interpolation
|
yading@10
|
78 */
|
yading@10
|
79 INTERPOLATE_METHOD(interpolate_biquadratic)
|
yading@10
|
80 {
|
yading@10
|
81 int x_c, x_f, y_c, y_f;
|
yading@10
|
82 uint8_t v1, v2, v3, v4;
|
yading@10
|
83 float f1, f2, f3, f4;
|
yading@10
|
84
|
yading@10
|
85 if (x < - 1 || x > width || y < -1 || y > height)
|
yading@10
|
86 return def;
|
yading@10
|
87 else {
|
yading@10
|
88 x_f = (int)x;
|
yading@10
|
89 x_c = x_f + 1;
|
yading@10
|
90 y_f = (int)y;
|
yading@10
|
91 y_c = y_f + 1;
|
yading@10
|
92
|
yading@10
|
93 v1 = PIXEL(src, x_c, y_c, width, height, stride, def);
|
yading@10
|
94 v2 = PIXEL(src, x_c, y_f, width, height, stride, def);
|
yading@10
|
95 v3 = PIXEL(src, x_f, y_c, width, height, stride, def);
|
yading@10
|
96 v4 = PIXEL(src, x_f, y_f, width, height, stride, def);
|
yading@10
|
97
|
yading@10
|
98 f1 = 1 - sqrt((x_c - x) * (y_c - y));
|
yading@10
|
99 f2 = 1 - sqrt((x_c - x) * (y - y_f));
|
yading@10
|
100 f3 = 1 - sqrt((x - x_f) * (y_c - y));
|
yading@10
|
101 f4 = 1 - sqrt((x - x_f) * (y - y_f));
|
yading@10
|
102 return (v1 * f1 + v2 * f2 + v3 * f3 + v4 * f4) / (f1 + f2 + f3 + f4);
|
yading@10
|
103 }
|
yading@10
|
104 }
|
yading@10
|
105
|
yading@10
|
106 void avfilter_get_matrix(float x_shift, float y_shift, float angle, float zoom, float *matrix) {
|
yading@10
|
107 matrix[0] = zoom * cos(angle);
|
yading@10
|
108 matrix[1] = -sin(angle);
|
yading@10
|
109 matrix[2] = x_shift;
|
yading@10
|
110 matrix[3] = -matrix[1];
|
yading@10
|
111 matrix[4] = matrix[0];
|
yading@10
|
112 matrix[5] = y_shift;
|
yading@10
|
113 matrix[6] = 0;
|
yading@10
|
114 matrix[7] = 0;
|
yading@10
|
115 matrix[8] = 1;
|
yading@10
|
116 }
|
yading@10
|
117
|
yading@10
|
118 void avfilter_add_matrix(const float *m1, const float *m2, float *result)
|
yading@10
|
119 {
|
yading@10
|
120 int i;
|
yading@10
|
121 for (i = 0; i < 9; i++)
|
yading@10
|
122 result[i] = m1[i] + m2[i];
|
yading@10
|
123 }
|
yading@10
|
124
|
yading@10
|
125 void avfilter_sub_matrix(const float *m1, const float *m2, float *result)
|
yading@10
|
126 {
|
yading@10
|
127 int i;
|
yading@10
|
128 for (i = 0; i < 9; i++)
|
yading@10
|
129 result[i] = m1[i] - m2[i];
|
yading@10
|
130 }
|
yading@10
|
131
|
yading@10
|
132 void avfilter_mul_matrix(const float *m1, float scalar, float *result)
|
yading@10
|
133 {
|
yading@10
|
134 int i;
|
yading@10
|
135 for (i = 0; i < 9; i++)
|
yading@10
|
136 result[i] = m1[i] * scalar;
|
yading@10
|
137 }
|
yading@10
|
138
|
yading@10
|
139 static inline int mirror(int v, int m)
|
yading@10
|
140 {
|
yading@10
|
141 while ((unsigned)v > (unsigned)m) {
|
yading@10
|
142 v = -v;
|
yading@10
|
143 if (v < 0)
|
yading@10
|
144 v += 2 * m;
|
yading@10
|
145 }
|
yading@10
|
146 return v;
|
yading@10
|
147 }
|
yading@10
|
148
|
yading@10
|
149 int avfilter_transform(const uint8_t *src, uint8_t *dst,
|
yading@10
|
150 int src_stride, int dst_stride,
|
yading@10
|
151 int width, int height, const float *matrix,
|
yading@10
|
152 enum InterpolateMethod interpolate,
|
yading@10
|
153 enum FillMethod fill)
|
yading@10
|
154 {
|
yading@10
|
155 int x, y;
|
yading@10
|
156 float x_s, y_s;
|
yading@10
|
157 uint8_t def = 0;
|
yading@10
|
158 uint8_t (*func)(float, float, const uint8_t *, int, int, int, uint8_t) = NULL;
|
yading@10
|
159
|
yading@10
|
160 switch(interpolate) {
|
yading@10
|
161 case INTERPOLATE_NEAREST:
|
yading@10
|
162 func = interpolate_nearest;
|
yading@10
|
163 break;
|
yading@10
|
164 case INTERPOLATE_BILINEAR:
|
yading@10
|
165 func = interpolate_bilinear;
|
yading@10
|
166 break;
|
yading@10
|
167 case INTERPOLATE_BIQUADRATIC:
|
yading@10
|
168 func = interpolate_biquadratic;
|
yading@10
|
169 break;
|
yading@10
|
170 default:
|
yading@10
|
171 return AVERROR(EINVAL);
|
yading@10
|
172 }
|
yading@10
|
173
|
yading@10
|
174 for (y = 0; y < height; y++) {
|
yading@10
|
175 for(x = 0; x < width; x++) {
|
yading@10
|
176 x_s = x * matrix[0] + y * matrix[1] + matrix[2];
|
yading@10
|
177 y_s = x * matrix[3] + y * matrix[4] + matrix[5];
|
yading@10
|
178
|
yading@10
|
179 switch(fill) {
|
yading@10
|
180 case FILL_ORIGINAL:
|
yading@10
|
181 def = src[y * src_stride + x];
|
yading@10
|
182 break;
|
yading@10
|
183 case FILL_CLAMP:
|
yading@10
|
184 y_s = av_clipf(y_s, 0, height - 1);
|
yading@10
|
185 x_s = av_clipf(x_s, 0, width - 1);
|
yading@10
|
186 def = src[(int)y_s * src_stride + (int)x_s];
|
yading@10
|
187 break;
|
yading@10
|
188 case FILL_MIRROR:
|
yading@10
|
189 x_s = mirror(x_s, width-1);
|
yading@10
|
190 y_s = mirror(y_s, height-1);
|
yading@10
|
191
|
yading@10
|
192 av_assert2(x_s >= 0 && y_s >= 0);
|
yading@10
|
193 av_assert2(x_s < width && y_s < height);
|
yading@10
|
194 def = src[(int)y_s * src_stride + (int)x_s];
|
yading@10
|
195 }
|
yading@10
|
196
|
yading@10
|
197 dst[y * dst_stride + x] = func(x_s, y_s, src, width, height, src_stride, def);
|
yading@10
|
198 }
|
yading@10
|
199 }
|
yading@10
|
200 return 0;
|
yading@10
|
201 }
|
yading@10
|
202
|