FFmpeg
Loading...
Searching...
No Matches
vf_ciescope.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2000 John Walker
3 * Copyright (c) 2016 Paul B Mahol
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "libavutil/avassert.h"
24#include "libavutil/opt.h"
26#include "libavutil/pixdesc.h"
27#include "avfilter.h"
28#include "filters.h"
29#include "formats.h"
30#include "video.h"
31
38
52
53typedef struct CiescopeContext {
54 const AVClass *class;
56 unsigned gamuts;
57 int size;
60 int cie;
61 float intensity;
62 float contrast;
64 int fill;
65
66 float log2lin[65536];
67 float igamma;
68 float i[3][3];
69 float m[3][3];
71 void (*filter)(AVFilterContext *ctx, const uint8_t *ptr,
72 ptrdiff_t linesize,
73 float *cx, float *cy, int x, int y);
75
76#define OFFSET(x) offsetof(CiescopeContext, x)
77#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
78
79static const AVOption ciescope_options[] = {
80 { "system", "set color system", OFFSET(color_system), AV_OPT_TYPE_INT, {.i64=Rec709system}, 0, NB_CS-1, FLAGS, .unit = "system" },
81 { "ntsc", "NTSC 1953 Y'I'O' (ITU-R BT.470 System M)", 0, AV_OPT_TYPE_CONST, {.i64=NTSCsystem}, 0, 0, FLAGS, .unit = "system" },
82 { "470m", "NTSC 1953 Y'I'O' (ITU-R BT.470 System M)", 0, AV_OPT_TYPE_CONST, {.i64=NTSCsystem}, 0, 0, FLAGS, .unit = "system" },
83 { "ebu", "EBU Y'U'V' (PAL/SECAM) (ITU-R BT.470 System B, G)", 0, AV_OPT_TYPE_CONST, {.i64=EBUsystem}, 0, 0, FLAGS, .unit = "system" },
84 { "470bg", "EBU Y'U'V' (PAL/SECAM) (ITU-R BT.470 System B, G)", 0, AV_OPT_TYPE_CONST, {.i64=EBUsystem}, 0, 0, FLAGS, .unit = "system" },
85 { "smpte", "SMPTE-C RGB", 0, AV_OPT_TYPE_CONST, {.i64=SMPTEsystem}, 0, 0, FLAGS, .unit = "system" },
86 { "240m", "SMPTE-240M Y'PbPr", 0, AV_OPT_TYPE_CONST, {.i64=SMPTE240Msystem},0, 0, FLAGS, .unit = "system" },
87 { "apple", "Apple RGB", 0, AV_OPT_TYPE_CONST, {.i64=APPLEsystem}, 0, 0, FLAGS, .unit = "system" },
88 { "widergb", "Adobe Wide Gamut RGB", 0, AV_OPT_TYPE_CONST, {.i64=wRGBsystem}, 0, 0, FLAGS, .unit = "system" },
89 { "cie1931", "CIE 1931 RGB", 0, AV_OPT_TYPE_CONST, {.i64=CIE1931system}, 0, 0, FLAGS, .unit = "system" },
90 { "hdtv", "ITU.BT-709 Y'CbCr", 0, AV_OPT_TYPE_CONST, {.i64=Rec709system}, 0, 0, FLAGS, .unit = "system" },
91 { "rec709", "ITU.BT-709 Y'CbCr", 0, AV_OPT_TYPE_CONST, {.i64=Rec709system}, 0, 0, FLAGS, .unit = "system" },
92 { "uhdtv", "ITU-R.BT-2020", 0, AV_OPT_TYPE_CONST, {.i64=Rec2020system}, 0, 0, FLAGS, .unit = "system" },
93 { "rec2020", "ITU-R.BT-2020", 0, AV_OPT_TYPE_CONST, {.i64=Rec2020system}, 0, 0, FLAGS, .unit = "system" },
94 { "dcip3", "DCI-P3", 0, AV_OPT_TYPE_CONST, {.i64=DCIP3}, 0, 0, FLAGS, .unit = "system" },
95 { "cie", "set cie system", OFFSET(cie), AV_OPT_TYPE_INT, {.i64=XYY}, 0, NB_CIE-1, FLAGS, .unit = "cie" },
96 { "xyy", "CIE 1931 xyY", 0, AV_OPT_TYPE_CONST, {.i64=XYY}, 0, 0, FLAGS, .unit = "cie" },
97 { "ucs", "CIE 1960 UCS", 0, AV_OPT_TYPE_CONST, {.i64=UCS}, 0, 0, FLAGS, .unit = "cie" },
98 { "luv", "CIE 1976 Luv", 0, AV_OPT_TYPE_CONST, {.i64=LUV}, 0, 0, FLAGS, .unit = "cie" },
99 { "gamuts", "set what gamuts to draw", OFFSET(gamuts), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, 0xFFF, FLAGS, .unit = "gamuts" },
100 { "ntsc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<NTSCsystem}, 0, 0, FLAGS, .unit = "gamuts" },
101 { "470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<NTSCsystem}, 0, 0, FLAGS, .unit = "gamuts" },
102 { "ebu", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<EBUsystem}, 0, 0, FLAGS, .unit = "gamuts" },
103 { "470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<EBUsystem}, 0, 0, FLAGS, .unit = "gamuts" },
104 { "smpte", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<SMPTEsystem}, 0, 0, FLAGS, .unit = "gamuts" },
105 { "240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<SMPTE240Msystem}, 0, 0, FLAGS, .unit = "gamuts" },
106 { "apple", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<APPLEsystem}, 0, 0, FLAGS, .unit = "gamuts" },
107 { "widergb", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<wRGBsystem}, 0, 0, FLAGS, .unit = "gamuts" },
108 { "cie1931", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<CIE1931system}, 0, 0, FLAGS, .unit = "gamuts" },
109 { "hdtv", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<Rec709system}, 0, 0, FLAGS, .unit = "gamuts" },
110 { "rec709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<Rec709system}, 0, 0, FLAGS, .unit = "gamuts" },
111 { "uhdtv", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<Rec2020system}, 0, 0, FLAGS, .unit = "gamuts" },
112 { "rec2020", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<Rec2020system}, 0, 0, FLAGS, .unit = "gamuts" },
113 { "dcip3", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<DCIP3}, 0, 0, FLAGS, .unit = "gamuts" },
114 { "size", "set ciescope size", OFFSET(size), AV_OPT_TYPE_INT, {.i64=512}, 256, 8192, FLAGS },
115 { "s", "set ciescope size", OFFSET(size), AV_OPT_TYPE_INT, {.i64=512}, 256, 8192, FLAGS },
116 { "intensity", "set ciescope intensity", OFFSET(intensity), AV_OPT_TYPE_FLOAT, {.dbl=0.001}, 0, 1, FLAGS },
117 { "i", "set ciescope intensity", OFFSET(intensity), AV_OPT_TYPE_FLOAT, {.dbl=0.001}, 0, 1, FLAGS },
118 { "contrast", NULL, OFFSET(contrast), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
119 { "corrgamma", NULL, OFFSET(correct_gamma), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
120 { "showwhite", NULL, OFFSET(show_white), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
121 { "gamma", NULL, OFFSET(igamma), AV_OPT_TYPE_DOUBLE, {.dbl=2.6}, 0.1, 6, FLAGS },
122 { "fill", "fill with CIE colors", OFFSET(fill), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
123 { NULL }
124};
125
127
136
137static const enum AVPixelFormat out_pix_fmts[] = {
140};
141
143 AVFilterFormatsConfig **cfg_in,
144 AVFilterFormatsConfig **cfg_out)
145{
146 int ret;
147
148 if ((ret = ff_formats_ref(ff_make_pixel_format_list(in_pix_fmts), &cfg_in[0]->formats)) < 0)
149 return ret;
150
151 if ((ret = ff_formats_ref(ff_make_pixel_format_list(out_pix_fmts), &cfg_out[0]->formats)) < 0)
152 return ret;
153
154 return 0;
155}
156
157static int config_output(AVFilterLink *outlink)
158{
159 CiescopeContext *s = outlink->src->priv;
160
161 outlink->h = outlink->w = s->size;
162 outlink->sample_aspect_ratio = (AVRational){1,1};
163
164 return 0;
165}
166
167/* A color system is defined by the CIE x and y coordinates of its
168 three primary illuminants and the x and y coordinates of the white
169 point. */
170
172 float xRed, yRed, /* Red primary illuminant */
173 xGreen, yGreen, /* Green primary illuminant */
174 xBlue, yBlue, /* Blue primary illuminant */
175 xWhite, yWhite, /* White point */
176 gamma; /* gamma of nonlinear correction */
177};
178
179static float const spectral_chromaticity[][3] = {
180 { 0.175560, 0.005294, 0.819146 },
181 { 0.175483, 0.005286, 0.819231 },
182 { 0.175400, 0.005279, 0.819321 },
183 { 0.175317, 0.005271, 0.819412 },
184 { 0.175237, 0.005263, 0.819500 },
185 { 0.175161, 0.005256, 0.819582 },
186 { 0.175088, 0.005247, 0.819665 },
187 { 0.175015, 0.005236, 0.819749 },
188 { 0.174945, 0.005226, 0.819829 },
189 { 0.174880, 0.005221, 0.819899 },
190 { 0.174821, 0.005221, 0.819959 },
191 { 0.174770, 0.005229, 0.820001 },
192 { 0.174722, 0.005238, 0.820040 },
193 { 0.174665, 0.005236, 0.820098 },
194 { 0.174595, 0.005218, 0.820187 },
195 { 0.174510, 0.005182, 0.820309 },
196 { 0.174409, 0.005127, 0.820464 },
197 { 0.174308, 0.005068, 0.820624 },
198 { 0.174222, 0.005017, 0.820761 },
199 { 0.174156, 0.004981, 0.820863 },
200 { 0.174112, 0.004964, 0.820924 },
201 { 0.174088, 0.004964, 0.820948 },
202 { 0.174073, 0.004973, 0.820955 },
203 { 0.174057, 0.004982, 0.820961 },
204 { 0.174036, 0.004986, 0.820978 },
205 { 0.174008, 0.004981, 0.821012 },
206 { 0.173972, 0.004964, 0.821064 },
207 { 0.173932, 0.004943, 0.821125 },
208 { 0.173889, 0.004926, 0.821185 },
209 { 0.173845, 0.004916, 0.821239 },
210 { 0.173801, 0.004915, 0.821284 },
211 { 0.173754, 0.004925, 0.821321 },
212 { 0.173705, 0.004937, 0.821358 },
213 { 0.173655, 0.004944, 0.821401 },
214 { 0.173606, 0.004940, 0.821454 },
215 { 0.173560, 0.004923, 0.821517 },
216 { 0.173514, 0.004895, 0.821590 },
217 { 0.173468, 0.004865, 0.821667 },
218 { 0.173424, 0.004836, 0.821740 },
219 { 0.173380, 0.004813, 0.821807 },
220 { 0.173337, 0.004797, 0.821866 },
221 { 0.173291, 0.004786, 0.821923 },
222 { 0.173238, 0.004779, 0.821983 },
223 { 0.173174, 0.004775, 0.822051 },
224 { 0.173101, 0.004774, 0.822125 },
225 { 0.173021, 0.004775, 0.822204 },
226 { 0.172934, 0.004781, 0.822285 },
227 { 0.172843, 0.004791, 0.822366 },
228 { 0.172751, 0.004799, 0.822450 },
229 { 0.172662, 0.004802, 0.822536 },
230 { 0.172577, 0.004799, 0.822624 },
231 { 0.172489, 0.004795, 0.822715 },
232 { 0.172396, 0.004796, 0.822808 },
233 { 0.172296, 0.004803, 0.822901 },
234 { 0.172192, 0.004815, 0.822993 },
235 { 0.172087, 0.004833, 0.823081 },
236 { 0.171982, 0.004855, 0.823163 },
237 { 0.171871, 0.004889, 0.823240 },
238 { 0.171741, 0.004939, 0.823319 },
239 { 0.171587, 0.005010, 0.823402 },
240 { 0.171407, 0.005102, 0.823490 },
241 { 0.171206, 0.005211, 0.823583 },
242 { 0.170993, 0.005334, 0.823674 },
243 { 0.170771, 0.005470, 0.823759 },
244 { 0.170541, 0.005621, 0.823838 },
245 { 0.170301, 0.005789, 0.823911 },
246 { 0.170050, 0.005974, 0.823976 },
247 { 0.169786, 0.006177, 0.824037 },
248 { 0.169505, 0.006398, 0.824097 },
249 { 0.169203, 0.006639, 0.824158 },
250 { 0.168878, 0.006900, 0.824222 },
251 { 0.168525, 0.007184, 0.824291 },
252 { 0.168146, 0.007491, 0.824363 },
253 { 0.167746, 0.007821, 0.824433 },
254 { 0.167328, 0.008175, 0.824496 },
255 { 0.166895, 0.008556, 0.824549 },
256 { 0.166446, 0.008964, 0.824589 },
257 { 0.165977, 0.009402, 0.824622 },
258 { 0.165483, 0.009865, 0.824652 },
259 { 0.164963, 0.010351, 0.824687 },
260 { 0.164412, 0.010858, 0.824731 },
261 { 0.163828, 0.011385, 0.824787 },
262 { 0.163210, 0.011937, 0.824853 },
263 { 0.162552, 0.012520, 0.824928 },
264 { 0.161851, 0.013137, 0.825011 },
265 { 0.161105, 0.013793, 0.825102 },
266 { 0.160310, 0.014491, 0.825199 },
267 { 0.159466, 0.015232, 0.825302 },
268 { 0.158573, 0.016015, 0.825412 },
269 { 0.157631, 0.016840, 0.825529 },
270 { 0.156641, 0.017705, 0.825654 },
271 { 0.155605, 0.018609, 0.825786 },
272 { 0.154525, 0.019556, 0.825920 },
273 { 0.153397, 0.020554, 0.826049 },
274 { 0.152219, 0.021612, 0.826169 },
275 { 0.150985, 0.022740, 0.826274 },
276 { 0.149691, 0.023950, 0.826359 },
277 { 0.148337, 0.025247, 0.826416 },
278 { 0.146928, 0.026635, 0.826437 },
279 { 0.145468, 0.028118, 0.826413 },
280 { 0.143960, 0.029703, 0.826337 },
281 { 0.142405, 0.031394, 0.826201 },
282 { 0.140796, 0.033213, 0.825991 },
283 { 0.139121, 0.035201, 0.825679 },
284 { 0.137364, 0.037403, 0.825233 },
285 { 0.135503, 0.039879, 0.824618 },
286 { 0.133509, 0.042692, 0.823798 },
287 { 0.131371, 0.045876, 0.822753 },
288 { 0.129086, 0.049450, 0.821464 },
289 { 0.126662, 0.053426, 0.819912 },
290 { 0.124118, 0.057803, 0.818079 },
291 { 0.121469, 0.062588, 0.815944 },
292 { 0.118701, 0.067830, 0.813468 },
293 { 0.115807, 0.073581, 0.810612 },
294 { 0.112776, 0.079896, 0.807328 },
295 { 0.109594, 0.086843, 0.803563 },
296 { 0.106261, 0.094486, 0.799253 },
297 { 0.102776, 0.102864, 0.794360 },
298 { 0.099128, 0.112007, 0.788865 },
299 { 0.095304, 0.121945, 0.782751 },
300 { 0.091294, 0.132702, 0.776004 },
301 { 0.087082, 0.144317, 0.768601 },
302 { 0.082680, 0.156866, 0.760455 },
303 { 0.078116, 0.170420, 0.751464 },
304 { 0.073437, 0.185032, 0.741531 },
305 { 0.068706, 0.200723, 0.730571 },
306 { 0.063993, 0.217468, 0.718539 },
307 { 0.059316, 0.235254, 0.705430 },
308 { 0.054667, 0.254096, 0.691238 },
309 { 0.050031, 0.274002, 0.675967 },
310 { 0.045391, 0.294976, 0.659633 },
311 { 0.040757, 0.316981, 0.642262 },
312 { 0.036195, 0.339900, 0.623905 },
313 { 0.031756, 0.363598, 0.604646 },
314 { 0.027494, 0.387921, 0.584584 },
315 { 0.023460, 0.412703, 0.563837 },
316 { 0.019705, 0.437756, 0.542539 },
317 { 0.016268, 0.462955, 0.520777 },
318 { 0.013183, 0.488207, 0.498610 },
319 { 0.010476, 0.513404, 0.476120 },
320 { 0.008168, 0.538423, 0.453409 },
321 { 0.006285, 0.563068, 0.430647 },
322 { 0.004875, 0.587116, 0.408008 },
323 { 0.003982, 0.610447, 0.385570 },
324 { 0.003636, 0.633011, 0.363352 },
325 { 0.003859, 0.654823, 0.341318 },
326 { 0.004646, 0.675898, 0.319456 },
327 { 0.006011, 0.696120, 0.297869 },
328 { 0.007988, 0.715342, 0.276670 },
329 { 0.010603, 0.733413, 0.255984 },
330 { 0.013870, 0.750186, 0.235943 },
331 { 0.017766, 0.765612, 0.216622 },
332 { 0.022244, 0.779630, 0.198126 },
333 { 0.027273, 0.792104, 0.180623 },
334 { 0.032820, 0.802926, 0.164254 },
335 { 0.038852, 0.812016, 0.149132 },
336 { 0.045328, 0.819391, 0.135281 },
337 { 0.052177, 0.825164, 0.122660 },
338 { 0.059326, 0.829426, 0.111249 },
339 { 0.066716, 0.832274, 0.101010 },
340 { 0.074302, 0.833803, 0.091894 },
341 { 0.082053, 0.834090, 0.083856 },
342 { 0.089942, 0.833289, 0.076769 },
343 { 0.097940, 0.831593, 0.070468 },
344 { 0.106021, 0.829178, 0.064801 },
345 { 0.114161, 0.826207, 0.059632 },
346 { 0.122347, 0.822770, 0.054882 },
347 { 0.130546, 0.818928, 0.050526 },
348 { 0.138702, 0.814774, 0.046523 },
349 { 0.146773, 0.810395, 0.042832 },
350 { 0.154722, 0.805864, 0.039414 },
351 { 0.162535, 0.801238, 0.036226 },
352 { 0.170237, 0.796519, 0.033244 },
353 { 0.177850, 0.791687, 0.030464 },
354 { 0.185391, 0.786728, 0.027881 },
355 { 0.192876, 0.781629, 0.025495 },
356 { 0.200309, 0.776399, 0.023292 },
357 { 0.207690, 0.771055, 0.021255 },
358 { 0.215030, 0.765595, 0.019375 },
359 { 0.222337, 0.760020, 0.017643 },
360 { 0.229620, 0.754329, 0.016051 },
361 { 0.236885, 0.748524, 0.014591 },
362 { 0.244133, 0.742614, 0.013253 },
363 { 0.251363, 0.736606, 0.012031 },
364 { 0.258578, 0.730507, 0.010916 },
365 { 0.265775, 0.724324, 0.009901 },
366 { 0.272958, 0.718062, 0.008980 },
367 { 0.280129, 0.711725, 0.008146 },
368 { 0.287292, 0.705316, 0.007391 },
369 { 0.294450, 0.698842, 0.006708 },
370 { 0.301604, 0.692308, 0.006088 },
371 { 0.308760, 0.685712, 0.005528 },
372 { 0.315914, 0.679063, 0.005022 },
373 { 0.323066, 0.672367, 0.004566 },
374 { 0.330216, 0.665628, 0.004156 },
375 { 0.337363, 0.658848, 0.003788 },
376 { 0.344513, 0.652028, 0.003459 },
377 { 0.351664, 0.645172, 0.003163 },
378 { 0.358814, 0.638287, 0.002899 },
379 { 0.365959, 0.631379, 0.002662 },
380 { 0.373102, 0.624451, 0.002448 },
381 { 0.380244, 0.617502, 0.002254 },
382 { 0.387379, 0.610542, 0.002079 },
383 { 0.394507, 0.603571, 0.001922 },
384 { 0.401626, 0.596592, 0.001782 },
385 { 0.408736, 0.589607, 0.001657 },
386 { 0.415836, 0.582618, 0.001546 },
387 { 0.422921, 0.575631, 0.001448 },
388 { 0.429989, 0.568649, 0.001362 },
389 { 0.437036, 0.561676, 0.001288 },
390 { 0.444062, 0.554714, 0.001224 },
391 { 0.451065, 0.547766, 0.001169 },
392 { 0.458041, 0.540837, 0.001123 },
393 { 0.464986, 0.533930, 0.001084 },
394 { 0.471899, 0.527051, 0.001051 },
395 { 0.478775, 0.520202, 0.001023 },
396 { 0.485612, 0.513389, 0.001000 },
397 { 0.492405, 0.506615, 0.000980 },
398 { 0.499151, 0.499887, 0.000962 },
399 { 0.505845, 0.493211, 0.000944 },
400 { 0.512486, 0.486591, 0.000923 },
401 { 0.519073, 0.480029, 0.000899 },
402 { 0.525600, 0.473527, 0.000872 },
403 { 0.532066, 0.467091, 0.000843 },
404 { 0.538463, 0.460725, 0.000812 },
405 { 0.544787, 0.454434, 0.000779 },
406 { 0.551031, 0.448225, 0.000744 },
407 { 0.557193, 0.442099, 0.000708 },
408 { 0.563269, 0.436058, 0.000673 },
409 { 0.569257, 0.430102, 0.000641 },
410 { 0.575151, 0.424232, 0.000616 },
411 { 0.580953, 0.418447, 0.000601 },
412 { 0.586650, 0.412758, 0.000591 },
413 { 0.592225, 0.407190, 0.000586 },
414 { 0.597658, 0.401762, 0.000580 },
415 { 0.602933, 0.396497, 0.000571 },
416 { 0.608035, 0.391409, 0.000556 },
417 { 0.612977, 0.386486, 0.000537 },
418 { 0.617779, 0.381706, 0.000516 },
419 { 0.622459, 0.377047, 0.000493 },
420 { 0.627037, 0.372491, 0.000472 },
421 { 0.631521, 0.368026, 0.000453 },
422 { 0.635900, 0.363665, 0.000435 },
423 { 0.640156, 0.359428, 0.000416 },
424 { 0.644273, 0.355331, 0.000396 },
425 { 0.648233, 0.351395, 0.000372 },
426 { 0.652028, 0.347628, 0.000344 },
427 { 0.655669, 0.344018, 0.000313 },
428 { 0.659166, 0.340553, 0.000281 },
429 { 0.662528, 0.337221, 0.000251 },
430 { 0.665764, 0.334011, 0.000226 },
431 { 0.668874, 0.330919, 0.000207 },
432 { 0.671859, 0.327947, 0.000194 },
433 { 0.674720, 0.325095, 0.000185 },
434 { 0.677459, 0.322362, 0.000179 },
435 { 0.680079, 0.319747, 0.000174 },
436 { 0.682582, 0.317249, 0.000170 },
437 { 0.684971, 0.314863, 0.000167 },
438 { 0.687250, 0.312586, 0.000164 },
439 { 0.689426, 0.310414, 0.000160 },
440 { 0.691504, 0.308342, 0.000154 },
441 { 0.693490, 0.306366, 0.000145 },
442 { 0.695389, 0.304479, 0.000133 },
443 { 0.697206, 0.302675, 0.000119 },
444 { 0.698944, 0.300950, 0.000106 },
445 { 0.700606, 0.299301, 0.000093 },
446 { 0.702193, 0.297725, 0.000083 },
447 { 0.703709, 0.296217, 0.000074 },
448 { 0.705163, 0.294770, 0.000067 },
449 { 0.706563, 0.293376, 0.000061 },
450 { 0.707918, 0.292027, 0.000055 },
451 { 0.709231, 0.290719, 0.000050 },
452 { 0.710500, 0.289453, 0.000047 },
453 { 0.711724, 0.288232, 0.000044 },
454 { 0.712901, 0.287057, 0.000041 },
455 { 0.714032, 0.285929, 0.000040 },
456 { 0.715117, 0.284845, 0.000038 },
457 { 0.716159, 0.283804, 0.000036 },
458 { 0.717159, 0.282806, 0.000035 },
459 { 0.718116, 0.281850, 0.000034 },
460 { 0.719033, 0.280935, 0.000032 },
461 { 0.719912, 0.280058, 0.000030 },
462 { 0.720753, 0.279219, 0.000028 },
463 { 0.721555, 0.278420, 0.000026 },
464 { 0.722315, 0.277662, 0.000023 },
465 { 0.723032, 0.276948, 0.000020 },
466 { 0.723702, 0.276282, 0.000016 },
467 { 0.724328, 0.275660, 0.000012 },
468 { 0.724914, 0.275078, 0.000007 },
469 { 0.725467, 0.274530, 0.000003 },
470 { 0.725992, 0.274008, 0.000000 },
471 { 0.726495, 0.273505, 0.000000 },
472 { 0.726975, 0.273025, 0.000000 },
473 { 0.727432, 0.272568, 0.000000 },
474 { 0.727864, 0.272136, 0.000000 },
475 { 0.728272, 0.271728, 0.000000 },
476 { 0.728656, 0.271344, 0.000000 },
477 { 0.729020, 0.270980, 0.000000 },
478 { 0.729361, 0.270639, 0.000000 },
479 { 0.729678, 0.270322, 0.000000 },
480 { 0.729969, 0.270031, 0.000000 },
481 { 0.730234, 0.269766, 0.000000 },
482 { 0.730474, 0.269526, 0.000000 },
483 { 0.730693, 0.269307, 0.000000 },
484 { 0.730896, 0.269104, 0.000000 },
485 { 0.731089, 0.268911, 0.000000 },
486 { 0.731280, 0.268720, 0.000000 },
487 { 0.731467, 0.268533, 0.000000 },
488 { 0.731650, 0.268350, 0.000000 },
489 { 0.731826, 0.268174, 0.000000 },
490 { 0.731993, 0.268007, 0.000000 },
491 { 0.732150, 0.267850, 0.000000 },
492 { 0.732300, 0.267700, 0.000000 },
493 { 0.732443, 0.267557, 0.000000 },
494 { 0.732581, 0.267419, 0.000000 },
495 { 0.732719, 0.267281, 0.000000 },
496 { 0.732859, 0.267141, 0.000000 },
497 { 0.733000, 0.267000, 0.000000 },
498 { 0.733142, 0.266858, 0.000000 },
499 { 0.733281, 0.266719, 0.000000 },
500 { 0.733417, 0.266583, 0.000000 },
501 { 0.733551, 0.266449, 0.000000 },
502 { 0.733683, 0.266317, 0.000000 },
503 { 0.733813, 0.266187, 0.000000 },
504 { 0.733936, 0.266064, 0.000000 },
505 { 0.734047, 0.265953, 0.000000 },
506 { 0.734143, 0.265857, 0.000000 },
507 { 0.734221, 0.265779, 0.000000 },
508 { 0.734286, 0.265714, 0.000000 },
509 { 0.734341, 0.265659, 0.000000 },
510 { 0.734390, 0.265610, 0.000000 },
511 { 0.734438, 0.265562, 0.000000 },
512 { 0.734482, 0.265518, 0.000000 },
513 { 0.734523, 0.265477, 0.000000 },
514 { 0.734560, 0.265440, 0.000000 },
515 { 0.734592, 0.265408, 0.000000 },
516 { 0.734621, 0.265379, 0.000000 },
517 { 0.734649, 0.265351, 0.000000 },
518 { 0.734673, 0.265327, 0.000000 },
519 { 0.734690, 0.265310, 0.000000 },
520 { 0.734690, 0.265310, 0.000000 },
521 { 0.734690, 0.265310, 0.000000 },
522 { 0.734690, 0.265310, 0.000000 },
523 { 0.734690, 0.265310, 0.000000 },
524 { 0.734690, 0.265310, 0.000000 },
525 { 0.734690, 0.265310, 0.000000 },
526 { 0.734690, 0.265310, 0.000000 },
527 { 0.734690, 0.265310, 0.000000 },
528 { 0.734690, 0.265310, 0.000000 },
529 { 0.734690, 0.265310, 0.000000 },
530 { 0.734690, 0.265310, 0.000000 },
531 { 0.734690, 0.265310, 0.000000 },
532 { 0.734690, 0.265310, 0.000000 },
533 { 0.734690, 0.265310, 0.000000 },
534 { 0.734690, 0.265310, 0.000000 },
535 { 0.734690, 0.265310, 0.000000 },
536 { 0.734690, 0.265310, 0.000000 },
537 { 0.734690, 0.265310, 0.000000 },
538 { 0.734690, 0.265310, 0.000000 },
539 { 0.734690, 0.265310, 0.000000 },
540 { 0.734690, 0.265310, 0.000000 },
541 { 0.734690, 0.265310, 0.000000 },
542 { 0.734690, 0.265310, 0.000000 },
543 { 0.734690, 0.265310, 0.000000 },
544 { 0.734690, 0.265310, 0.000000 },
545 { 0.734690, 0.265310, 0.000000 },
546 { 0.734690, 0.265310, 0.000000 },
547 { 0.734690, 0.265310, 0.000000 },
548 { 0.734690, 0.265310, 0.000000 },
549 { 0.734690, 0.265310, 0.000000 },
550 { 0.734690, 0.265310, 0.000000 },
551 { 0.734690, 0.265310, 0.000000 },
552 { 0.734690, 0.265310, 0.000000 },
553 { 0.734690, 0.265310, 0.000000 },
554 { 0.734690, 0.265310, 0.000000 },
555 { 0.734690, 0.265310, 0.000000 },
556 { 0.734690, 0.265310, 0.000000 },
557 { 0.734690, 0.265310, 0.000000 },
558 { 0.734690, 0.265310, 0.000000 },
559 { 0.734690, 0.265310, 0.000000 },
560 { 0.734690, 0.265310, 0.000000 },
561 { 0.734690, 0.265310, 0.000000 },
562 { 0.734690, 0.265310, 0.000000 },
563 { 0.734690, 0.265310, 0.000000 },
564 { 0.734690, 0.265310, 0.000000 },
565 { 0.734690, 0.265310, 0.000000 },
566 { 0.734690, 0.265310, 0.000000 },
567 { 0.734690, 0.265310, 0.000000 },
568 { 0.734690, 0.265310, 0.000000 },
569 { 0.734690, 0.265310, 0.000000 },
570 { 0.734690, 0.265310, 0.000000 },
571 { 0.734690, 0.265310, 0.000000 },
572 { 0.734690, 0.265310, 0.000000 },
573 { 0.734690, 0.265310, 0.000000 },
574 { 0.734690, 0.265310, 0.000000 },
575 { 0.734690, 0.265310, 0.000000 },
576 { 0.734690, 0.265310, 0.000000 },
577 { 0.734690, 0.265310, 0.000000 },
578 { 0.734690, 0.265310, 0.000000 },
579 { 0.734690, 0.265310, 0.000000 },
580 { 0.734690, 0.265310, 0.000000 },
581 { 0.734690, 0.265310, 0.000000 },
582 { 0.734690, 0.265310, 0.000000 },
583 { 0.734690, 0.265310, 0.000000 },
584 { 0.734690, 0.265310, 0.000000 },
585 { 0.734690, 0.265310, 0.000000 },
586 { 0.734690, 0.265310, 0.000000 },
587 { 0.734690, 0.265310, 0.000000 },
588 { 0.734690, 0.265310, 0.000000 },
589 { 0.734690, 0.265310, 0.000000 },
590 { 0.734690, 0.265310, 0.000000 },
591 { 0.734690, 0.265310, 0.000000 },
592 { 0.734690, 0.265310, 0.000000 },
593 { 0.734690, 0.265310, 0.000000 },
594 { 0.734690, 0.265310, 0.000000 },
595 { 0.734690, 0.265310, 0.000000 },
596 { 0.734690, 0.265310, 0.000000 },
597 { 0.734690, 0.265310, 0.000000 },
598 { 0.734690, 0.265310, 0.000000 },
599 { 0.734690, 0.265310, 0.000000 },
600 { 0.734690, 0.265310, 0.000000 },
601 { 0.734690, 0.265310, 0.000000 },
602 { 0.734690, 0.265310, 0.000000 },
603 { 0.734690, 0.265310, 0.000000 },
604 { 0.734690, 0.265310, 0.000000 },
605 { 0.734690, 0.265310, 0.000000 },
606 { 0.734690, 0.265310, 0.000000 },
607 { 0.734690, 0.265310, 0.000000 },
608 { 0.734690, 0.265310, 0.000000 },
609 { 0.734690, 0.265310, 0.000000 },
610 { 0.734690, 0.265310, 0.000000 },
611 { 0.734690, 0.265310, 0.000000 },
612 { 0.734690, 0.265310, 0.000000 },
613 { 0.734690, 0.265310, 0.000000 },
614 { 0.734690, 0.265310, 0.000000 },
615 { 0.734690, 0.265310, 0.000000 },
616 { 0.734690, 0.265310, 0.000000 },
617 { 0.734690, 0.265310, 0.000000 },
618 { 0.734690, 0.265310, 0.000000 },
619 { 0.734690, 0.265310, 0.000000 },
620 { 0.734690, 0.265310, 0.000000 },
621 { 0.734690, 0.265310, 0.000000 },
622 { 0.734690, 0.265310, 0.000000 },
623 { 0.734690, 0.265310, 0.000000 },
624 { 0.734690, 0.265310, 0.000000 },
625 { 0.734690, 0.265310, 0.000000 },
626 { 0.734690, 0.265310, 0.000000 },
627 { 0.734690, 0.265310, 0.000000 },
628 { 0.734690, 0.265310, 0.000000 },
629 { 0.734690, 0.265310, 0.000000 },
630 { 0.734690, 0.265310, 0.000000 },
631 { 0.734690, 0.265310, 0.000000 },
632 { 0.734690, 0.265310, 0.000000 },
633 { 0.734690, 0.265310, 0.000000 },
634 { 0.734690, 0.265310, 0.000000 },
635 { 0.734690, 0.265310, 0.000000 },
636 { 0.734690, 0.265310, 0.000000 },
637 { 0.734690, 0.265310, 0.000000 },
638 { 0.734690, 0.265310, 0.000000 },
639 { 0.734690, 0.265310, 0.000000 },
640 { 0.734690, 0.265310, 0.000000 },
641 { 0.734690, 0.265310, 0.000000 },
642 { 0.734690, 0.265310, 0.000000 },
643 { 0.734690, 0.265310, 0.000000 },
644 { 0.734690, 0.265310, 0.000000 },
645 { 0.734690, 0.265310, 0.000000 },
646 { 0.734690, 0.265310, 0.000000 },
647 { 0.734690, 0.265310, 0.000000 },
648 { 0.734690, 0.265310, 0.000000 },
649 { 0.734690, 0.265310, 0.000000 },
650 { 0.734690, 0.265310, 0.000000 },
651};
652
653
654/* Standard white point chromaticities. */
655
656#define C 0.310063, 0.316158
657#define E 1.0/3.0, 1.0/3.0
658#define D50 0.34570, 0.3585
659#define D65 0.312713, 0.329016
660
661/* Gamma of nonlinear correction.
662 See Charles Poynton's ColorFAQ Item 45 and GammaFAQ Item 6 at
663 http://www.inforamp.net/~poynton/ColorFAQ.html
664 http://www.inforamp.net/~poynton/GammaFAQ.html
665*/
666
667#define GAMMA_REC709 0. /* Rec. 709 */
668
669static const struct ColorSystem color_systems[] = {
670 [NTSCsystem] = {
671 0.67, 0.33, 0.21, 0.71, 0.14, 0.08,
673 },
674 [EBUsystem] = {
675 0.64, 0.33, 0.29, 0.60, 0.15, 0.06,
677 },
678 [SMPTEsystem] = {
679 0.630, 0.340, 0.310, 0.595, 0.155, 0.070,
681 },
682 [SMPTE240Msystem] = {
683 0.670, 0.330, 0.210, 0.710, 0.150, 0.060,
685 },
686 [APPLEsystem] = {
687 0.625, 0.340, 0.280, 0.595, 0.115, 0.070,
689 },
690 [wRGBsystem] = {
691 0.7347, 0.2653, 0.1152, 0.8264, 0.1566, 0.0177,
693 },
694 [CIE1931system] = {
695 0.7347, 0.2653, 0.2738, 0.7174, 0.1666, 0.0089,
697 },
698 [Rec709system] = {
699 0.64, 0.33, 0.30, 0.60, 0.15, 0.06,
701 },
702 [Rec2020system] = {
703 0.708, 0.292, 0.170, 0.797, 0.131, 0.046,
705 },
706 [DCIP3] = {
707 0.680, 0.320, 0.265, 0.690, 0.150, 0.060,
708 0.314, 0.351, GAMMA_REC709
709 },
710};
711
712/*
713static struct ColorSystem CustomSystem = {
714 "Custom",
715 0.64, 0.33, 0.30, 0.60, 0.15, 0.06,
716 D65, GAMMA_REC709
717};
718*/
719
720static void
721uv_to_xy(float const u,
722 float const v,
723 float *const xc,
724 float *const yc)
725{
726/*
727 Given 1970 coordinates u, v, determine 1931 chromaticities x, y
728*/
729 *xc = 3.f*u / (2.f*u - 8.f*v + 4.f);
730 *yc = 2.f*v / (2.f*u - 8.f*v + 4.f);
731}
732
733static void
734upvp_to_xy(float const up,
735 float const vp,
736 float * const xc,
737 float * const yc)
738{
739/*
740 Given 1976 coordinates u', v', determine 1931 chromaticities x, y
741*/
742 *xc = 9*up / (6*up - 16*vp + 12);
743 *yc = 4*vp / (6*up - 16*vp + 12);
744}
745
746static void
747xy_to_upvp(float xc,
748 float yc,
749 float * const up,
750 float * const vp)
751{
752/*
753 Given 1931 chromaticities x, y, determine 1976 coordinates u', v'
754*/
755 const float scale = 1.f / (-2.f*xc + 12.f*yc + 3.f);
756 *up = 4.f*xc * scale;
757 *vp = 9.f*yc * scale;
758}
759
760static void
761xy_to_uv(float xc,
762 float yc,
763 float * const u,
764 float * const v)
765{
766/*
767 Given 1931 chromaticities x, y, determine 1960 coordinates u, v
768*/
769 const float scale = 1.f / (-2.f*xc + 12.f*yc + 3.f);
770 *u = 4.f*xc * scale;
771 *v = 6.f*yc * scale;
772}
773
774static void
775xyz_to_rgb(const float m[3][3],
776 float xc, float yc, float zc,
777 float * const r, float * const g, float * const b)
778{
779 *r = m[0][0]*xc + m[0][1]*yc + m[0][2]*zc;
780 *g = m[1][0]*xc + m[1][1]*yc + m[1][2]*zc;
781 *b = m[2][0]*xc + m[2][1]*yc + m[2][2]*zc;
782}
783
784static void invert_matrix3x3(float in[3][3], float out[3][3])
785{
786 float m00 = in[0][0], m01 = in[0][1], m02 = in[0][2],
787 m10 = in[1][0], m11 = in[1][1], m12 = in[1][2],
788 m20 = in[2][0], m21 = in[2][1], m22 = in[2][2];
789 int i, j;
790 float det;
791
792 out[0][0] = (m11 * m22 - m21 * m12);
793 out[0][1] = -(m01 * m22 - m21 * m02);
794 out[0][2] = (m01 * m12 - m11 * m02);
795 out[1][0] = -(m10 * m22 - m20 * m12);
796 out[1][1] = (m00 * m22 - m20 * m02);
797 out[1][2] = -(m00 * m12 - m10 * m02);
798 out[2][0] = (m10 * m21 - m20 * m11);
799 out[2][1] = -(m00 * m21 - m20 * m01);
800 out[2][2] = (m00 * m11 - m10 * m01);
801
802 det = m00 * out[0][0] + m10 * out[0][1] + m20 * out[0][2];
803 det = 1.0 / det;
804
805 for (i = 0; i < 3; i++) {
806 for (j = 0; j < 3; j++)
807 out[i][j] *= det;
808 }
809}
810
811static void get_rgb2xyz_matrix(struct ColorSystem system, float m[3][3])
812{
813 float S[3], X[4], Z[4];
814 int i;
815
816 X[0] = system.xRed / system.yRed;
817 X[1] = system.xGreen / system.yGreen;
818 X[2] = system.xBlue / system.yBlue;
819 X[3] = system.xWhite / system.yWhite;
820
821 Z[0] = (1 - system.xRed - system.yRed) / system.yRed;
822 Z[1] = (1 - system.xGreen - system.yGreen) / system.yGreen;
823 Z[2] = (1 - system.xBlue - system.yBlue) / system.yBlue;
824 Z[3] = (1 - system.xWhite - system.yWhite) / system.yWhite;
825
826 for (i = 0; i < 3; i++) {
827 m[0][i] = X[i];
828 m[1][i] = 1;
829 m[2][i] = Z[i];
830 }
831
832 invert_matrix3x3(m, m);
833
834 for (i = 0; i < 3; i++)
835 S[i] = m[i][0] * X[3] + m[i][1] * 1 + m[i][2] * Z[3];
836
837 for (i = 0; i < 3; i++) {
838 m[0][i] = S[i] * X[i];
839 m[1][i] = S[i] * 1;
840 m[2][i] = S[i] * Z[i];
841 }
842}
843
844static void
845rgb_to_xy(float rc,
846 float gc,
847 float bc,
848 float * const x,
849 float * const y,
850 float * const z,
851 const float m[3][3])
852{
853 float scale;
854
855 *x = m[0][0] * rc + m[0][1] * gc + m[0][2] * bc;
856 *y = m[1][0] * rc + m[1][1] * gc + m[1][2] * bc;
857 *z = m[2][0] * rc + m[2][1] * gc + m[2][2] * bc;
858
859 scale = *x + *y + *z;
860 scale = 1.f / scale;
861 *x = *x * scale;
862 *y = *y * scale;
863}
864
865static int
866constrain_rgb(float * const r,
867 float * const g,
868 float * const b)
869{
870/*----------------------------------------------------------------------------
871 If the requested RGB shade contains a negative weight for one of
872 the primaries, it lies outside the color gamut accessible from
873 the given triple of primaries. Desaturate it by adding white,
874 equal quantities of R, G, and B, enough to make RGB all positive.
875-----------------------------------------------------------------------------*/
876 float w;
877
878 /* Amount of white needed is w = - min(0, *r, *g, *b) */
879 w = (0 < *r) ? 0 : *r;
880 w = (w < *g) ? w : *g;
881 w = (w < *b) ? w : *b;
882 w = - w;
883
884 /* Add just enough white to make r, g, b all positive. */
885 if (w > 0) {
886 *r += w; *g += w; *b += w;
887
888 return 1; /* Color modified to fit RGB gamut */
889 }
890
891 return 0; /* Color within RGB gamut */
892}
893
894static void
895gamma_correct(const struct ColorSystem * const cs,
896 float * const c)
897{
898/*----------------------------------------------------------------------------
899 Transform linear RGB values to nonlinear RGB values.
900
901 Rec. 709 is ITU-R Recommendation BT. 709 (1990)
902 ``Basic Parameter Values for the HDTV Standard for the Studio and for
903 International Programme Exchange'', formerly CCIR Rec. 709.
904
905 For details see
906 http://www.inforamp.net/~poynton/ColorFAQ.html
907 http://www.inforamp.net/~poynton/GammaFAQ.html
908-----------------------------------------------------------------------------*/
909 float gamma;
910 float cc;
911
912 gamma = cs->gamma;
913
914 if (gamma == 0.) {
915 /* Rec. 709 gamma correction. */
916 cc = 0.018;
917 if (*c < cc) {
918 *c *= (1.099 * pow(cc, 0.45) - 0.099) / cc;
919 } else {
920 *c = 1.099 * pow(*c, 0.45) - 0.099;
921 }
922 } else {
923 /* Nonlinear color = (Linear color)^(1/gamma) */
924 *c = pow(*c, 1./gamma);
925 }
926}
927
928
929
930static void
931gamma_correct_rgb(const struct ColorSystem * const cs,
932 float * const r,
933 float * const g,
934 float * const b)
935{
936 gamma_correct(cs, r);
937 gamma_correct(cs, g);
938 gamma_correct(cs, b);
939}
940
941/* Sz(X) is the displacement in pixels of a displacement of X normalized
942 distance units. (A normalized distance unit is 1/512 of the smaller
943 dimension of the canvas)
944*/
945#define Sz(x) (((x) * (int)FFMIN(w, h)) / 512)
946
947static void
948monochrome_color_location(float waveLength, int w, int h,
949 int cie, int *xP, int *yP)
950{
951 const int ix = waveLength - 360;
952 const float pX = spectral_chromaticity[ix][0];
953 const float pY = spectral_chromaticity[ix][1];
954 const float pZ = spectral_chromaticity[ix][2];
955 const float px = pX / (pX + pY + pZ);
956 const float py = pY / (pX + pY + pZ);
957
958 if (cie == LUV) {
959 float up, vp;
960
961 xy_to_upvp(px, py, &up, &vp);
962 *xP = up * (w - 1);
963 *yP = (h - 1) - vp * (h - 1);
964 } else if (cie == UCS) {
965 float u, v;
966
967 xy_to_uv(px, py, &u, &v);
968 *xP = u * (w - 1);
969 *yP = (h - 1) - v * (h - 1);
970 } else if (cie == XYY) {
971 *xP = px * (w - 1);
972 *yP = (h - 1) - py * (h - 1);
973 } else {
974 av_assert0(0);
975 }
976}
977
978static void
979find_tongue(uint16_t* const pixels,
980 int const w,
981 int const linesize,
982 int const row,
983 int * const presentP,
984 int * const leftEdgeP,
985 int * const rightEdgeP)
986{
987 int i;
988
989 for (i = 0; i < w && pixels[row * linesize + i * 4 + 0] == 0; i++)
990 ;
991
992 if (i >= w) {
993 *presentP = 0;
994 } else {
995 int j;
996 int const leftEdge = i;
997
998 *presentP = 1;
999
1000 for (j = w - 1; j >= leftEdge && pixels[row * linesize + j * 4 + 0] == 0; j--)
1001 ;
1002
1003 *rightEdgeP = j;
1004 *leftEdgeP = leftEdge;
1005 }
1006}
1007
1008static void draw_line(uint16_t *const pixels, int linesize,
1009 int x0, int y0, int x1, int y1,
1010 int w, int h,
1011 const uint16_t *const rgbcolor)
1012{
1013 int sx = x0 < x1 ? 1 : -1, sy = y0 < y1 ? 1 : -1, x2;
1014 int dx = FFABS(x1-x0), dy = FFABS(y1-y0), err = dx * dx + dy * dy;
1015 int e2 = err == 0 ? 1 : 0xffffff / (dx + dy);
1016
1017 dx *= e2;
1018 dy *= e2;
1019 err = dx - dy;
1020
1021 for (;;) {
1022 pixels[y0 * linesize + x0 * 4 + 0] = rgbcolor[0]-(FFABS(err - dx + dy) >> 8);
1023 pixels[y0 * linesize + x0 * 4 + 1] = rgbcolor[1]-(FFABS(err - dx + dy) >> 8);
1024 pixels[y0 * linesize + x0 * 4 + 2] = rgbcolor[2]-(FFABS(err - dx + dy) >> 8);
1025 pixels[y0 * linesize + x0 * 4 + 3] = rgbcolor[3]-(FFABS(err - dx + dy) >> 8);
1026
1027 e2 = err;
1028 x2 = x0;
1029 if (2 * e2 >= -dx) {
1030 if (x0 == x1)
1031 break;
1032 if (e2 + dy < 0xff0000) {
1033 pixels[(y0 + sy) * linesize + x0 * 4 + 0] = rgbcolor[0]-(FFABS(e2 + dy) >> 8);
1034 pixels[(y0 + sy) * linesize + x0 * 4 + 1] = rgbcolor[1]-(FFABS(e2 + dy) >> 8);
1035 pixels[(y0 + sy) * linesize + x0 * 4 + 2] = rgbcolor[2]-(FFABS(e2 + dy) >> 8);
1036 pixels[(y0 + sy) * linesize + x0 * 4 + 3] = rgbcolor[3]-(FFABS(e2 + dy) >> 8);
1037 }
1038 err -= dy;
1039 x0 += sx;
1040 }
1041
1042 if (2 * e2 <= dy) {
1043 if (y0 == y1)
1044 break;
1045 if (dx - e2 < 0xff0000) {
1046 pixels[y0 * linesize + (x2 + sx) * 4 + 0] = rgbcolor[0]-(FFABS(dx - e2) >> 8);
1047 pixels[y0 * linesize + (x2 + sx) * 4 + 1] = rgbcolor[1]-(FFABS(dx - e2) >> 8);
1048 pixels[y0 * linesize + (x2 + sx) * 4 + 2] = rgbcolor[2]-(FFABS(dx - e2) >> 8);
1049 pixels[y0 * linesize + (x2 + sx) * 4 + 3] = rgbcolor[3]-(FFABS(dx - e2) >> 8);
1050 }
1051 err += dx;
1052 y0 += sy;
1053 }
1054 }
1055}
1056
1057static void draw_rline(uint16_t *const pixels, int linesize,
1058 int x0, int y0, int x1, int y1,
1059 int w, int h)
1060{
1061 int dx = FFABS(x1 - x0), sx = x0 < x1 ? 1 : -1;
1062 int dy = FFABS(y1 - y0), sy = y0 < y1 ? 1 : -1;
1063 int err = (dx > dy ? dx : -dy) / 2, e2;
1064
1065 for (;;) {
1066 pixels[y0 * linesize + x0 * 4 + 0] = 65535 - pixels[y0 * linesize + x0 * 4 + 0];
1067 pixels[y0 * linesize + x0 * 4 + 1] = 65535 - pixels[y0 * linesize + x0 * 4 + 1];
1068 pixels[y0 * linesize + x0 * 4 + 2] = 65535 - pixels[y0 * linesize + x0 * 4 + 2];
1069 pixels[y0 * linesize + x0 * 4 + 3] = 65535;
1070
1071 if (x0 == x1 && y0 == y1)
1072 break;
1073
1074 e2 = err;
1075
1076 if (e2 >-dx) {
1077 err -= dy;
1078 x0 += sx;
1079 }
1080
1081 if (e2 < dy) {
1082 err += dx;
1083 y0 += sy;
1084 }
1085 }
1086}
1087
1088static void
1089tongue_outline(uint16_t* const pixels,
1090 int const linesize,
1091 int const w,
1092 int const h,
1093 uint16_t const maxval,
1094 int const cie)
1095{
1096 const uint16_t rgbcolor[4] = { maxval, maxval, maxval, maxval };
1097 int wavelength;
1098 int lx, ly;
1099 int fx, fy;
1100
1101 for (wavelength = 360; wavelength <= 830; wavelength++) {
1102 int icx, icy;
1103
1104 monochrome_color_location(wavelength, w, h, cie,
1105 &icx, &icy);
1106
1107 if (wavelength > 360)
1108 draw_line(pixels, linesize, lx, ly, icx, icy, w, h, rgbcolor);
1109 else {
1110 fx = icx;
1111 fy = icy;
1112 }
1113 lx = icx;
1114 ly = icy;
1115 }
1116 draw_line(pixels, linesize, lx, ly, fx, fy, w, h, rgbcolor);
1117}
1118
1119static void
1120fill_in_tongue(uint16_t* const pixels,
1121 int const linesize,
1122 int const w,
1123 int const h,
1124 uint16_t const maxval,
1125 const struct ColorSystem * const cs,
1126 float const m[3][3],
1127 int const cie,
1128 int const correct_gamma,
1129 float const contrast)
1130{
1131 int y;
1132
1133 /* Scan the image line by line and fill the tongue outline
1134 with the RGB values determined by the color system for the x-y
1135 coordinates within the tongue.
1136 */
1137
1138 for (y = 0; y < h; ++y) {
1139 int present; /* There is some tongue on this line */
1140 int leftEdge; /* x position of leftmost pixel in tongue on this line */
1141 int rightEdge; /* same, but rightmost */
1142
1143 find_tongue(pixels, w, linesize, y, &present, &leftEdge, &rightEdge);
1144
1145 if (present) {
1146 int x;
1147
1148 for (x = leftEdge; x <= rightEdge; ++x) {
1149 float cx, cy, cz, jr, jg, jb, jmax;
1150 int r, g, b, mx = maxval;
1151
1152 if (cie == LUV) {
1153 float up, vp;
1154 up = ((float) x) / (w - 1);
1155 vp = 1.0 - ((float) y) / (h - 1);
1156 upvp_to_xy(up, vp, &cx, &cy);
1157 cz = 1.0 - (cx + cy);
1158 } else if (cie == UCS) {
1159 float u, v;
1160 u = ((float) x) / (w - 1);
1161 v = 1.0 - ((float) y) / (h - 1);
1162 uv_to_xy(u, v, &cx, &cy);
1163 cz = 1.0 - (cx + cy);
1164 } else if (cie == XYY) {
1165 cx = ((float) x) / (w - 1);
1166 cy = 1.0 - ((float) y) / (h - 1);
1167 cz = 1.0 - (cx + cy);
1168 } else {
1169 av_assert0(0);
1170 }
1171
1172 xyz_to_rgb(m, cx, cy, cz, &jr, &jg, &jb);
1173
1174 /* Check whether the requested color is within the
1175 gamut achievable with the given color system. If
1176 not, draw it in a reduced intensity, interpolated
1177 by desaturation to the closest within-gamut color. */
1178
1179 if (constrain_rgb(&jr, &jg, &jb))
1180 mx *= contrast;
1181
1182 jmax = FFMAX3(jr, jg, jb);
1183 if (jmax > 0) {
1184 jr = jr / jmax;
1185 jg = jg / jmax;
1186 jb = jb / jmax;
1187 }
1188 /* gamma correct from linear rgb to nonlinear rgb. */
1189 if (correct_gamma)
1190 gamma_correct_rgb(cs, &jr, &jg, &jb);
1191 r = mx * jr;
1192 g = mx * jg;
1193 b = mx * jb;
1194 pixels[y * linesize + x * 4 + 0] = r;
1195 pixels[y * linesize + x * 4 + 1] = g;
1196 pixels[y * linesize + x * 4 + 2] = b;
1197 pixels[y * linesize + x * 4 + 3] = 65535;
1198 }
1199 }
1200 }
1201}
1202
1203static void
1204plot_white_point(uint16_t* pixels,
1205 int const linesize,
1206 int const w,
1207 int const h,
1208 int const maxval,
1209 int const color_system,
1210 int const cie)
1211{
1212 const struct ColorSystem *cs = &color_systems[color_system];
1213 int wx, wy;
1214
1215 if (cie == LUV) {
1216 float wup, wvp;
1217 xy_to_upvp(cs->xWhite, cs->yWhite, &wup, &wvp);
1218 wx = (w - 1) * wup;
1219 wy = (h - 1) - ((int) ((h - 1) * wvp));
1220 } else if (cie == UCS) {
1221 float wu, wv;
1222 xy_to_uv(cs->xWhite, cs->yWhite, &wu, &wv);
1223 wx = (w - 1) * wu;
1224 wy = (h - 1) - ((int) ((h - 1) * wv));
1225 } else if (cie == XYY) {
1226 wx = (w - 1) * cs->xWhite;
1227 wy = (h - 1) - ((int) ((h - 1) * cs->yWhite));
1228 } else {
1229 av_assert0(0);
1230 }
1231
1232 draw_rline(pixels, linesize,
1233 wx + Sz(3), wy, wx + Sz(10), wy,
1234 w, h);
1235 draw_rline(pixels, linesize,
1236 wx - Sz(3), wy, wx - Sz(10), wy,
1237 w, h);
1238 draw_rline(pixels, linesize,
1239 wx, wy + Sz(3), wx, wy + Sz(10),
1240 w, h);
1241 draw_rline(pixels, linesize,
1242 wx, wy - Sz(3), wx, wy - Sz(10),
1243 w, h);
1244}
1245
1247{
1248 CiescopeContext *s = ctx->priv;
1249 const struct ColorSystem *cs = &color_systems[s->color_system];
1250 AVFilterLink *outlink = ctx->outputs[0];
1251 int w = s->size;
1252 int h = s->size;
1253 uint16_t *pixels;
1254
1255 if ((s->f = ff_get_video_buffer(outlink, outlink->w, outlink->h)) == NULL)
1256 return AVERROR(ENOMEM);
1257 pixels = (uint16_t *)s->f->data[0];
1258
1259 tongue_outline(pixels, s->f->linesize[0] / 2, w, h, 65535, s->cie);
1260
1261 if (s->fill)
1262 fill_in_tongue(pixels, s->f->linesize[0] / 2, w, h, 65535, cs, (const float (*)[3])s->i, s->cie,
1263 s->correct_gamma, s->contrast);
1264
1265 return 0;
1266}
1267
1268static void filter_rgb48(AVFilterContext *ctx, const uint8_t *ptr,
1269 ptrdiff_t linesize,
1270 float *cx, float *cy, int x, int y)
1271{
1272 CiescopeContext *s = ctx->priv;
1273 const float scale = 1.f / 65535.f;
1274 const uint16_t *src = (const uint16_t*)(ptr + linesize * y + x * 6);
1275 float r = (src[0] + 0.01f) * scale;
1276 float g = (src[1] + 0.01f) * scale;
1277 float b = (src[2] + 0.01f) * scale;
1278 float cz;
1279
1280 rgb_to_xy(r, g, b, cx, cy, &cz, (const float (*)[3])s->m);
1281}
1282
1283static void filter_rgba64(AVFilterContext *ctx, const uint8_t *ptr,
1284 ptrdiff_t linesize,
1285 float *cx, float *cy, int x, int y)
1286{
1287 CiescopeContext *s = ctx->priv;
1288 const float scale = 1.f / 65535.f;
1289 const uint16_t *src = (const uint16_t*)(ptr + linesize * y + x * 8);
1290 float r = (src[0] + 0.01f) * scale;
1291 float g = (src[1] + 0.01f) * scale;
1292 float b = (src[2] + 0.01f) * scale;
1293 float cz;
1294
1295 rgb_to_xy(r, g, b, cx, cy, &cz, (const float (*)[3])s->m);
1296}
1297
1298static void filter_rgb24(AVFilterContext *ctx, const uint8_t *ptr,
1299 ptrdiff_t linesize,
1300 float *cx, float *cy, int x, int y)
1301{
1302 CiescopeContext *s = ctx->priv;
1303 const float scale = 1.f / 255.f;
1304 const uint8_t *src = ptr + linesize * y + x * 3;
1305 float r = (src[0] + 0.01f) * scale;
1306 float g = (src[1] + 0.01f) * scale;
1307 float b = (src[2] + 0.01f) * scale;
1308 float cz;
1309
1310 rgb_to_xy(r, g, b, cx, cy, &cz, (const float (*)[3])s->m);
1311}
1312
1313static void filter_rgba(AVFilterContext *ctx, const uint8_t *ptr,
1314 ptrdiff_t linesize,
1315 float *cx, float *cy, int x, int y)
1316{
1317 CiescopeContext *s = ctx->priv;
1318 const float scale = 1.f / 255.f;
1319 const uint8_t *src = ptr + linesize * y + x * 4;
1320 float r = (src[0] + 0.01f) * scale;
1321 float g = (src[1] + 0.01f) * scale;
1322 float b = (src[2] + 0.01f) * scale;
1323 float cz;
1324
1325 rgb_to_xy(r, g, b, cx, cy, &cz, (const float (*)[3])s->m);
1326}
1327
1328static void filter_xyz(AVFilterContext *ctx, const uint8_t *ptr,
1329 ptrdiff_t linesize,
1330 float *cx, float *cy, int x, int y)
1331{
1332 CiescopeContext *s = ctx->priv;
1333 const uint16_t* src = (uint16_t *)(ptr + linesize * y + x * 6);
1334 float lx = s->log2lin[src[0]];
1335 float ly = s->log2lin[src[1]];
1336 float lz = s->log2lin[src[2]];
1337 float sum = lx + ly + lz;
1338
1339 if (sum == 0)
1340 sum = 1;
1341 *cx = lx / sum;
1342 *cy = ly / sum;
1343}
1344
1345static void plot_gamuts(uint16_t *pixels, int linesize, int w, int h,
1346 int cie, int gamuts)
1347{
1348 int i;
1349
1350 for (i = 0; i < NB_CS; i++) {
1351 const struct ColorSystem *cs = &color_systems[i];
1352 int rx, ry, gx, gy, bx, by;
1353
1354 if (!((1 << i) & gamuts))
1355 continue;
1356 if (cie == LUV) {
1357 float wup, wvp;
1358 xy_to_upvp(cs->xRed, cs->yRed, &wup, &wvp);
1359 rx = (w - 1) * wup;
1360 ry = (h - 1) - ((int) ((h - 1) * wvp));
1361 xy_to_upvp(cs->xGreen, cs->yGreen, &wup, &wvp);
1362 gx = (w - 1) * wup;
1363 gy = (h - 1) - ((int) ((h - 1) * wvp));
1364 xy_to_upvp(cs->xBlue, cs->yBlue, &wup, &wvp);
1365 bx = (w - 1) * wup;
1366 by = (h - 1) - ((int) ((h - 1) * wvp));
1367 } else if (cie == UCS) {
1368 float wu, wv;
1369 xy_to_uv(cs->xRed, cs->yRed, &wu, &wv);
1370 rx = (w - 1) * wu;
1371 ry = (h - 1) - ((int) ((h - 1) * wv));
1372 xy_to_uv(cs->xGreen, cs->yGreen, &wu, &wv);
1373 gx = (w - 1) * wu;
1374 gy = (h - 1) - ((int) ((h - 1) * wv));
1375 xy_to_uv(cs->xBlue, cs->yBlue, &wu, &wv);
1376 bx = (w - 1) * wu;
1377 by = (h - 1) - ((int) ((h - 1) * wv));
1378 } else if (cie == XYY) {
1379 rx = (w - 1) * cs->xRed;
1380 ry = (h - 1) - ((int) ((h - 1) * cs->yRed));
1381 gx = (w - 1) * cs->xGreen;
1382 gy = (h - 1) - ((int) ((h - 1) * cs->yGreen));
1383 bx = (w - 1) * cs->xBlue;
1384 by = (h - 1) - ((int) ((h - 1) * cs->yBlue));
1385 } else {
1386 av_assert0(0);
1387 }
1388
1389 draw_rline(pixels, linesize, rx, ry, gx, gy, w, h);
1390 draw_rline(pixels, linesize, gx, gy, bx, by, w, h);
1391 draw_rline(pixels, linesize, bx, by, rx, ry, w, h);
1392 }
1393}
1394
1395static int filter_frame(AVFilterLink *inlink, AVFrame *in)
1396{
1397 AVFilterContext *ctx = inlink->dst;
1398 CiescopeContext *s = ctx->priv;
1399 AVFilterLink *outlink = ctx->outputs[0];
1400 int i = s->intensity * 65535;
1401 int w = outlink->w;
1402 int h = outlink->h;
1403 AVFrame *out;
1404 int ret, x, y;
1405
1406 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
1407 if (!out) {
1408 av_frame_free(&in);
1409 return AVERROR(ENOMEM);
1410 }
1411 out->pts = in->pts;
1412 out->duration = in->duration;
1413
1414 if (!s->background) {
1415 ret = draw_background(ctx);
1416 if (ret < 0) {
1418 return ret;
1419 }
1420 s->background = 1;
1421 }
1422 for (y = 0; y < outlink->h; y++) {
1423 memset(out->data[0] + y * out->linesize[0], 0, outlink->w * 8);
1424 }
1425
1426 for (y = 0; y < in->height; y++) {
1427 const uint8_t *src = in->data[0];
1428 const ptrdiff_t src_linesize = in->linesize[0];
1429 uint16_t *dst = (uint16_t *)out->data[0];
1430 const ptrdiff_t linesize = out->linesize[0] / 2;
1431 const int w_1 = w - 1;
1432 const int h_1 = h - 1;
1433
1434 for (x = 0; x < in->width; x++) {
1435 float cx, cy;
1436 int wx, wy, pos;
1437 int r, g, b;
1438
1439 s->filter(ctx, src, src_linesize, &cx, &cy, x, y);
1440
1441 if (s->cie == LUV) {
1442 float up, vp;
1443 xy_to_upvp(cx, cy, &up, &vp);
1444 cx = up;
1445 cy = vp;
1446 } else if (s->cie == UCS) {
1447 float u, v;
1448 xy_to_uv(cx, cy, &u, &v);
1449 cx = u;
1450 cy = v;
1451 }
1452
1453 wx = w_1 * cx;
1454 wy = h_1 - h_1 * cy;
1455
1456 if (wx < 0 || wx >= w ||
1457 wy < 0 || wy >= h)
1458 continue;
1459
1460 pos = wy * linesize + wx * 4;
1461 r = dst[pos + 0] + i;
1462 g = dst[pos + 1] + i;
1463 b = dst[pos + 2] + i;
1464
1465 dst[pos + 0] = FFMIN(r, 65535);
1466 dst[pos + 1] = FFMIN(g, 65535);
1467 dst[pos + 2] = FFMIN(b, 65535);
1468 dst[pos + 3] = 65535;
1469 }
1470 }
1471
1472 for (y = 0; y < outlink->h; y++) {
1473 uint16_t *dst = (uint16_t *)(out->data[0] + y * out->linesize[0]);
1474 const uint16_t *src = (const uint16_t *)(s->f->data[0] + y * s->f->linesize[0]);
1475 for (x = 0; x < outlink->w; x++) {
1476 const int xx = x * 4;
1477 if (dst[xx + 3] == 0) {
1478 dst[xx + 0] = src[xx + 0];
1479 dst[xx + 1] = src[xx + 1];
1480 dst[xx + 2] = src[xx + 2];
1481 dst[xx + 3] = src[xx + 3];
1482 }
1483 }
1484 }
1485
1486 if (s->show_white)
1487 plot_white_point((uint16_t *)out->data[0], out->linesize[0] / 2,
1488 outlink->w, outlink->h, 65535,
1489 s->color_system, s->cie);
1490
1491 plot_gamuts((uint16_t *)out->data[0], out->linesize[0] / 2,
1492 outlink->w, outlink->h,
1493 s->cie, s->gamuts);
1494
1495 av_frame_free(&in);
1496 return ff_filter_frame(outlink, out);
1497}
1498
1500{
1501 CiescopeContext *s = ctx->priv;
1502
1503 av_frame_free(&s->f);
1504}
1505
1506static int config_input(AVFilterLink *inlink)
1507{
1508 CiescopeContext *s = inlink->dst->priv;
1509 int i;
1510
1511 get_rgb2xyz_matrix(color_systems[s->color_system], s->m);
1512 invert_matrix3x3(s->m, s->i);
1513
1514 switch (inlink->format) {
1515 case AV_PIX_FMT_RGB24:
1516 s->filter = filter_rgb24;
1517 break;
1518 case AV_PIX_FMT_RGBA:
1519 s->filter = filter_rgba;
1520 break;
1521 case AV_PIX_FMT_RGB48:
1522 s->filter = filter_rgb48;
1523 break;
1524 case AV_PIX_FMT_RGBA64:
1525 s->filter = filter_rgba64;
1526 break;
1527 case AV_PIX_FMT_XYZ12:
1528 s->filter = filter_xyz;
1529 for (i = 0; i < 65536; i++)
1530 s->log2lin[i] = pow(i / 65535., s->igamma) * 65535.;
1531 break;
1532 default:
1533 av_assert0(0);
1534 }
1535
1536 return 0;
1537}
1538
1539static const AVFilterPad inputs[] = {
1540 {
1541 .name = "default",
1542 .type = AVMEDIA_TYPE_VIDEO,
1543 .filter_frame = filter_frame,
1544 .config_props = config_input,
1545 },
1546};
1547
1548static const AVFilterPad outputs[] = {
1549 {
1550 .name = "default",
1551 .type = AVMEDIA_TYPE_VIDEO,
1552 .config_props = config_output,
1553 },
1554};
1555
1557 .p.name = "ciescope",
1558 .p.description = NULL_IF_CONFIG_SMALL("Video CIE scope."),
1559 .p.priv_class = &ciescope_class,
1560 .priv_size = sizeof(CiescopeContext),
1561 .uninit = uninit,
1565};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t mx
Definition dsp.h:57
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition aeval.c:246
static const AVFilterPad inputs[]
Definition af_aap.c:299
static const AVFilterPad outputs[]
Definition af_aap.c:310
static int config_input(AVFilterLink *inlink)
const FFFilter ff_vf_ciescope
static FILE * out
static AVFormatContext * ctx
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
#define E
Definition avdct.c:34
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define FLAGS
Definition cmdutils.c:598
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition common.h:74
#define NULL
Definition coverity.c:32
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
Definition dolby_e.c:1067
#define X
Definition f_ebur128.c:157
#define S(s, c, i)
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add ref as a new reference to formats.
Definition formats.c:756
av_warn_unused_result AVFilterFormats * ff_make_pixel_format_list(const enum AVPixelFormat *fmts)
Create a list of supported pixel formats.
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
Definition opt.h:254
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_DOUBLE
Underlying C type is double.
Definition opt.h:266
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
Definition opt.h:270
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
#define AVERROR(e)
Definition error.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define r
Definition input.c:42
#define b
Definition input.c:43
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition intra.c:278
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int config_output(AVBitStreamFilterLink *outlink)
#define C
#define u(width, name, range_min, range_max)
Definition cbs_apv.c:68
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define FILTER_QUERY_FUNC2(func)
Definition filters.h:241
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
uint8_t w
Definition llvidencdsp.c:39
#define FFMAX3(a, b, c)
Definition macros.h:48
#define FFMIN(a, b)
Definition macros.h:49
AVOptions.
misc parsing utilities
#define AV_PIX_FMT_XYZ12
Definition pixfmt.h:605
#define AV_PIX_FMT_RGBA64
Definition pixfmt.h:535
#define AV_PIX_FMT_RGB48
Definition pixfmt.h:531
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition pixfmt.h:75
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition pixfmt.h:100
formats
Definition signature.h:47
unsigned int pos
Definition spdifenc.c:431
Describe the class of an AVClass context structure.
Definition log.h:76
An instance of a filter.
Definition avfilter.h:273
void * priv
private data for use by the filter
Definition avfilter.h:288
Lists of formats / etc.
Definition avfilter.h:120
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition frame.h:574
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int width
Definition frame.h:544
int height
Definition frame.h:544
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:517
int64_t duration
Duration of the frame, in the same units as pts.
Definition frame.h:820
AVOption.
Definition opt.h:428
Rational number (pair of numerator and denominator).
Definition rational.h:58
float log2lin[65536]
Definition vf_ciescope.c:66
float i[3][3]
Definition vf_ciescope.c:68
float m[3][3]
Definition vf_ciescope.c:69
void(* filter)(AVFilterContext *ctx, const uint8_t *ptr, ptrdiff_t linesize, float *cx, float *cy, int x, int y)
Definition vf_ciescope.c:71
unsigned gamuts
Definition vf_ciescope.c:56
#define src
Definition vp8dsp.c:248
int size
#define Z
Definition uops_tmpl.h:83
static void plot_white_point(uint16_t *pixels, int const linesize, int const w, int const h, int const maxval, int const color_system, int const cie)
static void av_cold uninit(AVFilterContext *ctx)
static void uv_to_xy(float const u, float const v, float *const xc, float *const yc)
#define Sz(x)
static int constrain_rgb(float *const r, float *const g, float *const b)
ColorsSystems
Definition vf_ciescope.c:39
@ NTSCsystem
Definition vf_ciescope.c:40
@ SMPTE240Msystem
Definition vf_ciescope.c:43
@ SMPTEsystem
Definition vf_ciescope.c:42
@ Rec709system
Definition vf_ciescope.c:47
@ DCIP3
Definition vf_ciescope.c:49
@ CIE1931system
Definition vf_ciescope.c:46
@ NB_CS
Definition vf_ciescope.c:50
@ wRGBsystem
Definition vf_ciescope.c:45
@ EBUsystem
Definition vf_ciescope.c:41
@ APPLEsystem
Definition vf_ciescope.c:44
@ Rec2020system
Definition vf_ciescope.c:48
#define D65
static void gamma_correct(const struct ColorSystem *const cs, float *const c)
#define GAMMA_REC709
static void tongue_outline(uint16_t *const pixels, int const linesize, int const w, int const h, uint16_t const maxval, int const cie)
static void invert_matrix3x3(float in[3][3], float out[3][3])
static void xyz_to_rgb(const float m[3][3], float xc, float yc, float zc, float *const r, float *const g, float *const b)
static void xy_to_uv(float xc, float yc, float *const u, float *const v)
static void filter_rgba64(AVFilterContext *ctx, const uint8_t *ptr, ptrdiff_t linesize, float *cx, float *cy, int x, int y)
static int config_input(AVFilterLink *inlink)
static enum AVPixelFormat in_pix_fmts[]
static void filter_rgb48(AVFilterContext *ctx, const uint8_t *ptr, ptrdiff_t linesize, float *cx, float *cy, int x, int y)
static const AVOption ciescope_options[]
Definition vf_ciescope.c:79
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
static void rgb_to_xy(float rc, float gc, float bc, float *const x, float *const y, float *const z, const float m[3][3])
static void draw_line(uint16_t *const pixels, int linesize, int x0, int y0, int x1, int y1, int w, int h, const uint16_t *const rgbcolor)
static const struct ColorSystem color_systems[]
static void draw_rline(uint16_t *const pixels, int linesize, int x0, int y0, int x1, int y1, int w, int h)
static void monochrome_color_location(float waveLength, int w, int h, int cie, int *xP, int *yP)
static void upvp_to_xy(float const up, float const vp, float *const xc, float *const yc)
static void xy_to_upvp(float xc, float yc, float *const up, float *const vp)
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
static void filter_rgba(AVFilterContext *ctx, const uint8_t *ptr, ptrdiff_t linesize, float *cx, float *cy, int x, int y)
static void fill_in_tongue(uint16_t *const pixels, int const linesize, int const w, int const h, uint16_t const maxval, const struct ColorSystem *const cs, float const m[3][3], int const cie, int const correct_gamma, float const contrast)
static void filter_xyz(AVFilterContext *ctx, const uint8_t *ptr, ptrdiff_t linesize, float *cx, float *cy, int x, int y)
static int draw_background(AVFilterContext *ctx)
static enum AVPixelFormat out_pix_fmts[]
static void gamma_correct_rgb(const struct ColorSystem *const cs, float *const r, float *const g, float *const b)
#define OFFSET(x)
Definition vf_ciescope.c:76
static void plot_gamuts(uint16_t *pixels, int linesize, int w, int h, int cie, int gamuts)
static int config_output(AVFilterLink *outlink)
CieSystem
Definition vf_ciescope.c:32
@ NB_CIE
Definition vf_ciescope.c:36
@ LUV
Definition vf_ciescope.c:35
@ XYY
Definition vf_ciescope.c:33
@ UCS
Definition vf_ciescope.c:34
static void filter_rgb24(AVFilterContext *ctx, const uint8_t *ptr, ptrdiff_t linesize, float *cx, float *cy, int x, int y)
#define D50
static void find_tongue(uint16_t *const pixels, int const w, int const linesize, int const row, int *const presentP, int *const leftEdgeP, int *const rightEdgeP)
static float const spectral_chromaticity[][3]
static void get_rgb2xyz_matrix(struct ColorSystem system, float m[3][3])
const char * g
Definition vf_curves.c:128
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition video.c:89
static double c[64]