FFmpeg
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"
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/opt.h"
25 #include "libavutil/parseutils.h"
26 #include "libavutil/pixdesc.h"
27 #include "avfilter.h"
28 #include "filters.h"
29 #include "formats.h"
30 #include "video.h"
31 
32 enum CieSystem {
33  XYY,
34  UCS,
35  LUV,
37 };
38 
51 };
52 
53 typedef 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 
79 static 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 
126 AVFILTER_DEFINE_CLASS(ciescope);
127 
128 static const enum AVPixelFormat in_pix_fmts[] = {
135 };
136 
137 static 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_format_list(in_pix_fmts), &cfg_in[0]->formats)) < 0)
149  return ret;
150 
151  if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &cfg_out[0]->formats)) < 0)
152  return ret;
153 
154  return 0;
155 }
156 
157 static 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 
171 struct ColorSystem {
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 
179 static 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 
669 static const struct ColorSystem color_systems[] = {
670  [NTSCsystem] = {
671  0.67, 0.33, 0.21, 0.71, 0.14, 0.08,
672  C, GAMMA_REC709
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,
696  E, GAMMA_REC709
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 /*
713 static 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 
720 static void
721 uv_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 
733 static void
734 upvp_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 
746 static void
747 xy_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 
760 static void
761 xy_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 
774 static void
775 xyz_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 
784 static 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 
811 static 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 
844 static void
845 rgb_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 
865 static int
866 constrain_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 
894 static void
895 gamma_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 
930 static void
931 gamma_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 
947 static void
948 monochrome_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 
978 static void
979 find_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 
1008 static 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 
1057 static 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 
1088 static void
1089 tongue_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 
1119 static void
1120 fill_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  co-ordinates 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 
1203 static void
1204 plot_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 
1268 static 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 
1283 static 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 
1298 static 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 
1313 static 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 
1328 static 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 
1345 static 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 
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) {
1417  av_frame_free(&out);
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 
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 
1539 static 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 
1548 static const AVFilterPad outputs[] = {
1549  {
1550  .name = "default",
1551  .type = AVMEDIA_TYPE_VIDEO,
1552  .config_props = config_output,
1553  },
1554 };
1555 
1557  .name = "ciescope",
1558  .description = NULL_IF_CONFIG_SMALL("Video CIE scope."),
1559  .priv_size = sizeof(CiescopeContext),
1560  .priv_class = &ciescope_class,
1561  .uninit = uninit,
1565 };
formats
formats
Definition: signature.h:47
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:116
XYY
@ XYY
Definition: vf_ciescope.c:33
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
ColorSystem::xGreen
float xGreen
Definition: vf_ciescope.c:173
uv_to_xy
static void uv_to_xy(float const u, float const v, float *const xc, float *const yc)
Definition: vf_ciescope.c:721
r
const char * r
Definition: vf_curves.c:127
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
CiescopeContext::fill
int fill
Definition: vf_ciescope.c:64
NB_CS
@ NB_CS
Definition: vf_ciescope.c:50
ff_make_format_list
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:435
out
FILE * out
Definition: movenc.c:55
CieSystem
CieSystem
Definition: vf_ciescope.c:32
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:251
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1062
AVFrame::duration
int64_t duration
Duration of the frame, in the same units as pts.
Definition: frame.h:795
ColorsSystems
ColorsSystems
Definition: vf_ciescope.c:39
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:162
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: filters.h:262
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
pixdesc.h
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:501
AVFrame::width
int width
Definition: frame.h:461
w
uint8_t w
Definition: llviddspenc.c:38
C
#define C
Definition: vf_ciescope.c:656
ColorSystem::yWhite
float yWhite
Definition: vf_ciescope.c:175
inputs
static const AVFilterPad inputs[]
Definition: vf_ciescope.c:1539
AVOption
AVOption.
Definition: opt.h:429
b
#define b
Definition: input.c:41
config_input
static int config_input(AVFilterLink *inlink)
Definition: vf_ciescope.c:1506
EBUsystem
@ EBUsystem
Definition: vf_ciescope.c:41
CiescopeContext::correct_gamma
int correct_gamma
Definition: vf_ciescope.c:59
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:205
xyz_to_rgb
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)
Definition: vf_ciescope.c:775
D65
#define D65
Definition: vf_ciescope.c:659
color_systems
static const struct ColorSystem color_systems[]
Definition: vf_ciescope.c:669
query_formats
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition: vf_ciescope.c:142
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_ciescope.c:1395
video.h
get_rgb2xyz_matrix
static void get_rgb2xyz_matrix(struct ColorSystem system, float m[3][3])
Definition: vf_ciescope.c:811
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:410
draw_rline
static void draw_rline(uint16_t *const pixels, int linesize, int x0, int y0, int x1, int y1, int w, int h)
Definition: vf_ciescope.c:1057
formats.h
S
#define S(s, c, i)
Definition: flacdsp_template.c:46
upvp_to_xy
static void upvp_to_xy(float const up, float const vp, float *const xc, float *const yc)
Definition: vf_ciescope.c:734
mx
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t mx
Definition: dsp.h:53
AVFilterContext::priv
void * priv
private data for use by the filter
Definition: avfilter.h:472
ColorSystem::xWhite
float xWhite
Definition: vf_ciescope.c:175
filter_rgba64
static void filter_rgba64(AVFilterContext *ctx, const uint8_t *ptr, ptrdiff_t linesize, float *cx, float *cy, int x, int y)
Definition: vf_ciescope.c:1283
CiescopeContext
Definition: vf_ciescope.c:53
FLAGS
#define FLAGS
Definition: vf_ciescope.c:77
ColorSystem
Definition: vf_ciescope.c:171
CiescopeContext::cie
int cie
Definition: vf_ciescope.c:60
monochrome_color_location
static void monochrome_color_location(float waveLength, int w, int h, int cie, int *xP, int *yP)
Definition: vf_ciescope.c:948
CiescopeContext::gamuts
unsigned gamuts
Definition: vf_ciescope.c:56
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:38
in_pix_fmts
static enum AVPixelFormat in_pix_fmts[]
Definition: vf_ciescope.c:128
avassert.h
invert_matrix3x3
static void invert_matrix3x3(float in[3][3], float out[3][3])
Definition: vf_ciescope.c:784
av_cold
#define av_cold
Definition: attributes.h:90
ColorSystem::xRed
float xRed
Definition: vf_ciescope.c:172
tongue_outline
static void tongue_outline(uint16_t *const pixels, int const linesize, int const w, int const h, uint16_t const maxval, int const cie)
Definition: vf_ciescope.c:1089
float
float
Definition: af_crystalizer.c:122
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
GAMMA_REC709
#define GAMMA_REC709
Definition: vf_ciescope.c:667
g
const char * g
Definition: vf_curves.c:128
AV_OPT_TYPE_DOUBLE
@ AV_OPT_TYPE_DOUBLE
Underlying C type is double.
Definition: opt.h:267
ff_formats_ref
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:678
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
filters.h
ctx
AVFormatContext * ctx
Definition: movenc.c:49
xy_to_uv
static void xy_to_uv(float xc, float yc, float *const u, float *const v)
Definition: vf_ciescope.c:761
plot_white_point
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)
Definition: vf_ciescope.c:1204
ColorSystem::yBlue
float yBlue
Definition: vf_ciescope.c:174
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: filters.h:263
filter_rgb48
static void filter_rgb48(AVFilterContext *ctx, const uint8_t *ptr, ptrdiff_t linesize, float *cx, float *cy, int x, int y)
Definition: vf_ciescope.c:1268
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:74
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:492
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
E
#define E
Definition: vf_ciescope.c:657
NULL
#define NULL
Definition: coverity.c:32
plot_gamuts
static void plot_gamuts(uint16_t *pixels, int linesize, int w, int h, int cie, int gamuts)
Definition: vf_ciescope.c:1345
ciescope_options
static const AVOption ciescope_options[]
Definition: vf_ciescope.c:79
gamma_correct_rgb
static void gamma_correct_rgb(const struct ColorSystem *const cs, float *const r, float *const g, float *const b)
Definition: vf_ciescope.c:931
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
system
FFmpeg currently uses a custom build system
Definition: build_system.txt:1
parseutils.h
draw_background
static int draw_background(AVFilterContext *ctx)
Definition: vf_ciescope.c:1246
wRGBsystem
@ wRGBsystem
Definition: vf_ciescope.c:45
D50
#define D50
Definition: vf_ciescope.c:658
CiescopeContext::size
int size
Definition: vf_ciescope.c:57
CiescopeContext::intensity
float intensity
Definition: vf_ciescope.c:61
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
AVFilterFormatsConfig
Lists of formats / etc.
Definition: avfilter.h:111
filter_xyz
static void filter_xyz(AVFilterContext *ctx, const uint8_t *ptr, ptrdiff_t linesize, float *cx, float *cy, int x, int y)
Definition: vf_ciescope.c:1328
draw_line
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)
Definition: vf_ciescope.c:1008
ColorSystem::xBlue
float xBlue
Definition: vf_ciescope.c:174
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:75
SMPTE240Msystem
@ SMPTE240Msystem
Definition: vf_ciescope.c:43
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:94
SMPTEsystem
@ SMPTEsystem
Definition: vf_ciescope.c:42
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
CiescopeContext::contrast
float contrast
Definition: vf_ciescope.c:62
CiescopeContext::m
float m[3][3]
Definition: vf_ciescope.c:69
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:488
size
int size
Definition: twinvq_data.h:10344
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(ciescope)
Rec709system
@ Rec709system
Definition: vf_ciescope.c:47
CiescopeContext::filter
void(* filter)(AVFilterContext *ctx, const uint8_t *ptr, ptrdiff_t linesize, float *cx, float *cy, int x, int y)
Definition: vf_ciescope.c:71
NTSCsystem
@ NTSCsystem
Definition: vf_ciescope.c:40
OFFSET
#define OFFSET(x)
Definition: vf_ciescope.c:76
find_tongue
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)
Definition: vf_ciescope.c:979
ColorSystem::gamma
float gamma
Definition: vf_ciescope.c:176
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
Definition: opt.h:271
CiescopeContext::f
AVFrame * f
Definition: vf_ciescope.c:70
AV_PIX_FMT_XYZ12
#define AV_PIX_FMT_XYZ12
Definition: pixfmt.h:549
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
CiescopeContext::log2lin
float log2lin[65536]
Definition: vf_ciescope.c:66
ff_vf_ciescope
const AVFilter ff_vf_ciescope
Definition: vf_ciescope.c:1556
out_pix_fmts
static enum AVPixelFormat out_pix_fmts[]
Definition: vf_ciescope.c:137
FILTER_QUERY_FUNC2
#define FILTER_QUERY_FUNC2(func)
Definition: filters.h:239
uninit
static void av_cold uninit(AVFilterContext *ctx)
Definition: vf_ciescope.c:1499
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
CiescopeContext::i
float i[3][3]
Definition: vf_ciescope.c:68
AVFilterPad::name
const char * name
Pad name.
Definition: filters.h:44
LUV
@ LUV
Definition: vf_ciescope.c:35
config_output
static int config_output(AVFilterLink *outlink)
Definition: vf_ciescope.c:157
AVFilter
Filter definition.
Definition: avfilter.h:201
ret
ret
Definition: filter_design.txt:187
filter_rgba
static void filter_rgba(AVFilterContext *ctx, const uint8_t *ptr, ptrdiff_t linesize, float *cx, float *cy, int x, int y)
Definition: vf_ciescope.c:1313
CiescopeContext::color_system
int color_system
Definition: vf_ciescope.c:55
rgb_to_xy
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])
Definition: vf_ciescope.c:845
pos
unsigned int pos
Definition: spdifenc.c:414
NB_CIE
@ NB_CIE
Definition: vf_ciescope.c:36
AVFrame::height
int height
Definition: frame.h:461
CiescopeContext::background
int background
Definition: vf_ciescope.c:63
DCIP3
@ DCIP3
Definition: vf_ciescope.c:49
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
avfilter.h
Sz
#define Sz(x)
Definition: vf_ciescope.c:945
xy_to_upvp
static void xy_to_upvp(float xc, float yc, float *const up, float *const vp)
Definition: vf_ciescope.c:747
APPLEsystem
@ APPLEsystem
Definition: vf_ciescope.c:44
AVFilterContext
An instance of a filter.
Definition: avfilter.h:457
X
@ X
Definition: vf_addroi.c:27
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
spectral_chromaticity
static const float spectral_chromaticity[][3]
Definition: vf_ciescope.c:179
CiescopeContext::igamma
float igamma
Definition: vf_ciescope.c:67
Rec2020system
@ Rec2020system
Definition: vf_ciescope.c:48
scale
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition: intra.c:291
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
filter_rgb24
static void filter_rgb24(AVFilterContext *ctx, const uint8_t *ptr, ptrdiff_t linesize, float *cx, float *cy, int x, int y)
Definition: vf_ciescope.c:1298
FFMAX3
#define FFMAX3(a, b, c)
Definition: macros.h:48
gamma_correct
static void gamma_correct(const struct ColorSystem *const cs, float *const c)
Definition: vf_ciescope.c:895
AV_OPT_TYPE_FLAGS
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
Definition: opt.h:255
AVFrame::linesize
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:434
h
h
Definition: vp9dsp_template.c:2070
ColorSystem::yGreen
float yGreen
Definition: vf_ciescope.c:173
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:299
constrain_rgb
static int constrain_rgb(float *const r, float *const g, float *const b)
Definition: vf_ciescope.c:866
CiescopeContext::show_white
int show_white
Definition: vf_ciescope.c:58
fill_in_tongue
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)
Definition: vf_ciescope.c:1120
ColorSystem::yRed
float yRed
Definition: vf_ciescope.c:172
src
#define src
Definition: vp8dsp.c:248
outputs
static const AVFilterPad outputs[]
Definition: vf_ciescope.c:1548
CIE1931system
@ CIE1931system
Definition: vf_ciescope.c:46
UCS
@ UCS
Definition: vf_ciescope.c:34