Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
colorchecker.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2020-2021 Aurélien PIERRE.
4 Copyright (C) 2021 Hubert Kowalski.
5 Copyright (C) 2021 Marco Carrarini.
6 Copyright (C) 2021 Ralf Brown.
7 Copyright (C) 2022 Martin Bařinka.
8 Copyright (C) 2023 Luca Zulberti.
9 Copyright (C) 2026 Guillaume Stutin.
10
11 darktable is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
15
16 darktable is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with darktable. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#include "darktable.h"
26
31// types of targets we support
43
44// helper to deal with patch color
46{
47 char *name; // mnemonic name for the patch
48 dt_aligned_pixel_t Lab; // reference color in CIE Lab
49
50 // (x, y) position of the patch center, relatively to the guides (white dots)
51 // in ratio of the grid dimension along that axis
52 struct
53 {
54 float x;
55 float y;
56 };
58
59typedef struct dt_color_checker_t
60{
61 char *name;
62 char *author;
63 char *date;
66
67 float ratio; // format ratio of the chart, guide to guide (white dots)
68 float radius; // radius of a patch in ratio of the checker diagonal
69 size_t patches; // number of patches in target
70 size_t size[2]; // dimension along x, y axes
71 size_t middle_grey; // index of the closest patch to 20% neutral grey
72 size_t white; // index of the closest patch to pure white
73 size_t black; // index of the closest patch to pure black
74 dt_color_checker_patch *values; // pointer to an array of colors
75 gboolean finished; // whether the color checker is loaded or not
77
79 { "A1", { 37.986, 13.555, 14.059 }, { 0.087, 0.125}},
80 { "A2", { 65.711, 18.13, 17.81 }, { 0.250, 0.125}},
81 { "A3", { 49.927, -04.88, -21.905 }, { 0.417, 0.125}},
82 { "A4", { 43.139, -13.095, 21.905 }, { 0.584, 0.125}},
83 { "A5", { 55.112, 08.844, -25.399 }, { 0.751, 0.125}},
84 { "A6", { 70.719, -33.397, -0.199 }, { 0.918, 0.125}},
85 { "B1", { 62.661, 36.067, 57.096 }, { 0.087, 0.375}},
86 { "B2", { 40.02, 10.41, -45.964 }, { 0.250, 0.375}},
87 { "B3", { 51.124, 48.239, 16.248 }, { 0.417, 0.375}},
88 { "B4", { 30.325, 22.976, -21.587 }, { 0.584, 0.375}},
89 { "B5", { 72.532, -23.709, 57.255 }, { 0.751, 0.375}},
90 { "B6", { 71.941, 19.363, 67.857 }, { 0.918, 0.375}},
91 { "C1", { 28.778, 14.179, -50.297 }, { 0.087, 0.625}},
92 { "C2", { 55.261, -38.342, 31.37 }, { 0.250, 0.625}},
93 { "C3", { 42.101, 53.378, 28.19 }, { 0.417, 0.625}},
94 { "C4", { 81.733, 04.039, 79.819 }, { 0.584, 0.625}},
95 { "C5", { 51.935, 49.986, -14.574 }, { 0.751, 0.625}},
96 { "C6", { 51.038, -28.631, -28.638 }, { 0.918, 0.625}},
97 { "D1", { 96.539, -0.425, 1.186 }, { 0.087, 0.875}},
98 { "D2", { 81.257, -0.638, -0.335 }, { 0.250, 0.875}},
99 { "D3", { 66.766, -0.734, -0.504 }, { 0.417, 0.875}},
100 { "D4", { 50.867, -0.153, -0.27 }, { 0.584, 0.875}},
101 { "D5", { 35.656, -0.421, -1.231 }, { 0.751, 0.875}},
102 { "D6", { 20.461, -0.079, -0.973 }, { 0.918, 0.875}} };
103
104dt_color_checker_t xrite_24_2000 = { .name = "Xrite ColorChecker 24 before 2014",
105 .author = "X-Rite",
106 .date = "3/27/2000",
107 .manufacturer = "X-Rite/Gretag Macbeth",
109 .ratio = 2.f / 3.f,
110 .radius = 0.055f,
111 .patches = 24,
112 .size = { 4, 6 },
113 .middle_grey = 21,
114 .white = 18,
115 .black = 23,
116 .values = xrite_24_2000_patches };
117
119 { "A1", { 37.54, 14.37, 14.92 }, { 0.087, 0.125}},
120 { "A2", { 64.66, 19.27, 17.50 }, { 0.250, 0.125}},
121 { "A3", { 49.32, -03.82, -22.54 }, { 0.417, 0.125}},
122 { "A4", { 43.46, -12.74, 22.72 }, { 0.584, 0.125}},
123 { "A5", { 54.94, 09.61, -24.79 }, { 0.751, 0.125}},
124 { "A6", { 70.48, -32.26, -00.37 }, { 0.918, 0.125}},
125 { "B1", { 62.73, 35.83, 56.50 }, { 0.087, 0.375}},
126 { "B2", { 39.43, 10.75, -45.17 }, { 0.250, 0.375}},
127 { "B3", { 50.57, 48.64, 16.67 }, { 0.417, 0.375}},
128 { "B4", { 30.10, 22.54, -20.87 }, { 0.584, 0.375}},
129 { "B5", { 71.77, -24.13, 58.19 }, { 0.751, 0.375}},
130 { "B6", { 71.51, 18.24, 67.37 }, { 0.918, 0.375}},
131 { "C1", { 28.37, 15.42, -49.80 }, { 0.087, 0.625}},
132 { "C2", { 54.38, -39.72, 32.27 }, { 0.250, 0.625}},
133 { "C3", { 42.43, 51.05, 28.62 }, { 0.417, 0.625}},
134 { "C4", { 81.80, 02.67, 80.41 }, { 0.584, 0.625}},
135 { "C5", { 50.63, 51.28, -14.12 }, { 0.751, 0.625}},
136 { "C6", { 49.57, -29.71, -28.32 }, { 0.918, 0.625}},
137 { "D1", { 95.19, -01.03, 02.93 }, { 0.087, 0.875}},
138 { "D2", { 81.29, -00.57, 00.44 }, { 0.250, 0.875}},
139 { "D3", { 66.89, -00.75, -00.06 }, { 0.417, 0.875}},
140 { "D4", { 50.76, -00.13, 00.14 }, { 0.584, 0.875}},
141 { "D5", { 35.63, -00.46, -00.48 }, { 0.751, 0.875}},
142 { "D6", { 20.64, 00.07, -00.46 }, { 0.918, 0.875}} };
143
144dt_color_checker_t xrite_24_2014 = { .name = "Xrite ColorChecker 24 after 2014",
145 .author = "X-Rite",
146 .date = "3/28/2015",
147 .manufacturer = "X-Rite/Gretag Macbeth",
149 .ratio = 2.f / 3.f,
150 .radius = 0.055f,
151 .patches = 24,
152 .size = { 4, 6 },
153 .middle_grey = 21,
154 .white = 18,
155 .black = 23,
156 .values = xrite_24_2014_patches };
157
158
159// dimensions between reference dots : 197 mm width x 135 mm height
160// patch width : 26x26 mm
161// outer gutter : 8 mm
162// internal gutters (gap between patches) : 5 mm
163
165 { "A1", { 96.04, 2.16, 2.60 }, { 0.107, 0.844 } },
166 { "A2", { 80.44, 1.17, 2.05 }, { 0.264, 0.844 } },
167 { "A3", { 65.52, 0.69, 1.86 }, { 0.421, 0.844 } },
168 { "A4", { 49.62, 0.58, 1.56 }, { 0.579, 0.844 } },
169 { "A5", { 33.55, 0.35, 1.40 }, { 0.736, 0.844 } },
170 { "A6", { 16.91, 1.43, -0.81 }, { 0.893, 0.844 } },
171 { "B1", { 47.12, -32.50, -28.75 }, { 0.107, 0.615 } },
172 { "B2", { 50.49, 53.45, -13.55 }, { 0.264, 0.615 } },
173 { "B3", { 83.61, 3.36, 87.02 }, { 0.421, 0.615 } },
174 { "B4", { 41.05, 60.75, 31.17 }, { 0.579, 0.615 } },
175 { "B5", { 54.14, -40.80, 34.75 }, { 0.736, 0.615 } },
176 { "B6", { 24.75, 13.78, -49.48 }, { 0.893, 0.615 } },
177 { "C1", { 60.94, 38.21, 61.31 }, { 0.107, 0.385 } },
178 { "C2", { 37.80, 7.30, -43.04 }, { 0.264, 0.385 } },
179 { "C3", { 49.81, 48.50, 15.76 }, { 0.421, 0.385 } },
180 { "C4", { 28.88, 19.36, -24.48 }, { 0.579, 0.385 } },
181 { "C5", { 72.45, -23.60, 60.47 }, { 0.736, 0.385 } },
182 { "C6", { 71.65, 23.74, 72.28 }, { 0.893, 0.385 } },
183 { "D1", { 70.19, -31.90, 1.98 }, { 0.107, 0.155 } },
184 { "D2", { 54.38, 8.84, -25.71 }, { 0.264, 0.155 } },
185 { "D3", { 42.03, -15.80, 22.93 }, { 0.421, 0.155 } },
186 { "D4", { 48.82, -5.11, -23.08 }, { 0.579, 0.155 } },
187 { "D5", { 65.10, 18.14, 18.68 }, { 0.736, 0.155 } },
188 { "D6", { 36.13, 14.15, 15.78 }, { 0.893, 0.155 } } };
189
190dt_color_checker_t spyder_24 = { .name = "Datacolor SpyderCheckr 24 before 2018",
191 .author = "Aur\303\251lien PIERRE",
192 .date = "dec, 9 2016",
193 .manufacturer = "DataColor",
195 .ratio = 2.f / 3.f,
196 .radius = 0.035,
197 .patches = 24,
198 .size = { 4, 6 },
199 .middle_grey = 03,
200 .white = 00,
201 .black = 05,
202 .values = spyder_24_patches };
203
204
205// dimensions between reference dots : 197 mm width x 135 mm height
206// patch width : 26x26 mm
207// outer gutter : 8 mm
208// internal gutters (gap between patches) : 5 mm
209
210dt_color_checker_patch spyder_24_v2_patch[] = {{ "A1", { 96.04, 2.16, 2.60 }, { 0.107, 0.844 } },
211 { "A2", { 80.44, 1.17, 2.05 }, { 0.264, 0.844 } },
212 { "A3", { 65.52, 0.69, 1.86 }, { 0.421, 0.844 } },
213 { "A4", { 49.62, 0.58, 1.56 }, { 0.579, 0.844 } },
214 { "A5", { 33.55, 0.35, 1.40 }, { 0.736, 0.844 } },
215 { "A6", { 16.91, 1.43, -0.81 }, { 0.893, 0.844 } },
216 { "B1", { 47.12, -32.50, -28.75 }, { 0.107, 0.615 } },
217 { "B2", { 50.49, 53.45, -13.55 }, { 0.264, 0.615 } },
218 { "B3", { 83.61, 3.36, 87.02 }, { 0.421, 0.615 } },
219 { "B4", { 41.05, 60.75, 31.17 }, { 0.579, 0.615 } },
220 { "B5", { 54.14, -40.80, 34.75 }, { 0.736, 0.615 } },
221 { "B6", { 24.75, 13.78, -49.48 }, { 0.893, 0.615 } },
222 { "C1", { 60.94, 38.21, 61.31 }, { 0.107, 0.385 } },
223 { "C2", { 37.80, 7.30, -43.04 }, { 0.264, 0.385 } },
224 { "C3", { 49.81, 48.50, 15.76 }, { 0.421, 0.385 } },
225 { "C4", { 28.88, 19.36, -24.48 }, { 0.579, 0.385 } },
226 { "C5", { 72.45, -23.57, 60.47 }, { 0.736, 0.385 } },
227 { "C6", { 71.65, 23.74, 72.28 }, { 0.893, 0.385 } },
228 { "D1", { 70.19, -31.85, 1.98 }, { 0.107, 0.155 } },
229 { "D2", { 54.38, 8.84, -25.71 }, { 0.264, 0.155 } },
230 { "D3", { 42.03, -15.78, 22.93 }, { 0.421, 0.155 } },
231 { "D4", { 48.82, -5.11, -23.08 }, { 0.579, 0.155 } },
232 { "D5", { 65.10, 18.14, 18.68 }, { 0.736, 0.155 } },
233 { "D6", { 36.13, 14.15, 15.78 }, { 0.893, 0.155 } } };
234
235dt_color_checker_t spyder_24_v2 = { .name = "Datacolor SpyderCheckr 24 after 2018",
236 .author = "Aur\303\251lien PIERRE",
237 .date = "dec, 9 2016",
238 .manufacturer = "DataColor",
240 .ratio = 2.f / 3.f,
241 .radius = 0.035,
242 .patches = 24,
243 .size = { 4, 6 },
244 .middle_grey = 03,
245 .white = 00,
246 .black = 05,
247 .values = spyder_24_v2_patch };
248
249
250// dimensions between reference dots : 297 mm width x 197 mm height
251// patch width : 26x26 mm
252// outer gutter : 8 mm
253// internal gutters (gap between patches) : 5 mm
254
255dt_color_checker_patch spyder_48_patches[] = { { "A1", { 61.35, 34.81, 18.38 }, { 0.071, 0.107 } },
256 { "A2", { 75.50 , 5.84, 50.42 }, { 0.071, 0.264 } },
257 { "A3", { 66.82, -25.1, 23.47 }, { 0.071, 0.421 } },
258 { "A4", { 60.53, -22.6, -20.40 }, { 0.071, 0.579 } },
259 { "A5", { 59.66, -2.03, -28.46 }, { 0.071, 0.736 } },
260 { "A6", { 59.15, 30.83, -5.72 }, { 0.071, 0.893 } },
261 { "B1", { 82.68, 5.03, 3.02 }, { 0.175, 0.107 } },
262 { "B2", { 82.25, -2.42, 3.78 }, { 0.175, 0.264 } },
263 { "B3", { 82.29, 2.20, -2.04 }, { 0.175, 0.421 } },
264 { "B4", { 24.89, 4.43, 0.78 }, { 0.175, 0.579 } },
265 { "B5", { 25.16, -3.88, 2.13 }, { 0.175, 0.736 } },
266 { "B6", { 26.13, 2.61, -5.03 }, { 0.175, 0.893 } },
267 { "C1", { 85.42, 9.41, 14.49 }, { 0.279, 0.107 } },
268 { "C2", { 74.28, 9.05, 27.21 }, { 0.279, 0.264 } },
269 { "C3", { 64.57, 12.39, 37.24 }, { 0.279, 0.421 } },
270 { "C4", { 44.49, 17.23, 26.24 }, { 0.279, 0.579 } },
271 { "C5", { 25.29, 7.95, 8.87 }, { 0.279, 0.736 } },
272 { "C6", { 22.67, 2.11, -1.10 }, { 0.279, 0.893 } },
273 { "D1", { 92.72, 1.89, 2.76 }, { 0.384, 0.107 } },
274 { "D2", { 88.85, 1.59, 2.27 }, { 0.384, 0.264 } },
275 { "D3", { 73.42, 0.99, 1.89 }, { 0.384, 0.421 } },
276 { "D4", { 57.15, 0.57, 1.19 }, { 0.384, 0.579 } },
277 { "D5", { 41.57, 0.24, 1.45 }, { 0.384, 0.736 } },
278 { "D6", { 25.65, 1.24, 0.05 }, { 0.384, 0.893 } },
279 { "E1", { 96.04, 2.16, 2.60 }, { 0.616, 0.107 } },
280 { "E2", { 80.44, 1.17, 2.05 }, { 0.616, 0.264 } },
281 { "E3", { 65.52, 0.69, 1.86 }, { 0.616, 0.421 } },
282 { "E4", { 49.62, 0.58, 1.56 }, { 0.616, 0.579 } },
283 { "E5", { 33.55, 0.35, 1.40 }, { 0.616, 0.736 } },
284 { "E6", { 16.91, 1.43, -0.81 }, { 0.616, 0.893 } },
285 { "F1", { 47.12, -32.50, -28.75 }, { 0.721, 0.107 } },
286 { "F2", { 50.49, 53.45, -13.55 }, { 0.721, 0.264 } },
287 { "F3", { 83.61, 3.36, 87.02 }, { 0.721, 0.421 } },
288 { "F4", { 41.05, 60.75, 31.17 }, { 0.721, 0.579 } },
289 { "F5", { 54.14, -40.80, 34.75 }, { 0.721, 0.736 } },
290 { "F6", { 24.75, 13.78, -49.48 }, { 0.721, 0.893 } },
291 { "G1", { 60.94, 38.21, 61.31 }, { 0.825, 0.107 } },
292 { "G2", { 37.80, 7.30, -43.04 }, { 0.825, 0.264 } },
293 { "G3", { 49.81, 48.50, 15.76 }, { 0.825, 0.421 } },
294 { "G4", { 28.88, 19.36, -24.48 }, { 0.825, 0.579 } },
295 { "G5", { 72.45, -23.60, 60.47 }, { 0.825, 0.736 } },
296 { "G6", { 71.65, 23.74, 72.28 }, { 0.825, 0.893 } },
297 { "H1", { 70.19, -31.90, 1.98 }, { 0.929, 0.107 } },
298 { "H2", { 54.38, 8.84, -25.71 }, { 0.929, 0.264 } },
299 { "H3", { 42.03, -15.80, 22.93 }, { 0.929, 0.421 } },
300 { "H4", { 48.82, -5.11, -23.08 }, { 0.929, 0.579 } },
301 { "H5", { 65.10, 18.14, 18.68 }, { 0.929, 0.736 } },
302 { "H6", { 36.13, 14.15, 15.78 }, { 0.929, 0.893 } } };
303
304dt_color_checker_t spyder_48 = { .name = "Datacolor SpyderCheckr 48 before 2018",
305 .author = "Aur\303\251lien PIERRE",
306 .date = "dec, 9 2016",
307 .manufacturer = "DataColor",
309 .ratio = 2.f / 3.f,
310 .radius = 0.035,
311 .patches = 48,
312 .size = { 8, 6 },
313 .middle_grey = 27,
314 .white = 24,
315 .black = 29,
316 .values = spyder_48_patches };
317
318
319// dimensions between reference dots : 297 mm width x 197 mm height
320// patch width : 26x26 mm
321// outer gutter : 8 mm
322// internal gutters (gap between patches) : 5 mm
323
324dt_color_checker_patch spyder_48_v2_patch[] = { { "A1", { 61.35, 34.81, 18.38 }, { 0.071, 0.107 } },
325 { "A2", { 75.50 , 5.84, 50.42 }, { 0.071, 0.264 } },
326 { "A3", { 66.82, -25.1, 23.47 }, { 0.071, 0.421 } },
327 { "A4", { 60.53, -22.62, -20.40 }, { 0.071, 0.579 } },
328 { "A5", { 59.66, -2.03, -28.46 }, { 0.071, 0.736 } },
329 { "A6", { 59.15, 30.83, -5.72 }, { 0.071, 0.893 } },
330 { "B1", { 82.68, 5.03, 3.02 }, { 0.175, 0.107 } },
331 { "B2", { 82.25, -2.42, 3.78 }, { 0.175, 0.264 } },
332 { "B3", { 82.29, 2.20, -2.04 }, { 0.175, 0.421 } },
333 { "B4", { 24.89, 4.43, 0.78 }, { 0.175, 0.579 } },
334 { "B5", { 25.16, -3.88, 2.13 }, { 0.175, 0.736 } },
335 { "B6", { 26.13, 2.61, -5.03 }, { 0.175, 0.893 } },
336 { "C1", { 85.42, 9.41, 14.49 }, { 0.279, 0.107 } },
337 { "C2", { 74.28, 9.05, 27.21 }, { 0.279, 0.264 } },
338 { "C3", { 64.57, 12.39, 37.24 }, { 0.279, 0.421 } },
339 { "C4", { 44.49, 17.23, 26.24 }, { 0.279, 0.579 } },
340 { "C5", { 25.29, 7.95, 8.87 }, { 0.279, 0.736 } },
341 { "C6", { 22.67, 2.11, -1.10 }, { 0.279, 0.893 } },
342 { "D1", { 92.72, 1.89, 2.76 }, { 0.384, 0.107 } },
343 { "D2", { 88.85, 1.59, 2.27 }, { 0.384, 0.264 } },
344 { "D3", { 73.42, 0.99, 1.89 }, { 0.384, 0.421 } },
345 { "D4", { 57.15, 0.57, 1.19 }, { 0.384, 0.579 } },
346 { "D5", { 41.57, 0.24, 1.45 }, { 0.384, 0.736 } },
347 { "D6", { 25.65, 1.24, 0.05 }, { 0.384, 0.893 } },
348 { "E1", { 96.04, 2.16, 2.60 }, { 0.616, 0.107 } },
349 { "E2", { 80.44, 1.17, 2.05 }, { 0.616, 0.264 } },
350 { "E3", { 65.52, 0.69, 1.86 }, { 0.616, 0.421 } },
351 { "E4", { 49.62, 0.58, 1.56 }, { 0.616, 0.579 } },
352 { "E5", { 33.55, 0.35, 1.40 }, { 0.616, 0.736 } },
353 { "E6", { 16.91, 1.43, -0.81 }, { 0.616, 0.893 } },
354 { "F1", { 47.12, -32.50, -28.75 }, { 0.721, 0.107 } },
355 { "F2", { 50.49, 53.45, -13.55 }, { 0.721, 0.264 } },
356 { "F3", { 83.61, 3.36, 87.02 }, { 0.721, 0.421 } },
357 { "F4", { 41.05, 60.75, 31.17 }, { 0.721, 0.579 } },
358 { "F5", { 54.14, -40.80, 34.75 }, { 0.721, 0.736 } },
359 { "F6", { 24.75, 13.78, -49.48 }, { 0.721, 0.893 } },
360 { "G1", { 60.94, 38.21, 61.31 }, { 0.825, 0.107 } },
361 { "G2", { 37.80, 7.30, -43.04 }, { 0.825, 0.264 } },
362 { "G3", { 49.81, 48.50, 15.76 }, { 0.825, 0.421 } },
363 { "G4", { 28.88, 19.36, -24.48 }, { 0.825, 0.579 } },
364 { "G5", { 72.45, -23.57, 60.47 }, { 0.825, 0.736 } },
365 { "G6", { 71.65, 23.74, 72.28 }, { 0.825, 0.893 } },
366 { "H1", { 70.19, -31.85, 1.98 }, { 0.929, 0.107 } },
367 { "H2", { 54.38, 8.84, -25.71 }, { 0.929, 0.264 } },
368 { "H3", { 42.03, -15.78, 22.93 }, { 0.929, 0.421 } },
369 { "H4", { 48.82, -5.11, -23.08 }, { 0.929, 0.579 } },
370 { "H5", { 65.10, 18.14, 18.68 }, { 0.929, 0.736 } },
371 { "H6", { 36.13, 14.15, 15.78 }, { 0.929, 0.893 } } };
372
373dt_color_checker_t spyder_48_v2 = { .name = "Datacolor SpyderCheckr 48 after 2018",
374 .author = "Aur\303\251lien PIERRE",
375 .date = "dec, 9 2016",
376 .manufacturer = "DataColor",
378 .ratio = 2.f / 3.f,
379 .radius = 0.035,
380 .patches = 48,
381 .size = { 8, 6 },
382 .middle_grey = 27,
383 .white = 24,
384 .black = 29,
385 .values = spyder_48_v2_patch };
386
394
395// Add other supported type of CGATS here
404
406 "IT8.7/1", // transparent
407 "IT8.7/2", // opaque
408 "CTI3" // opaque
409};
410
417
419 "Transparent",
420 "Opaque"
421};
422
429
430// This defines charts specifications
432{
433 const gchar *type;
434 float radius; // radius of a patch in ratio of the checker diagonal
435 float ratio; // format ratio of the chart, guide to guide (white dots)
436 size_t size[2]; // number of patch along x, y axes
437 float guide_size[2];// size of the guide area, specified by "MARK" data in cht files
439 size_t white;
440 size_t black;
441
442 int num_patches; // total number of patches
444 int rows;
449
450 GSList *patches; // list of patches struct, data are dt_color_checker_patch
451
453
454dt_colorchecker_label_t *dt_colorchecker_label_init(const char *label, const dt_color_checker_targets type, const char *path, const int patch_nb)
455{
456 dt_colorchecker_label_t *checker_label = malloc(sizeof(dt_colorchecker_label_t));
457 if(!checker_label) return NULL;
458
459 checker_label->name = label ? g_strdup(label) : NULL;
460 checker_label->type = type;
461 checker_label->path = path ? g_strdup(path) : NULL;
462 checker_label->patch_nb = patch_nb;
463
464 return checker_label;
465}
466
468{
470 if(!patches) return NULL;
471
472 // Initialize the patches
473 for(size_t i = 0; i < num_patches; i++)
474 {
475 patches[i].name = NULL;
476 patches[i].x = 0.0f;
477 patches[i].y = 0.0f;
478 patches[i].Lab[0] = 0.0f;
479 patches[i].Lab[1] = 0.0f;
480 patches[i].Lab[2] = 0.0f;
481 }
482 return patches;
483}
484
486{
487 if(!patch) return;
488 if(!patch->name) return;
489
490 dt_free(patch->name);
491}
492
493// This one is to fully free GSList of dt_color_checker_patch
495{
497 if(!patch) return;
498
499 // Free the name if it was allocated
500 dt_free(patch->name);
501
502 dt_free(patch);
503}
504
506{
507 dt_color_checker_t *checker = (dt_color_checker_t*)malloc(sizeof(dt_color_checker_t));
508 if(!checker) return NULL;
509
510 checker->name = NULL;
511 checker->author = NULL;
512 checker->date = NULL;
513 checker->manufacturer = NULL;
514 checker->values = NULL;
515 checker->finished = FALSE;
516
517 return checker;
518}
519
521{
522 if (!checker) return;
523
524 dt_free(checker->name);
525 dt_free(checker->author);
526 dt_free(checker->date);
527 dt_free(checker->manufacturer);
528
529 if(checker->patches > 0 && checker->values)
530 {
531 for(size_t i = 0; i < checker->patches; i++)
532 {
534 }
535
536 dt_free_align(checker->values);
537 }
538 free(checker);
539 checker = NULL;
540}
541
542void dt_colorchecker_label_free(gpointer data)
543{
544 dt_colorchecker_label_t *checker_label = (dt_colorchecker_label_t *)data;
545 if(!checker_label) return;
546
547 dt_free(checker_label->name);
548 dt_free(checker_label->path);
549 dt_free(checker_label);
550}
551
552void dt_colorchecker_label_list_cleanup(GList **colorcheckers)
553{
554 if(!colorcheckers) return;
555
556 g_list_free_full(g_steal_pointer(colorcheckers), dt_colorchecker_label_free);
557 *colorcheckers = NULL;
558}
559
567dt_color_checker_t *dt_colorchecker_user_ref_create(const char *color_filename, const char *cht_filename);
568
575int dt_colorchecker_find_cht_files(GList **chts);
576
583int dt_colorchecker_find_CGATS_reference_files(GList **ref_colorcheckers_files);
584
591int dt_colorchecker_find_builtin(GList **colorcheckers_label);
592
600
601
602static dt_color_checker_t *dt_get_color_checker(const dt_color_checker_targets target_type, GList **colorchecker_label, const char *color_filename)
603{
604 // initialize the destination checker
605 dt_color_checker_t *checker_dest = NULL;
606 checker_dest = dt_colorchecker_init();
607 if(!checker_dest) return NULL;
608
609 // check if the target type is a user reference and get the label data if available
611 const char *cht_filename = NULL;
612 if(target_type >= COLOR_CHECKER_USER_REF && colorchecker_label)
613 {
614 dt_print(DT_DEBUG_VERBOSE, _("dt_get_color_checker: colorchecker type %i is a user reference.\n"), target_type);
615
616 // Get the label data from the list
617 const dt_colorchecker_label_t *label_data = (const dt_colorchecker_label_t*)g_list_nth_data(*colorchecker_label, target_type);
618 checker_type = COLOR_CHECKER_USER_REF;
619 cht_filename = label_data->path;
620 }
621 else // it's a builtin colorchecker
622 checker_type = target_type;
623
624 // Copy the color checker data from the predefined checkers or from reference file
625 switch(checker_type)
626 {
628 dt_colorchecker_copy(checker_dest, &xrite_24_2000);
629 break;
631 dt_colorchecker_copy(checker_dest, &xrite_24_2014);
632 break;
634 dt_colorchecker_copy(checker_dest, &spyder_24);
635 break;
637 dt_colorchecker_copy(checker_dest, &spyder_24_v2);
638 break;
640 dt_colorchecker_copy(checker_dest, &spyder_48);
641 break;
643 dt_colorchecker_copy(checker_dest, &spyder_48_v2);
644 break;
646 if(color_filename)
647 {
648 dt_color_checker_t *p = dt_colorchecker_user_ref_create(color_filename, cht_filename);
649 if(p)
650 {
651 dt_colorchecker_copy(checker_dest, p);
653 }
654 }
655 else fprintf(stderr, "dt_get_color_checker: colorchecker %i is a user reference but no color filename was provided!\n", target_type);
656 break;
657
659 fprintf(stderr, "dt_get_color_checker: colorchecker type %i not found!\n", target_type);
660 dt_colorchecker_copy(checker_dest, &xrite_24_2014);
661 }
662
663 return checker_dest;
664}
665
670// get a patch index in the list of values from the coordinates of the patch in the checker array
671static inline size_t dt_color_checker_get_index(const dt_color_checker_t *const target_checker, const size_t coordinates[2])
672{
673 // patches are stored column-major
674 const size_t height = target_checker->size[1];
675 return CLAMP(height * coordinates[0] + coordinates[1], 0, target_checker->patches - 1);
676}
677
678// get a a patch coordinates of in the checker array from the patch index in the list of values
679static inline void dt_color_checker_get_coordinates(const dt_color_checker_t *const target_checker, size_t *coordinates, const size_t index)
680{
681 // patches are stored column-major
682 const size_t idx = CLAMP(index, 0, target_checker->patches - 1);
683 const size_t height = target_checker->size[1];
684 const size_t num_col = idx / height;
685 const size_t num_lin = idx - num_col * height;
686 coordinates[0] = CLAMP(num_col, 0, target_checker->size[0] - 1);
687 coordinates[1] = CLAMP(num_lin, 0, target_checker->size[1] - 1);
688}
689
690// find a patch matching a name
691static inline const dt_color_checker_patch *dt_color_checker_get_patch_by_name(const dt_color_checker_t *const target_checker, const char *name, size_t *index)
692{
693 size_t idx = -1;
694 const dt_color_checker_patch *patch = NULL;
695
696 for(size_t k = 0; k < target_checker->patches; k++)
697 if(strcmp(name, target_checker->values[k].name) == 0)
698 {
699 idx = k;
700 patch = &target_checker->values[k];
701 break;
702 }
703
704 if(IS_NULL_PTR(patch)) fprintf(stderr, "No patch matching name `%s` was found in %s\n", name, target_checker->name);
705
706 if(index) *index = idx;
707 return patch;
708}
709
716int dt_colorchecker_find(GList **colorcheckers_label)
717{
718 int total = dt_colorchecker_find_builtin(colorcheckers_label);
719 dt_print(DT_DEBUG_VERBOSE, _("dt_colorchecker_find: found %d builtin colorcheckers\n"), total);
720 int b_nb = total;
721
722 total += dt_colorchecker_find_cht_files(colorcheckers_label);
723 if (total) dt_print(DT_DEBUG_VERBOSE, _("dt_colorchecker_find: found %d CGAT references files\n"), total - b_nb);
724 return total;
725}
726
733int dt_colorchecker_find_color(GList **color_label)
734{
735 if(!color_label) return 0;
736
737 // Clear cht file list
739
740 // Refill the list
741 const int total = dt_colorchecker_find_CGATS_reference_files(color_label);
742 if(total) dt_print(DT_DEBUG_VERBOSE, _("dt_colorchecker_find_color: found %d .cht files\n"), total);
743
744 if(*color_label == NULL)
745 fprintf(stderr, "[channelmixerrgb] no CGATS file found\n");
746
747 return *color_label ? total : 0;
748}
749
750// clang-format off
751// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
752// vim: shiftwidth=2 expandtab tabstop=2 cindent
753// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
754// clang-format on
#define FALSE
Definition ashift_lsd.c:158
int height
Definition bilateral.h:1
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
int dt_colorchecker_find_CGATS_reference_files(GList **ref_colorcheckers_files)
Find all CGAT files in the user config/color/it8 directory.
dt_color_checker_patch spyder_48_v2_patch[]
dt_color_checker_targets
@ COLOR_CHECKER_SPYDER_48
@ COLOR_CHECKER_XRITE_24_2000
@ COLOR_CHECKER_XRITE_24_2014
@ COLOR_CHECKER_LAST
@ COLOR_CHECKER_SPYDER_24_V2
@ COLOR_CHECKER_SPYDER_24
@ COLOR_CHECKER_USER_REF
@ COLOR_CHECKER_SPYDER_48_V2
dt_color_checker_patch spyder_24_patches[]
dt_color_checker_patch xrite_24_2014_patches[]
dt_colorchecker_material_types
@ COLOR_CHECKER_MATERIAL_TRANSPARENT
@ COLOR_CHECKER_MATERIAL_UNKNOWN
@ COLOR_CHECKER_MATERIAL_OPAQUE
dt_color_checker_t * dt_colorchecker_init()
int dt_colorchecker_find_cht_files(GList **chts)
Find all .cht files in the user config/color/it8 directory.
static size_t dt_color_checker_get_index(const dt_color_checker_t *const target_checker, const size_t coordinates[2])
dt_colorchecker_CGATS_types
@ CGATS_TYPE_IT8_7_1
@ CGATS_TYPE_UNKOWN
@ CGATS_TYPE_IT8_7_2
@ CGATS_TYPE_CTI3
dt_color_checker_t spyder_24
static const dt_color_checker_patch * dt_color_checker_get_patch_by_name(const dt_color_checker_t *const target_checker, const char *name, size_t *index)
void dt_colorchecker_patch_cleanup_list(void *_patch)
dt_color_checker_t spyder_48
void dt_colorchecker_patch_cleanup(dt_color_checker_patch *patch)
void dt_colorchecker_copy(dt_color_checker_t *dest, const dt_color_checker_t *src)
Copy the content of a color checker from source to destination.
const char * colorchecker_material_types[COLOR_CHECKER_MATERIAL_UNKNOWN]
dt_color_checker_t * dt_colorchecker_user_ref_create(const char *color_filename, const char *cht_filename)
Creates a color checker from a reference file (CGATS format).
void dt_colorchecker_label_free(gpointer data)
dt_color_checker_patch spyder_48_patches[]
dt_color_checker_t spyder_48_v2
dt_colorchecker_label_t * dt_colorchecker_label_init(const char *label, const dt_color_checker_targets type, const char *path, const int patch_nb)
void dt_colorchecker_label_list_cleanup(GList **colorcheckers)
dt_color_checker_t spyder_24_v2
static void dt_color_checker_get_coordinates(const dt_color_checker_t *const target_checker, size_t *coordinates, const size_t index)
dt_color_checker_t xrite_24_2014
dt_color_checker_patch spyder_24_v2_patch[]
dt_color_checker_patch * dt_colorchecker_patch_array_init(const size_t num_patches)
int dt_colorchecker_find_builtin(GList **colorcheckers_label)
Find all builtin colorcheckers.
static dt_color_checker_t * dt_get_color_checker(const dt_color_checker_targets target_type, GList **colorchecker_label, const char *color_filename)
dt_color_checker_t xrite_24_2000
dt_color_checker_patch xrite_24_2000_patches[]
int dt_colorchecker_find(GList **colorcheckers_label)
Find all builtin and .cht colorcheckers.
void dt_colorchecker_cleanup(dt_color_checker_t *checker)
int dt_colorchecker_find_color(GList **color_label)
Find all builtin and CGATS colorcheckers.
const char * CGATS_types[CGATS_TYPE_UNKOWN]
int type
char * name
void * dt_alloc_align(size_t size)
Definition darktable.c:484
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1600
#define dt_free_align(ptr)
Definition darktable.h:503
@ DT_DEBUG_VERBOSE
Definition darktable.h:765
#define dt_free(ptr)
Definition darktable.h:478
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:293
float *const restrict const size_t k
float dt_aligned_pixel_t[4]
dt_aligned_pixel_t Lab
dt_color_checker_targets type
dt_color_checker_patch * values
dt_color_checker_targets type