1 /*
2 * Original copyright (c) 2002 Remi Guyomarch <rguyom@pobox.com>
3 * Port copyright (c) 2010 Daniel G. Taylor <dan@programmer-art.org>
4 * Relicensed to the LGPL with permission from Remi Guyomarch.
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /**
24 * @file
25 * blur / sharpen filter, ported to FFmpeg from MPlayer
26 * libmpcodecs/unsharp.c.
27 *
28 * This code is based on:
29 *
30 * An Efficient algorithm for Gaussian blur using finite-state machines
31 * Frederick M. Waltz and John W. V. Miller
32 *
33 * SPIE Conf. on Machine Vision Systems for Inspection and Metrology VII
34 * Originally published Boston, Nov 98
35 *
36 * http://www.engin.umd.umich.edu/~jwvm/ece581/21_GBlur.pdf
37 */
38
50
54 {
55 uint32_t **sc = fp->
sc;
57
61 const int amount = fp->
amount;
62 const int steps_x = fp->
steps_x;
63 const int steps_y = fp->
steps_y;
66
67 if (!amount) {
69 return;
70 }
71
72 for (y = 0; y < 2 * steps_y; y++)
73 memset(sc[y], 0, sizeof(sc[y][0]) * (width + 2 * steps_x));
74
75 for (y = -steps_y; y < height + steps_y; y++) {
76 if (y < height)
78
79 memset(sr, 0, sizeof(sr[0]) * (2 * steps_x - 1));
80 for (x = -steps_x; x < width + steps_x; x++) {
81 tmp1 = x <= 0 ? src2[0] : x >= width ? src2[width-1] : src2[x];
82 for (z = 0; z < steps_x * 2; z += 2) {
83 tmp2 = sr[z + 0] + tmp1; sr[z + 0] = tmp1;
84 tmp1 = sr[z + 1] + tmp2; sr[z + 1] = tmp2;
85 }
86 for (z = 0; z < steps_y * 2; z += 2) {
87 tmp2 = sc[z + 0][x + steps_x] + tmp1; sc[z + 0][x + steps_x] = tmp1;
88 tmp1 = sc[z + 1][x + steps_x] + tmp2; sc[z + 1][x + steps_x] = tmp2;
89 }
90 if (x >= steps_x && y >= steps_y) {
91 const uint8_t *srx = src - steps_y * src_stride + x - steps_x;
92 uint8_t *dsx = dst - steps_y * dst_stride + x - steps_x;
93
94 res = (
int32_t)*srx + ((((
int32_t) * srx - (
int32_t)((tmp1 + halfscale) >> scalebits)) * amount) >> 16);
95 *dsx = av_clip_uint8(res);
96 }
97 }
98 if (y >= 0) {
99 dst += dst_stride;
100 src += src_stride;
101 }
102 }
103 }
104
106 {
109 int i, plane_w[3], plane_h[3];
111 plane_w[0] = inlink->
w;
113 plane_h[0] = inlink->
h;
115 fp[0] = &unsharp->
luma;
116 fp[1] = fp[2] = &unsharp->
chroma;
117 for (i = 0; i < 3; i++) {
119 }
120 return 0;
121 }
122
124 {
127 fp->
amount = amount * 65536.0;
128
133 }
134
136 {
139
140
143
145 if (!CONFIG_OPENCL && unsharp->
opencl) {
146 av_log(ctx,
AV_LOG_ERROR,
"OpenCL support was not enabled in this build, cannot be selected\n");
148 }
149 if (CONFIG_OPENCL && unsharp->
opencl) {
152 if (ret < 0)
154 }
155 return 0;
156 }
157
159 {
164 };
165
167
168 return 0;
169 }
170
172 {
173 int z;
174 const char *effect = fp->
amount == 0 ?
"none" : fp->
amount < 0 ?
"blur" :
"sharpen";
175
178 "Invalid even size for %s matrix size %dx%d\n",
181 }
182
185
186 for (z = 0; z < 2 * fp->
steps_y; z++)
188 sizeof(*(fp->
sc[z])))))
190
191 return 0;
192 }
193
195 {
199
202
204 if (ret < 0)
207 if (ret < 0)
209
210 return 0;
211 }
212
214 {
215 int z;
216
217 for (z = 0; z < 2 * fp->
steps_y; z++)
219 }
220
222 {
224
225 if (CONFIG_OPENCL && unsharp->
opencl) {
227 }
228
231 }
232
234 {
239
241 if (!out) {
244 }
246 if (CONFIG_OPENCL && unsharp->
opencl) {
248 if (ret < 0)
250 }
251
255
256 if (ret < 0)
259 }
260
261 #define OFFSET(x) offsetof(UnsharpContext, x)
262 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
280 };
281
283
285 {
290 },
292 };
293
295 {
298 },
300 };
301
306 .priv_class = &unsharp_class,
310 .
inputs = avfilter_vf_unsharp_inputs,
311 .
outputs = avfilter_vf_unsharp_outputs,
313 };