1 /*
2 * Copyright (c) 2011 Stefano Sabatini
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /**
22 * @file
23 * Compute a look-up table for binding the input value to the output
24 * value, and apply it to input video.
25 */
26
37
39 "w", ///< width of the input video
40 "h", ///< height of the input video
41 "val", ///< input value for the pixel
42 "maxval", ///< max value for the pixel
43 "minval", ///< min value for the pixel
44 "negval", ///< negated value
45 "clipval",
47 };
48
58 };
59
62 uint8_t lut[4][256];
///< lookup table for each component
71
79
80 #define OFFSET(x) offsetof(LutContext, x)
81 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
82
96 };
97
99 {
101 int i;
102
103 for (i = 0; i < 4; i++) {
107 }
108 }
109
110 #define YUV_FORMATS \
111 AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, \
112 AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P, \
113 AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, \
114 AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, \
115 AV_PIX_FMT_YUVJ440P
116
117 #define RGB_FORMATS \
118 AV_PIX_FMT_ARGB, AV_PIX_FMT_RGBA, \
119 AV_PIX_FMT_ABGR, AV_PIX_FMT_BGRA, \
120 AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24
121
125
127 {
129
133
135 return 0;
136 }
137
138 /**
139 * Clip value val in the minval - maxval range.
140 */
142 {
146
147 return av_clip(val, minval, maxval);
148 }
149
150 /**
151 * Compute gamma correction for value val, assuming the minval-maxval
152 * range, val is clipped to a value contained in the same interval.
153 */
155 {
160
161 return pow((val-minval)/(maxval-minval), gamma) * (maxval-minval)+minval;
162 }
163
164 /**
165 * Compute ITU Rec.709 gamma correction of value val.
166 */
168 {
173 double level = (val - minval) / (maxval - minval);
174 level = level < 0.018 ? 4.5 * level
175 : 1.099 * pow(level, 1.0 / gamma) - 0.099;
176 return level * (maxval - minval) + minval;
177 }
178
179 static double (*
const funcs1[])(
void *, double) = {
184 };
185
187 "clip",
188 "gammaval",
189 "gammaval709",
191 };
192
194 {
198 uint8_t rgba_map[4];
/* component index -> RGBA color index map */
201
204
207
218 min[
Y] = min[
U] = min[
V] = 16;
220 max[
U] = max[
V] = 240;
221 min[
A] = 0; max[
A] = 255;
222 break;
223 default:
224 min[0] = min[1] = min[2] = min[3] = 0;
225 max[0] = max[1] = max[2] = max[3] = 255;
226 }
227
231
235 }
236
238 double res;
240
241 /* create the parsed expression */
246 if (ret < 0) {
248 "Error when parsing the expression '%s' for the component %d and color %d.\n",
251 }
252
253 /* compute the lut */
256
257 for (val = 0; val < 256; val++) {
262 min[color], max[color]);
263
267 "Error when evaluating the expression '%s' for the value %d for the component %d.\n",
270 }
271 s->
lut[
comp][
val] = av_clip((
int)res, min[color], max[color]);
273 }
274 }
275
276 return 0;
277 }
278
280 {
285 uint8_t *inrow, *outrow, *inrow0, *outrow0;
286 int i, j, plane, direct = 0;
287
289 direct = 1;
291 } else {
293 if (!out) {
296 }
298 }
299
301 /* packed */
302 const int w = inlink->
w;
305 const int in_linesize = in->
linesize[0];
306 const int out_linesize = out->
linesize[0];
307 const int step = s->
step;
308
309 inrow0 = in ->
data[0];
310 outrow0 = out->
data[0];
311
312 for (i = 0; i < h; i ++) {
313 inrow = inrow0;
314 outrow = outrow0;
315 for (j = 0; j < w; j++) {
316 switch (step) {
317 case 4: outrow[3] =
tab[3][inrow[3]];
// Fall-through
318 case 3: outrow[2] =
tab[2][inrow[2]];
// Fall-through
319 case 2: outrow[1] =
tab[1][inrow[1]];
// Fall-through
320 default: outrow[0] =
tab[0][inrow[0]];
321 }
322 outrow += step;
323 inrow += step;
324 }
325 inrow0 += in_linesize;
326 outrow0 += out_linesize;
327 }
328 } else {
329 /* planar */
330 for (plane = 0; plane < 4 && in->
data[plane] && in->
linesize[plane]; plane++) {
331 int vsub = plane == 1 || plane == 2 ? s->
vsub : 0;
332 int hsub = plane == 1 || plane == 2 ? s->
hsub : 0;
336 const int in_linesize = in->
linesize[plane];
337 const int out_linesize = out->
linesize[plane];
338
339 inrow = in ->
data[plane];
340 outrow = out->
data[plane];
341
342 for (i = 0; i < h; i++) {
343 for (j = 0; j < w; j++)
344 outrow[j] = tab[inrow[j]];
345 inrow += in_linesize;
346 outrow += out_linesize;
347 }
348 }
349 }
350
351 if (!direct)
353
355 }
356
362 },
364 };
368 },
370 };
371
372 #define DEFINE_LUT_FILTER(name_, description_) \
373 AVFilter ff_vf_##name_ = { \
374 .name = #name_, \
375 .description = NULL_IF_CONFIG_SMALL(description_), \
376 .priv_size = sizeof(LutContext), \
377 .priv_class = &name_ ## _class, \
378 .init = name_##_init, \
379 .uninit = uninit, \
380 .query_formats = query_formats, \
381 .inputs = inputs, \
382 .outputs = outputs, \
383 .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, \
384 }
385
386 #if CONFIG_LUT_FILTER
387
388 #define lut_options options
390
392 {
393 return 0;
394 }
395
396 DEFINE_LUT_FILTER(lut,
"Compute and apply a lookup table to the RGB/YUV input video.");
397 #endif
398
399 #if CONFIG_LUTYUV_FILTER
400
401 #define lutyuv_options options
403
405 {
407
409
410 return 0;
411 }
412
413 DEFINE_LUT_FILTER(lutyuv,
"Compute and apply a lookup table to the YUV input video.");
414 #endif
415
416 #if CONFIG_LUTRGB_FILTER
417
418 #define lutrgb_options options
420
422 {
424
426
427 return 0;
428 }
429
430 DEFINE_LUT_FILTER(lutrgb,
"Compute and apply a lookup table to the RGB input video.");
431 #endif
432
433 #if CONFIG_NEGATE_FILTER
434
435 static const AVOption negate_options[] = {
438 };
439
441
443 {
445 int i;
446
448
449 for (i = 0; i < 4; i++) {
451 "val" : "negval");
455 }
456 }
457
458 return 0;
459 }
460
462
463 #endif