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