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