Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
chromatic_adaptation.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2020 darktable developers.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#pragma once
20
21#include "common/math.h"
23
24typedef enum dt_adaptation_t
25{
26 DT_ADAPTATION_LINEAR_BRADFORD = 0, // $DESCRIPTION: "linear Bradford (ICC v4)"
27 DT_ADAPTATION_CAT16 = 1, // $DESCRIPTION: "CAT16 (CIECAM16)"
28 DT_ADAPTATION_FULL_BRADFORD = 2, // $DESCRIPTION: "non-linear Bradford"
29 DT_ADAPTATION_XYZ = 3, // $DESCRIPTION: "XYZ"
30 DT_ADAPTATION_RGB = 4, // $DESCRIPTION: "none (bypass)"
33
34
35// modified LMS cone response space for Bradford transform
36// explanation here : https://onlinelibrary.wiley.com/doi/pdf/10.1002/9781119021780.app3
37// but coeffs are wrong in the above, so they come from :
38// http://www2.cmp.uea.ac.uk/Research/compvis/Papers/FinSuss_COL00.pdf
39// At any time, ensure XYZ_to_LMS is the exact matrice inverse of LMS_to_XYZ
40const dt_colormatrix_t XYZ_to_Bradford_LMS = { { 0.8951f, 0.2664f, -0.1614f, 0.f },
41 { -0.7502f, 1.7135f, 0.0367f, 0.f },
42 { 0.0389f, -0.0685f, 1.0296f, 0.f } };
43
44const dt_colormatrix_t Bradford_LMS_to_XYZ = { { 0.9870f, -0.1471f, 0.1600f, 0.f },
45 { 0.4323f, 0.5184f, 0.0493f, 0.f },
46 { -0.0085f, 0.0400f, 0.9685f, 0.f } };
47
48#ifdef _OPENMP
49#pragma omp declare simd aligned(XYZ, LMS:16)
50#endif
51static inline void convert_XYZ_to_bradford_LMS(const dt_aligned_pixel_t XYZ, dt_aligned_pixel_t LMS)
52{
53 // Warning : needs XYZ normalized with Y - you need to downscale before
55}
56
57#ifdef _OPENMP
58#pragma omp declare simd aligned(XYZ, LMS:16)
59#endif
60static inline void convert_bradford_LMS_to_XYZ(const dt_aligned_pixel_t LMS, dt_aligned_pixel_t XYZ)
61{
62 // Warning : output XYZ normalized with Y - you need to upscale later
64}
65
66
67// modified LMS cone response for CAT16, from CIECAM16
68// reference : https://ntnuopen.ntnu.no/ntnu-xmlui/bitstream/handle/11250/2626317/CCIW-23.pdf?sequence=1
69// At any time, ensure XYZ_to_LMS is the exact matrice inverse of LMS_to_XYZ
70const dt_colormatrix_t XYZ_to_CAT16_LMS = { { 0.401288f, 0.650173f, -0.051461f, 0.f },
71 { -0.250268f, 1.204414f, 0.045854f, 0.f },
72 { -0.002079f, 0.048952f, 0.953127f, 0.f } };
73
74const dt_colormatrix_t CAT16_LMS_to_XYZ = { { 1.862068f, -1.011255f, 0.149187f, 0.f },
75 { 0.38752f , 0.621447f, -0.008974f, 0.f },
76 { -0.015841f, -0.034123f, 1.049964f, 0.f } };
77
78#ifdef _OPENMP
79#pragma omp declare simd aligned(XYZ, LMS:16)
80#endif
81static inline void convert_XYZ_to_CAT16_LMS(const dt_aligned_pixel_t XYZ, dt_aligned_pixel_t LMS)
82{
83 // Warning : needs XYZ normalized with Y - you need to downscale before
85}
86
87#ifdef _OPENMP
88#pragma omp declare simd aligned(XYZ, LMS:16)
89#endif
90static inline void convert_CAT16_LMS_to_XYZ(const dt_aligned_pixel_t LMS, dt_aligned_pixel_t XYZ)
91{
92 // Warning : output XYZ normalized with Y - you need to upscale later
94}
95
96
97#ifdef _OPENMP
98#pragma omp declare simd aligned(XYZ, LMS:16) uniform(kind)
99#endif
100static inline void convert_any_LMS_to_XYZ(const dt_aligned_pixel_t LMS, dt_aligned_pixel_t XYZ,
101 const dt_adaptation_t kind)
102{
103 // helper function switching internally to the proper conversion
104
105 switch(kind)
106 {
109 {
111 break;
112 }
114 {
115 convert_CAT16_LMS_to_XYZ(LMS, XYZ);
116 break;
117 }
121 default:
122 {
123 // special case : just pass through.
124 XYZ[0] = LMS[0];
125 XYZ[1] = LMS[1];
126 XYZ[2] = LMS[2];
127 break;
128 }
129 }
130}
131
132
133#ifdef _OPENMP
134#pragma omp declare simd aligned(XYZ, LMS:16) uniform(kind)
135#endif
136static inline void convert_any_XYZ_to_LMS(const dt_aligned_pixel_t XYZ, dt_aligned_pixel_t LMS, dt_adaptation_t kind)
137{
138 // helper function switching internally to the proper conversion
139
140 switch(kind)
141 {
144 {
146 break;
147 }
149 {
150 convert_XYZ_to_CAT16_LMS(XYZ, LMS);
151 break;
152 }
156 default:
157 {
158 // special case : just pass through.
159 LMS[0] = XYZ[0];
160 LMS[1] = XYZ[1];
161 LMS[2] = XYZ[2];
162 break;
163 }
164 }
165}
166
167
168#ifdef _OPENMP
169#pragma omp declare simd aligned(RGB, LMS:16) uniform(kind)
170#endif
171static inline void convert_any_LMS_to_RGB(const dt_aligned_pixel_t LMS, dt_aligned_pixel_t RGB, dt_adaptation_t kind)
172{
173 // helper function switching internally to the proper conversion
174 dt_aligned_pixel_t XYZ = { 0.f };
175 convert_any_LMS_to_XYZ(LMS, XYZ, kind);
176
177 // Fixme : convert to RGB display space instead of sRGB but first the display profile should be global in dt,
178 // not confined to colorout where it gets created/destroyed all the time.
179 dt_XYZ_to_Rec709_D65(XYZ, RGB);
180
181 // Handle gamut clipping
182 float max_RGB = fmaxf(fmaxf(RGB[0], RGB[1]), RGB[2]);
183 for(int c = 0; c < 3; c++) RGB[c] = fmaxf(RGB[c] / max_RGB, 0.f);
184
185}
186
187
188/* Bradford adaptations pre-computed for D50 and D65 outputs */
189
190#ifdef _OPENMP
191#pragma omp declare simd uniform(origin_illuminant) \
192 aligned(lms_in, lms_out, origin_illuminant:16)
193#endif
194static inline void bradford_adapt_D65(const dt_aligned_pixel_t lms_in,
195 const dt_aligned_pixel_t origin_illuminant,
196 const float p, const int full,
197 dt_aligned_pixel_t lms_out)
198{
199 // Bradford chromatic adaptation from origin to target D65 illuminant in LMS space
200 // p = powf(origin_illuminant[2] / D65[2], 0.0834f) needs to be precomputed for performance,
201 // since it is independent from current pixel values
202 // origin illuminant need also to be precomputed to LMS
203
204 // Precomputed D65 primaries in Bradford LMS for camera WB adjustment
205 const dt_aligned_pixel_t D65 = { 0.941238f, 1.040633f, 1.088932f, 0.f };
206
207 dt_aligned_pixel_t temp = { lms_in[0] / origin_illuminant[0],
208 lms_in[1] / origin_illuminant[1],
209 lms_in[2] / origin_illuminant[2],
210 0.f };
211
212 // use linear Bradford if B is negative
213 if(full) temp[2] = (temp[2] > 0.f) ? powf(temp[2], p) : temp[2];
214
215 lms_out[0] = D65[0] * temp[0];
216 lms_out[1] = D65[1] * temp[1];
217 lms_out[2] = D65[2] * temp[2];
218}
219
220
221#ifdef _OPENMP
222#pragma omp declare simd uniform(origin_illuminant) \
223 aligned(lms_in, lms_out, origin_illuminant:16)
224#endif
225static inline void bradford_adapt_D50(const dt_aligned_pixel_t lms_in,
226 const dt_aligned_pixel_t origin_illuminant,
227 const float p, const int full,
228 dt_aligned_pixel_t lms_out)
229{
230 // Bradford chromatic adaptation from origin to target D50 illuminant in LMS space
231 // p = powf(origin_illuminant[2] / D50[2], 0.0834f) needs to be precomputed for performance,
232 // since it is independent from current pixel values
233 // origin illuminant need also to be precomputed to LMS
234
235 // Precomputed D50 primaries in Bradford LMS for ICC transforms
236 const dt_aligned_pixel_t D50 = { 0.996078f, 1.020646f, 0.818155f, 0.f };
237
238 dt_aligned_pixel_t temp = { lms_in[0] / origin_illuminant[0],
239 lms_in[1] / origin_illuminant[1],
240 lms_in[2] / origin_illuminant[2],
241 0.f };
242
243 // use linear Bradford if B is negative
244 if(full) temp[2] = (temp[2] > 0.f) ? powf(temp[2], p) : temp[2];
245
246 lms_out[0] = D50[0] * temp[0];
247 lms_out[1] = D50[1] * temp[1];
248 lms_out[2] = D50[2] * temp[2];
249}
250
251
252/* CAT16 adaptations pre-computed for D50 and D65 outputs */
253
254#ifdef _OPENMP
255#pragma omp declare simd uniform(origin_illuminant) \
256 aligned(lms_in, lms_out, origin_illuminant:16)
257#endif
258static inline void CAT16_adapt_D65(const dt_aligned_pixel_t lms_in,
259 const dt_aligned_pixel_t origin_illuminant,
260 const float D, const int full, dt_aligned_pixel_t lms_out)
261{
262 // CAT16 chromatic adaptation from origin to target D65 illuminant in LMS space
263 // D is the coefficient of adaptation, depending of the surround lighting
264 // origin illuminant need also to be precomputed to LMS
265
266 // Precomputed D65 primaries in CAT16 LMS for camera WB adjustment
267 const dt_aligned_pixel_t D65 = { 0.97553267f, 1.01647859f, 1.0848344f, 0.f };
268
269 if(full)
270 {
271 lms_out[0] = lms_in[0] * D65[0] / origin_illuminant[0];
272 lms_out[1] = lms_in[1] * D65[1] / origin_illuminant[1];
273 lms_out[2] = lms_in[2] * D65[2] / origin_illuminant[2];
274 }
275 else
276 {
277 lms_out[0] = lms_in[0] * (D * D65[0] / origin_illuminant[0] + 1.f - D);
278 lms_out[1] = lms_in[1] * (D * D65[1] / origin_illuminant[1] + 1.f - D);
279 lms_out[2] = lms_in[2] * (D * D65[2] / origin_illuminant[2] + 1.f - D);
280 }
281}
282
283
284#ifdef _OPENMP
285#pragma omp declare simd uniform(origin_illuminant) \
286 aligned(lms_in, lms_out, origin_illuminant:16)
287#endif
288static inline void CAT16_adapt_D50(const dt_aligned_pixel_t lms_in,
289 const dt_aligned_pixel_t origin_illuminant,
290 const float D, const int full,
291 dt_aligned_pixel_t lms_out)
292{
293 // CAT16 chromatic adaptation from origin to target D50 illuminant in LMS space
294 // D is the coefficient of adaptation, depending of the surround lighting
295 // origin illuminant need also to be precomputed to LMS
296
297 // Precomputed D50 primaries in CAT16 LMS for ICC transforms
298 const dt_aligned_pixel_t D50 = { 0.994535f, 1.000997f, 0.833036f, 0.f };
299
300 if(full)
301 {
302 lms_out[0] = lms_in[0] * D50[0] / origin_illuminant[0];
303 lms_out[1] = lms_in[1] * D50[1] / origin_illuminant[1];
304 lms_out[2] = lms_in[2] * D50[2] / origin_illuminant[2];
305 }
306 else
307 {
308 lms_out[0] = lms_in[0] * (D * D50[0] / origin_illuminant[0] + 1.f - D);
309 lms_out[1] = lms_in[1] * (D * D50[1] / origin_illuminant[1] + 1.f - D);
310 lms_out[2] = lms_in[2] * (D * D50[2] / origin_illuminant[2] + 1.f - D);
311 }
312}
313
314/* XYZ adaptations pre-computed for D50 and D65 outputs */
315
316#ifdef _OPENMP
317#pragma omp declare simd uniform(origin_illuminant) \
318 aligned(lms_in, lms_out, origin_illuminant:16)
319#endif
320static inline void XYZ_adapt_D65(const dt_aligned_pixel_t lms_in,
321 const dt_aligned_pixel_t origin_illuminant,
322 dt_aligned_pixel_t lms_out)
323{
324 // XYZ chromatic adaptation from origin to target D65 illuminant in XYZ space
325 // origin illuminant need also to be precomputed to XYZ
326
327 // Precomputed D65 primaries in XYZ for camera WB adjustment
328 const dt_aligned_pixel_t D65 = { 0.9504285453771807f, 1.0f, 1.0889003707981277f, 0.f };
329
330 lms_out[0] = lms_in[0] * D65[0] / origin_illuminant[0];
331 lms_out[1] = lms_in[1] * D65[1] / origin_illuminant[1];
332 lms_out[2] = lms_in[2] * D65[2] / origin_illuminant[2];
333}
334
335#ifdef _OPENMP
336#pragma omp declare simd uniform(origin_illuminant) \
337 aligned(lms_in, lms_out, origin_illuminant:16)
338#endif
339static inline void XYZ_adapt_D50(const dt_aligned_pixel_t lms_in,
340 const dt_aligned_pixel_t origin_illuminant,
341 dt_aligned_pixel_t lms_out)
342{
343 // XYZ chromatic adaptation from origin to target D65 illuminant in XYZ space
344 // origin illuminant need also to be precomputed to XYZ
345
346 // Precomputed D50 primaries in XYZ for camera WB adjustment
347 const dt_aligned_pixel_t D50 = { 0.9642119944211994f, 1.0f, 0.8251882845188288f, 0.f };
348
349 lms_out[0] = lms_in[0] * D50[0] / origin_illuminant[0];
350 lms_out[1] = lms_in[1] * D50[1] / origin_illuminant[1];
351 lms_out[2] = lms_in[2] * D50[2] / origin_illuminant[2];
352}
353
354/* Pre-solved matrices to adjust white point for triplets in CIE XYZ 1931 2° observer */
355
357 = { { 9.89466254e-01f, -4.00304626e-02f, 4.40530317e-02f, 0.f },
358 { -5.40518733e-03f, 1.00666069e+00f, -1.75551955e-03f, 0.f },
359 { -4.03920992e-04f, 1.50768030e-02f, 1.30210211e+00f, 0.f } };
360
362 = { { 0.95547342f, -0.02309845f, 0.06325924f, 0.f },
363 { -0.02836971f, 1.00999540f, 0.02104144f, 0.f },
364 { 0.01231401f, -0.02050765f, 1.33036593f, 0.f } };
365
367 = { { 1.01085433e+00f, 4.07086103e-02f, -3.41445825e-02f, 0.f },
368 { 5.42814201e-03f, 9.93581926e-01f, 1.15592039e-03f, 0.f },
369 { 2.50722468e-04f, -1.14918759e-02f, 7.67964947e-01f, 0.f } };
370
372 = { { 1.04792979f, 0.02294687f, -0.05019227f, 0.f },
373 { 0.02962781f, 0.99043443f, -0.0170738f, 0.f },
374 { -0.00924304f, 0.01505519f, 0.75187428f, 0.f } };
375
376#ifdef _OPENMP
377#pragma omp declare simd aligned(XYZ_in, XYZ_out:16)
378#endif
379static inline void XYZ_D50_to_D65(const dt_aligned_pixel_t XYZ_in, dt_aligned_pixel_t XYZ_out)
380{
381 dot_product(XYZ_in, XYZ_D50_to_D65_CAT16, XYZ_out);
382}
383
384#ifdef _OPENMP
385#pragma omp declare simd aligned(XYZ_in, XYZ_out:16)
386#endif
387static inline void XYZ_D65_to_D50(const dt_aligned_pixel_t XYZ_in, dt_aligned_pixel_t XYZ_out)
388{
389 dot_product(XYZ_in, XYZ_D65_to_D50_CAT16, XYZ_out);
390}
391
392/* Helper function to directly chroma-adapt a pixel in CIE XYZ 1931 2° */
393
394static inline void chroma_adapt_pixel(const dt_aligned_pixel_t in, dt_aligned_pixel_t out,
395 const dt_aligned_pixel_t illuminant, const dt_adaptation_t adaptation, const float p)
396{
397
398 // intermediate temp buffers
399 dt_aligned_pixel_t temp_one;
400 dt_aligned_pixel_t temp_two;
401
402 /* WE START IN XYZ */
403 const float Y = in[1];
404
405 switch(adaptation)
406 {
408 {
409 convert_XYZ_to_bradford_LMS(in, temp_two);
410 downscale_vector(temp_two, Y);
411 bradford_adapt_D50(temp_two, illuminant, p, TRUE, temp_one);
412 upscale_vector(temp_one, Y);
413 convert_bradford_LMS_to_XYZ(temp_one, out);
414 break;
415 }
417 {
418 convert_XYZ_to_bradford_LMS(in, temp_two);
419 downscale_vector(temp_two, Y);
420 bradford_adapt_D50(temp_two, illuminant, p, FALSE, temp_one);
421 upscale_vector(temp_one, Y);
422 convert_bradford_LMS_to_XYZ(temp_one, out);
423 break;
424 }
426 {
427 convert_XYZ_to_CAT16_LMS(in, temp_two);
428 downscale_vector(temp_two, Y);
429 CAT16_adapt_D50(temp_two, illuminant, 1.0f, TRUE, temp_one); // force full-adaptation
430 upscale_vector(temp_one, Y);
431 convert_CAT16_LMS_to_XYZ(temp_one, out);
432 break;
433 }
435 {
436 for(size_t c = 0; c < DT_PIXEL_SIMD_CHANNELS; ++c) temp_one[c] = in[c];
437 downscale_vector(temp_one, Y);
438 XYZ_adapt_D50(temp_one, illuminant, temp_two);
439 upscale_vector(temp_two, Y);
440 for(size_t c = 0; c < DT_PIXEL_SIMD_CHANNELS; ++c) out[c] = temp_two[c];
441 break;
442 }
445 default:
446 {
447 // No white balance.
448 for(size_t c = 0; c < DT_PIXEL_SIMD_CHANNELS; ++c) out[c] = in[c];
449 break;
450 }
451 }
452}
453
454/* Helper to get the D50 white point coordinates in LMS spaces */
455static inline void convert_D50_to_LMS(const dt_adaptation_t adaptation, dt_aligned_pixel_t D50)
456{
457 switch(adaptation)
458 {
461 {
462 D50[0] = 0.996078f;
463 D50[1] = 1.020646f;
464 D50[2] = 0.818155f;
465 D50[3] = 0.f;
466 break;
467 }
469 {
470 D50[0] = 0.994535f;
471 D50[1] = 1.000997f;
472 D50[2] = 0.833036f;
473 D50[3] = 0.f;
474 break;
475 }
477 {
478 D50[0] = 0.9642119944211994f;
479 D50[1] = 1.0f;
480 D50[2] = 0.8251882845188288f;
481 D50[3] = 0.f;
482 break;
483 }
486 default:
487 {
488 D50[0] = 1.f;
489 D50[1] = 1.f;
490 D50[2] = 1.f;
491 D50[3] = 0.f;
492 break;
493 }
494 }
495}
496// clang-format off
497// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
498// vim: shiftwidth=2 expandtab tabstop=2 cindent
499// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
500// clang-format on
#define TRUE
Definition ashift_lsd.c:151
#define FALSE
Definition ashift_lsd.c:147
static void XYZ_D50_to_D65(const dt_aligned_pixel_t XYZ_in, dt_aligned_pixel_t XYZ_out)
Definition chromatic_adaptation.h:379
static void CAT16_adapt_D50(const dt_aligned_pixel_t lms_in, const dt_aligned_pixel_t origin_illuminant, const float D, const int full, dt_aligned_pixel_t lms_out)
Definition chromatic_adaptation.h:288
static void CAT16_adapt_D65(const dt_aligned_pixel_t lms_in, const dt_aligned_pixel_t origin_illuminant, const float D, const int full, dt_aligned_pixel_t lms_out)
Definition chromatic_adaptation.h:258
const dt_colormatrix_t XYZ_D50_to_D65_Bradford
Definition chromatic_adaptation.h:362
const dt_colormatrix_t CAT16_LMS_to_XYZ
Definition chromatic_adaptation.h:74
static void XYZ_D65_to_D50(const dt_aligned_pixel_t XYZ_in, dt_aligned_pixel_t XYZ_out)
Definition chromatic_adaptation.h:387
const dt_colormatrix_t XYZ_D65_to_D50_CAT16
Definition chromatic_adaptation.h:367
const dt_colormatrix_t XYZ_D50_to_D65_CAT16
Definition chromatic_adaptation.h:357
const dt_colormatrix_t XYZ_to_CAT16_LMS
Definition chromatic_adaptation.h:70
static void convert_XYZ_to_CAT16_LMS(const dt_aligned_pixel_t XYZ, dt_aligned_pixel_t LMS)
Definition chromatic_adaptation.h:81
static void convert_D50_to_LMS(const dt_adaptation_t adaptation, dt_aligned_pixel_t D50)
Definition chromatic_adaptation.h:455
static void convert_any_LMS_to_XYZ(const dt_aligned_pixel_t LMS, dt_aligned_pixel_t XYZ, const dt_adaptation_t kind)
Definition chromatic_adaptation.h:100
dt_adaptation_t
Definition chromatic_adaptation.h:25
@ DT_ADAPTATION_LAST
Definition chromatic_adaptation.h:31
@ DT_ADAPTATION_FULL_BRADFORD
Definition chromatic_adaptation.h:28
@ DT_ADAPTATION_XYZ
Definition chromatic_adaptation.h:29
@ DT_ADAPTATION_CAT16
Definition chromatic_adaptation.h:27
@ DT_ADAPTATION_RGB
Definition chromatic_adaptation.h:30
@ DT_ADAPTATION_LINEAR_BRADFORD
Definition chromatic_adaptation.h:26
static void bradford_adapt_D50(const dt_aligned_pixel_t lms_in, const dt_aligned_pixel_t origin_illuminant, const float p, const int full, dt_aligned_pixel_t lms_out)
Definition chromatic_adaptation.h:225
static void convert_any_XYZ_to_LMS(const dt_aligned_pixel_t XYZ, dt_aligned_pixel_t LMS, dt_adaptation_t kind)
Definition chromatic_adaptation.h:136
static void bradford_adapt_D65(const dt_aligned_pixel_t lms_in, const dt_aligned_pixel_t origin_illuminant, const float p, const int full, dt_aligned_pixel_t lms_out)
Definition chromatic_adaptation.h:194
static void convert_CAT16_LMS_to_XYZ(const dt_aligned_pixel_t LMS, dt_aligned_pixel_t XYZ)
Definition chromatic_adaptation.h:90
static void chroma_adapt_pixel(const dt_aligned_pixel_t in, dt_aligned_pixel_t out, const dt_aligned_pixel_t illuminant, const dt_adaptation_t adaptation, const float p)
Definition chromatic_adaptation.h:394
static void convert_any_LMS_to_RGB(const dt_aligned_pixel_t LMS, dt_aligned_pixel_t RGB, dt_adaptation_t kind)
Definition chromatic_adaptation.h:171
static void convert_bradford_LMS_to_XYZ(const dt_aligned_pixel_t LMS, dt_aligned_pixel_t XYZ)
Definition chromatic_adaptation.h:60
static void XYZ_adapt_D65(const dt_aligned_pixel_t lms_in, const dt_aligned_pixel_t origin_illuminant, dt_aligned_pixel_t lms_out)
Definition chromatic_adaptation.h:320
const dt_colormatrix_t XYZ_to_Bradford_LMS
Definition chromatic_adaptation.h:40
const dt_colormatrix_t Bradford_LMS_to_XYZ
Definition chromatic_adaptation.h:44
static void XYZ_adapt_D50(const dt_aligned_pixel_t lms_in, const dt_aligned_pixel_t origin_illuminant, dt_aligned_pixel_t lms_out)
Definition chromatic_adaptation.h:339
static void convert_XYZ_to_bradford_LMS(const dt_aligned_pixel_t XYZ, dt_aligned_pixel_t LMS)
Definition chromatic_adaptation.h:51
const dt_colormatrix_t XYZ_D65_to_D50_Bradford
Definition chromatic_adaptation.h:372
static void dt_XYZ_to_Rec709_D65(const dt_aligned_pixel_t XYZ, dt_aligned_pixel_t sRGB)
Definition colorspaces_inline_conversions.h:417
#define DT_PIXEL_SIMD_CHANNELS
Definition darktable.h:387
static void upscale_vector(dt_aligned_pixel_t vector, const float scaling)
Definition math.h:244
static void downscale_vector(dt_aligned_pixel_t vector, const float scaling)
Definition math.h:233
float DT_ALIGNED_ARRAY dt_colormatrix_t[4][4]
Definition matrices.h:24
static void dot_product(const dt_aligned_pixel_t v_in, const dt_colormatrix_t M, dt_aligned_pixel_t v_out)
Definition matrices.h:178