Skip to content

Commit 394a9fd

Browse files
committed
wb: revert, treat DT_ILLUMINANT_FROM_WB the same as DT_ILLUMINANT_CAMERA (then gradually separate them, in small steps)
1 parent ae57760 commit 394a9fd

2 files changed

Lines changed: 90 additions & 169 deletions

File tree

src/common/illuminants.h

Lines changed: 36 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -216,18 +216,15 @@ static inline void illuminant_CCT_to_RGB(const float t, dt_aligned_pixel_t RGB)
216216
illuminant_xy_to_RGB(x, y, RGB);
217217
}
218218

219-
static inline gboolean find_temperature_from_wb_coeffs(const dt_image_t *img, const dt_aligned_pixel_t wb_coeffs,
220-
float *chroma_x, float *chroma_y);
221219

222220
// Fetch image from pipeline and read EXIF for camera RAW WB coeffs
223-
static inline gboolean find_temperature_from_as_shot_coeffs(const dt_image_t *img, const dt_aligned_pixel_t adaptation_ratios,
221+
static inline gboolean find_temperature_from_raw_coeffs(const dt_image_t *img, const dt_aligned_pixel_t custom_wb,
224222
float *chroma_x, float *chroma_y);
225223

226224

227225
static inline int illuminant_to_xy(const dt_illuminant_t illuminant, // primary type of illuminant
228226
const dt_image_t *img, // image container
229-
const dt_aligned_pixel_t wb_coeffs,
230-
const dt_aligned_pixel_t adaptation_ratios, // optional ratios to adapt camera WB
227+
const dt_aligned_pixel_t custom_wb, // optional user-set WB coeffs
231228
float *x_out, float *y_out, // chromaticity output
232229
const float t, // temperature in K, if needed
233230
const dt_illuminant_fluo_t fluo, // sub-type of fluorescent illuminant, if needed
@@ -304,11 +301,13 @@ static inline int illuminant_to_xy(const dt_illuminant_t illuminant, // primary
304301
{
305302
// Detect WB from RAW EXIF
306303
if(img)
307-
if(find_temperature_from_as_shot_coeffs(img, adaptation_ratios, &x, &y)) break;
304+
if(find_temperature_from_raw_coeffs(img, custom_wb, &x, &y)) break;
308305
}
309-
case DT_ILLUMINANT_FROM_WB: {
306+
case DT_ILLUMINANT_FROM_WB:
307+
{ // FIXME copy-paste
308+
// Detect WB from RAW EXIF
310309
if(img)
311-
if(find_temperature_from_wb_coeffs(img, wb_coeffs, &x, &y)) break;
310+
if(find_temperature_from_raw_coeffs(img, custom_wb, &x, &y)) break;
312311
}
313312
case DT_ILLUMINANT_CUSTOM: // leave x and y as-is
314313
case DT_ILLUMINANT_DETECT_EDGES:
@@ -337,8 +336,6 @@ static inline void WB_coeffs_to_illuminant_xy(const float CAM_to_XYZ[4][3], cons
337336
dt_aligned_pixel_t XYZ, LMS;
338337
// Simulate white point, aka convert (1, 1, 1) in camera space to XYZ
339338
// warning : we multiply the transpose of CAM_to_XYZ since the pseudoinverse transposes it
340-
// if we're not in 'caveat' workaround mode, we'll push (1, 1, 1) through the matrix to find the
341-
// XYZ of the illuminant
342339
XYZ[0] = CAM_to_XYZ[0][0] / WB[0] + CAM_to_XYZ[1][0] / WB[1] + CAM_to_XYZ[2][0] / WB[2];
343340
XYZ[1] = CAM_to_XYZ[0][1] / WB[0] + CAM_to_XYZ[1][1] / WB[1] + CAM_to_XYZ[2][1] / WB[2];
344341
XYZ[2] = CAM_to_XYZ[0][2] / WB[0] + CAM_to_XYZ[1][2] / WB[1] + CAM_to_XYZ[2][2] / WB[2];
@@ -395,10 +392,31 @@ static inline void matrice_pseudoinverse(float (*in)[3], float (*out)[3], int si
395392
}
396393
}
397394

398-
// returns TRUE is OK, FALSE if failed
399-
static gboolean get_CAM_to_XYZ(const dt_image_t * img, float(* CAM_to_XYZ)[3])
395+
396+
static gboolean find_temperature_from_raw_coeffs(const dt_image_t *img, const dt_aligned_pixel_t custom_wb,
397+
float *chroma_x, float *chroma_y)
400398
{
401-
// Get the camera input profile (matrice of primaries) - embedded or raw library DB
399+
if(img == NULL) return FALSE;
400+
if(!dt_image_is_matrix_correction_supported(img)) return FALSE;
401+
402+
gboolean has_valid_coeffs = TRUE;
403+
const int num_coeffs = (img->flags & DT_IMAGE_4BAYER) ? 4 : 3;
404+
405+
// Check coeffs
406+
for(int k = 0; has_valid_coeffs && k < num_coeffs; k++)
407+
if(!dt_isnormal(img->wb_coeffs[k]) || img->wb_coeffs[k] == 0.0f) has_valid_coeffs = FALSE;
408+
409+
if(!has_valid_coeffs) return FALSE;
410+
411+
// Get white balance camera factors
412+
dt_aligned_pixel_t WB = { img->wb_coeffs[0], img->wb_coeffs[1], img->wb_coeffs[2], img->wb_coeffs[3] };
413+
414+
// Adapt the camera coeffs with custom white balance if provided
415+
// this can deal with WB coeffs that don't use the input matrix reference
416+
if(custom_wb)
417+
for(size_t k = 0; k < 4; k++) WB[k] *= custom_wb[k];
418+
419+
// Get the camera input profile (matrice of primaries)
402420
float XYZ_to_CAM[4][3];
403421
dt_mark_colormatrix_invalid(&XYZ_to_CAM[0][0]);
404422

@@ -427,60 +445,21 @@ static gboolean get_CAM_to_XYZ(const dt_image_t * img, float(* CAM_to_XYZ)[3])
427445

428446
if(!dt_is_valid_colormatrix(XYZ_to_CAM[0][0])) return FALSE;
429447

448+
// Bloody input matrices define XYZ -> CAM transform, as if we often needed camera profiles to output
449+
// So we need to invert them. Here go your CPU cycles again.
450+
float CAM_to_XYZ[4][3];
430451
dt_mark_colormatrix_invalid(&CAM_to_XYZ[0][0]);
431452
matrice_pseudoinverse(XYZ_to_CAM, CAM_to_XYZ, 3);
432-
return dt_is_valid_colormatrix(CAM_to_XYZ[0][0]);
433-
}
434-
435-
// returns FALSE if failed; TRUE if successful
436-
static gboolean find_temperature_from_wb_coeffs(const dt_image_t *img, const dt_aligned_pixel_t wb_coeffs,
437-
float *chroma_x, float *chroma_y)
438-
{
439-
if(img == NULL || wb_coeffs) return FALSE;
440-
if(!dt_image_is_matrix_correction_supported(img)) return FALSE;
441-
442-
float CAM_to_XYZ[4][3];
443-
if (!get_CAM_to_XYZ(img, CAM_to_XYZ)) {
444-
return FALSE;
445-
}
453+
if(!dt_is_valid_colormatrix(CAM_to_XYZ[0][0])) return FALSE;
446454

447455
float x, y;
448-
WB_coeffs_to_illuminant_xy(CAM_to_XYZ, wb_coeffs, &x, &y);
456+
WB_coeffs_to_illuminant_xy(CAM_to_XYZ, WB, &x, &y);
449457
*chroma_x = x;
450458
*chroma_y = y;
451459

452460
return TRUE;
453461
}
454462

455-
// returns FALSE if failed; TRUE if successful
456-
static gboolean find_temperature_from_as_shot_coeffs(const dt_image_t *img, const dt_aligned_pixel_t adaptation_ratios,
457-
float *chroma_x, float *chroma_y)
458-
{
459-
if(img == NULL) return FALSE;
460-
461-
gboolean has_valid_coeffs = TRUE;
462-
const int num_coeffs = (img->flags & DT_IMAGE_4BAYER) ? 4 : 3;
463-
464-
// Check coeffs
465-
for(int k = 0; has_valid_coeffs && k < num_coeffs; k++)
466-
if(!dt_isnormal(img->wb_coeffs[k]) || img->wb_coeffs[k] == 0.0f) has_valid_coeffs = FALSE;
467-
468-
if(!has_valid_coeffs) return FALSE;
469-
470-
// Get as-shot white balance camera factors (from raw)
471-
// component wise raw-RGB * wb_coeffs should provide R=G=B for a neutral patch under
472-
// the scene illuminant
473-
dt_aligned_pixel_t WB = { img->wb_coeffs[0], img->wb_coeffs[1], img->wb_coeffs[2], img->wb_coeffs[3] };
474-
475-
// Adapt the camera coeffs with custom D65 coefficients if provided ('caveats' workaround)
476-
// this can deal with WB coeffs that don't use the input matrix reference
477-
// adaptation_ratios[k] = chr->D65coeffs[k] / chr->wb_coeffs[k]
478-
if(adaptation_ratios)
479-
for(size_t k = 0; k < 4; k++) WB[k] *= adaptation_ratios[k];
480-
// for a neutral surface, raw RGB * img->wb_coeffs would produce neutral R=G=B
481-
482-
return find_temperature_from_wb_coeffs(img, WB, chroma_x, chroma_y);
483-
}
484463

485464
DT_OMP_DECLARE_SIMD()
486465
static inline float planckian_normal(const float x, const float t)

0 commit comments

Comments
 (0)