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