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