Skip to content

Commit 6631dc3

Browse files
committed
wb: added wb_coeffs to illuminant_to_xy, separate from correction_ratios (renamed from misleading custom_wb)
1 parent 9454fad commit 6631dc3

2 files changed

Lines changed: 86 additions & 57 deletions

File tree

src/common/illuminants.h

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -220,17 +220,18 @@ static inline gboolean find_temperature_from_wb_coeffs(const dt_image_t *img, co
220220
float *chroma_x, float *chroma_y);
221221

222222
// 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 custom_wb,
223+
static inline gboolean find_temperature_from_as_shot_coeffs(const dt_image_t *img, const dt_aligned_pixel_t correction_ratios,
224224
float *chroma_x, float *chroma_y);
225225

226226

227-
static inline int illuminant_to_xy(const dt_illuminant_t illuminant, // primary type of illuminant
228-
const dt_image_t *img, // image container
229-
const dt_aligned_pixel_t custom_wb, // optional user-set WB coeffs
230-
float *x_out, float *y_out, // chromaticity output
231-
const float t, // temperature in K, if needed
232-
const dt_illuminant_fluo_t fluo, // sub-type of fluorescent illuminant, if needed
233-
const dt_illuminant_led_t iled) // sub-type of led illuminant, if needed
227+
static inline int illuminant_to_xy(const dt_illuminant_t illuminant, // primary type of illuminant
228+
const dt_image_t *img, // image container
229+
const dt_aligned_pixel_t correction_ratios, // optional D65 correction ratios derived from user-set coefficients
230+
const dt_aligned_pixel_t wb_coeffs, // optional user-set WB coeffs (absolute)
231+
float *x_out, float *y_out, // chromaticity output
232+
const float t, // temperature in K, if needed
233+
const dt_illuminant_fluo_t fluo, // sub-type of fluorescent illuminant, if needed
234+
const dt_illuminant_led_t iled) // sub-type of led illuminant, if needed
234235
{
235236
/**
236237
* Compute the x and y chromaticity coordinates in Yxy spaces for standard illuminants
@@ -301,15 +302,15 @@ static inline int illuminant_to_xy(const dt_illuminant_t illuminant, // primary
301302
}
302303
case DT_ILLUMINANT_CAMERA:
303304
{
304-
// Detect WB from RAW EXIF
305+
// Detect WB from RAW EXIF, correcting with D65/wb_coeff ratios
305306
if(img)
306-
if(find_temperature_from_as_shot_coeffs(img, custom_wb, &x, &y)) break;
307+
if(find_temperature_from_as_shot_coeffs(img, correction_ratios, &x, &y)) break;
307308
}
308309
case DT_ILLUMINANT_FROM_WB:
309-
{ // FIXME copy-paste
310-
// Detect WB from RAW EXIF
310+
{
311+
// Detect WB from user-provided coefficients
311312
if(img)
312-
if(find_temperature_from_as_shot_coeffs(img, custom_wb, &x, &y)) break;
313+
if(find_temperature_from_wb_coeffs(img, wb_coeffs, &x, &y)) break;
313314
}
314315
case DT_ILLUMINANT_CUSTOM: // leave x and y as-is
315316
case DT_ILLUMINANT_DETECT_EDGES:
@@ -453,7 +454,7 @@ static gboolean find_temperature_from_wb_coeffs(const dt_image_t *img, const dt_
453454
}
454455

455456
// 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 custom_wb,
457+
static gboolean find_temperature_from_as_shot_coeffs(const dt_image_t *img, const dt_aligned_pixel_t correction_ratios,
457458
float *chroma_x, float *chroma_y)
458459
{
459460
if(img == NULL) return FALSE;
@@ -475,8 +476,8 @@ static gboolean find_temperature_from_as_shot_coeffs(const dt_image_t *img, cons
475476
// Adapt the camera coeffs with custom D65 coefficients if provided ('caveats' workaround)
476477
// this can deal with WB coeffs that don't use the input matrix reference
477478
// adaptation_ratios[k] = chr->D65coeffs[k] / chr->wb_coeffs[k]
478-
if(custom_wb)
479-
for(size_t k = 0; k < 4; k++) WB[k] *= custom_wb[k];
479+
if(correction_ratios)
480+
for(size_t k = 0; k < 4; k++) WB[k] *= correction_ratios[k];
480481
// for a neutral surface, raw RGB * img->wb_coeffs would produce neutral R=G=B
481482

482483
return find_temperature_from_wb_coeffs(img, WB, chroma_x, chroma_y);

src/iop/channelmixerrgb.c

Lines changed: 69 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ void init_presets(dt_iop_module_so_t *self)
422422
p.illum_fluo = DT_ILLUMINANT_FLUO_F3;
423423
p.illum_led = DT_ILLUMINANT_LED_B5;
424424
p.temperature = 5003.f;
425-
illuminant_to_xy(DT_ILLUMINANT_PIPE, NULL, NULL, &p.x, &p.y, p.temperature,
425+
illuminant_to_xy(DT_ILLUMINANT_PIPE, NULL, NULL, NULL, &p.x, &p.y, p.temperature,
426426
DT_ILLUMINANT_FLUO_LAST, DT_ILLUMINANT_LED_LAST);
427427

428428
p.red[0] = 1.f;
@@ -609,14 +609,14 @@ static const char *_area_mapping_section_text(const dt_iop_channelmixer_rgb_gui_
609609
return _area_mapping_active(g) ? _("area color mapping (active)") : _("area color mapping");
610610
}
611611

612-
static gboolean _get_white_balance_coeff(const dt_iop_module_t *self,
613-
dt_aligned_pixel_t custom_wb)
612+
static gboolean _get_d65_correction_ratios(const dt_iop_module_t *self,
613+
dt_aligned_pixel_t out_correction_ratios)
614614
{
615615
const dt_dev_chroma_t *chr = &self->dev->chroma;
616616

617617
// Init output with a no-op
618618
for_four_channels(k)
619-
custom_wb[k] = 1.0f;
619+
out_correction_ratios[k] = 1.0f;
620620

621621
if(!dt_image_is_matrix_correction_supported(&self->dev->image_storage))
622622
return TRUE;
@@ -636,7 +636,7 @@ static gboolean _get_white_balance_coeff(const dt_iop_module_t *self,
636636
if(valid_chroma && changed_chroma)
637637
{
638638
for_four_channels(k)
639-
custom_wb[k] = (float)chr->D65coeffs[k] / chr->wb_coeffs[k];
639+
out_correction_ratios[k] = (float)chr->D65coeffs[k] / chr->wb_coeffs[k];
640640
}
641641
return FALSE;
642642
}
@@ -1244,7 +1244,7 @@ static void _check_if_close_to_daylight(const float x,
12441244
float uv_test[2];
12451245

12461246
// Compute the test chromaticity from the daylight model
1247-
illuminant_to_xy(DT_ILLUMINANT_D, NULL, NULL, &xy_test[0], &xy_test[1], t,
1247+
illuminant_to_xy(DT_ILLUMINANT_D, NULL, NULL, NULL, &xy_test[0], &xy_test[1], t,
12481248
DT_ILLUMINANT_FLUO_LAST, DT_ILLUMINANT_LED_LAST);
12491249
xy_to_uv(xy_test, uv_test);
12501250

@@ -1253,7 +1253,7 @@ static void _check_if_close_to_daylight(const float x,
12531253
const float delta_daylight = dt_fast_hypotf(uv_test[0] - uv_ref[0], uv_test[1] - uv_ref[1]);
12541254

12551255
// Compute the test chromaticity from the blackbody model
1256-
illuminant_to_xy(DT_ILLUMINANT_BB, NULL, NULL, &xy_test[0], &xy_test[1], t,
1256+
illuminant_to_xy(DT_ILLUMINANT_BB, NULL, NULL, NULL, &xy_test[0], &xy_test[1], t,
12571257
DT_ILLUMINANT_FLUO_LAST, DT_ILLUMINANT_LED_LAST);
12581258
xy_to_uv(xy_test, uv_test);
12591259

@@ -2205,10 +2205,10 @@ void process(dt_iop_module_t *self,
22052205
// change here, so we can't update the defaults. So we need to
22062206
// re-run the detection at runtime…
22072207
float x, y;
2208-
dt_aligned_pixel_t custom_wb;
2209-
_get_white_balance_coeff(self, custom_wb);
2208+
dt_aligned_pixel_t correction_ratios;
2209+
_get_d65_correction_ratios(self, correction_ratios);
22102210

2211-
if(find_temperature_from_as_shot_coeffs(&(self->dev->image_storage), custom_wb, &(x), &(y)))
2211+
if(find_temperature_from_as_shot_coeffs(&(self->dev->image_storage), correction_ratios, &(x), &(y)))
22122212
{
22132213
// Convert illuminant from xyY to XYZ
22142214
dt_aligned_pixel_t XYZ;
@@ -2331,10 +2331,10 @@ int process_cl(dt_iop_module_t *self,
23312331
// change here, so we can't update the defaults. So we need to
23322332
// re-run the detection at runtime…
23332333
float x, y;
2334-
dt_aligned_pixel_t custom_wb;
2335-
_get_white_balance_coeff(self, custom_wb);
2334+
dt_aligned_pixel_t correction_ratios;
2335+
_get_d65_correction_ratios(self, correction_ratios);
23362336

2337-
if(find_temperature_from_as_shot_coeffs(&(self->dev->image_storage), custom_wb, &(x), &(y)))
2337+
if(find_temperature_from_as_shot_coeffs(&(self->dev->image_storage), correction_ratios, &(x), &(y)))
23382338
{
23392339
// Convert illuminant from xyY to XYZ
23402340
dt_aligned_pixel_t XYZ;
@@ -3145,16 +3145,22 @@ void commit_params(dt_iop_module_t *self,
31453145
// find x y coordinates of illuminant for CIE 1931 2° observer
31463146
float x = p->x;
31473147
float y = p->y;
3148-
dt_aligned_pixel_t custom_wb;
3149-
_get_white_balance_coeff(self, custom_wb);
3150-
illuminant_to_xy(p->illuminant, &(self->dev->image_storage),
3151-
custom_wb, &x, &y, p->temperature, p->illum_fluo, p->illum_led);
3148+
dt_aligned_pixel_t correction_ratios;
3149+
_get_d65_correction_ratios(self, correction_ratios);
3150+
dt_aligned_pixel_t wb_coeffs = {0.f};
3151+
if(p->illuminant == DT_ILLUMINANT_FROM_WB)
3152+
{
3153+
for(int k = 0; k < 4; k++)
3154+
wb_coeffs[k] = self->dev->chroma.wb_coeffs[k];
3155+
}
3156+
illuminant_to_xy(p->illuminant, &(self->dev->image_storage), correction_ratios,
3157+
wb_coeffs, &x, &y, p->temperature, p->illum_fluo,
3158+
p->illum_led);
31523159

3153-
// if illuminant is set as camera, x and y are set on-the-fly at
3160+
// if illuminant is from camera or user WB coefficients, x and y are set on-the-fly at
31543161
// commit time, so we need to set adaptation too
31553162
if(p->illuminant == DT_ILLUMINANT_CAMERA || p->illuminant == DT_ILLUMINANT_FROM_WB)
3156-
_check_if_close_to_daylight(x, y, NULL, NULL, &(d->adaptation));
3157-
3163+
_check_if_close_to_daylight(x, y, NULL, NULL, &(d->adaptation));
31583164
d->illuminant_type = p->illuminant;
31593165

31603166
// Convert illuminant from xyY to XYZ
@@ -3590,11 +3596,18 @@ static gboolean _illuminant_color_draw(GtkWidget *widget,
35903596
// camera RAW is chosen
35913597
float x = p->x;
35923598
float y = p->y;
3593-
dt_aligned_pixel_t RGB = { 0 };
3594-
dt_aligned_pixel_t custom_wb;
3595-
_get_white_balance_coeff(self, custom_wb);
3596-
illuminant_to_xy(p->illuminant, &(self->dev->image_storage), custom_wb,
3597-
&x, &y, p->temperature, p->illum_fluo, p->illum_led);
3599+
dt_aligned_pixel_t RGB = { 0.f };
3600+
dt_aligned_pixel_t correction_ratios;
3601+
_get_d65_correction_ratios(self, correction_ratios);
3602+
dt_aligned_pixel_t wb_coeffs = { 0.f };
3603+
if(p->illuminant == DT_ILLUMINANT_FROM_WB)
3604+
{
3605+
for(int k = 0; k < 4; k++)
3606+
wb_coeffs[k] = self->dev->chroma.wb_coeffs[k];
3607+
}
3608+
illuminant_to_xy(p->illuminant, &(self->dev->image_storage), correction_ratios,
3609+
wb_coeffs, &x, &y, p->temperature, p->illum_fluo,
3610+
p->illum_led);
35983611
illuminant_xy_to_RGB(x, y, RGB);
35993612
cairo_set_source_rgb(cr, RGB[0], RGB[1], RGB[2]);
36003613
cairo_rectangle(cr, INNER_PADDING, margin, width, height);
@@ -3694,10 +3707,17 @@ static void _update_approx_cct(const dt_iop_module_t *self)
36943707

36953708
float x = p->x;
36963709
float y = p->y;
3697-
dt_aligned_pixel_t custom_wb;
3698-
_get_white_balance_coeff(self, custom_wb);
3699-
illuminant_to_xy(p->illuminant, &(self->dev->image_storage),
3700-
custom_wb, &x, &y, p->temperature, p->illum_fluo, p->illum_led);
3710+
dt_aligned_pixel_t correction_ratios;
3711+
_get_d65_correction_ratios(self, correction_ratios);
3712+
dt_aligned_pixel_t wb_coeffs = { 0.f };
3713+
if(p->illuminant == DT_ILLUMINANT_FROM_WB)
3714+
{
3715+
for(int k = 0; k < 4; k++)
3716+
wb_coeffs[k] = self->dev->chroma.wb_coeffs[k];
3717+
}
3718+
illuminant_to_xy(p->illuminant, &(self->dev->image_storage), correction_ratios,
3719+
wb_coeffs, &x, &y, p->temperature, p->illum_fluo,
3720+
p->illum_led);
37013721

37023722
dt_illuminant_t test_illuminant;
37033723
float t = 5000.f;
@@ -3931,10 +3951,10 @@ void reload_defaults(dt_iop_module_t *self)
39313951
{
39323952
d->adaptation = DT_ADAPTATION_CAT16;
39333953

3934-
dt_aligned_pixel_t custom_wb;
3935-
if(!_get_white_balance_coeff(self, custom_wb))
3954+
dt_aligned_pixel_t correction_ratios;
3955+
if(!_get_d65_correction_ratios(self, correction_ratios))
39363956
{
3937-
if(find_temperature_from_as_shot_coeffs(img, custom_wb, &(d->x), &(d->y)))
3957+
if(find_temperature_from_as_shot_coeffs(img, correction_ratios, &(d->x), &(d->y)))
39383958
d->illuminant = DT_ILLUMINANT_CAMERA;
39393959
_check_if_close_to_daylight(d->x, d->y,
39403960
&(d->temperature), &(d->illuminant), &(d->adaptation));
@@ -4035,9 +4055,9 @@ void gui_changed(dt_iop_module_t *self,
40354055
// illuminant = "as set in camera", temperature and
40364056
// chromaticity are inited with the preset content when
40374057
// illuminant is changed.
4038-
dt_aligned_pixel_t custom_wb;
4039-
_get_white_balance_coeff(self, custom_wb);
4040-
find_temperature_from_as_shot_coeffs(&(self->dev->image_storage), custom_wb,
4058+
dt_aligned_pixel_t correction_ratios;
4059+
_get_d65_correction_ratios(self, correction_ratios);
4060+
find_temperature_from_as_shot_coeffs(&(self->dev->image_storage), correction_ratios,
40414061
&(p->x), &(p->y));
40424062
_check_if_close_to_daylight(p->x, p->y, &(p->temperature), NULL, &(p->adaptation));
40434063
}
@@ -4066,7 +4086,7 @@ void gui_changed(dt_iop_module_t *self,
40664086
{
40674087
// Get camera WB and update illuminant
40684088
dt_aligned_pixel_t custom_wb;
4069-
_get_white_balance_coeff(self, custom_wb);
4089+
_get_d65_correction_ratios(self, custom_wb);
40704090
const gboolean found = find_temperature_from_as_shot_coeffs(&(self->dev->image_storage),
40714091
custom_wb, &(p->x), &(p->y));
40724092
_check_if_close_to_daylight(p->x, p->y, &(p->temperature), NULL, &(p->adaptation));
@@ -4115,7 +4135,7 @@ void gui_changed(dt_iop_module_t *self,
41154135
{
41164136
// We are in any mode defining (x, y) indirectly from an
41174137
// interface, so commit (x, y) explicitly
4118-
illuminant_to_xy(p->illuminant, NULL, NULL, &(p->x), &(p->y),
4138+
illuminant_to_xy(p->illuminant, NULL, NULL, NULL, &(p->x), &(p->y),
41194139
p->temperature, p->illum_fluo, p->illum_led);
41204140
}
41214141

@@ -4283,11 +4303,19 @@ static void _auto_set_illuminant(dt_iop_module_t *self,
42834303
// find x y coordinates of illuminant for CIE 1931 2° observer
42844304
float x = p->x;
42854305
float y = p->y;
4306+
dt_aligned_pixel_t correction_ratios;
4307+
_get_d65_correction_ratios(self, correction_ratios);
4308+
dt_aligned_pixel_t wb_coeffs = { 0.f };
4309+
if(p->illuminant == DT_ILLUMINANT_FROM_WB)
4310+
{
4311+
for(int k = 0; k < 4; k++)
4312+
wb_coeffs[k] = self->dev->chroma.wb_coeffs[k];
4313+
}
4314+
illuminant_to_xy(p->illuminant, &(self->dev->image_storage), correction_ratios,
4315+
wb_coeffs, &x, &y, p->temperature, p->illum_fluo,
4316+
p->illum_led);
4317+
42864318
dt_adaptation_t adaptation = p->adaptation;
4287-
dt_aligned_pixel_t custom_wb;
4288-
_get_white_balance_coeff(self, custom_wb);
4289-
illuminant_to_xy(p->illuminant, &(self->dev->image_storage),
4290-
custom_wb, &x, &y, p->temperature, p->illum_fluo, p->illum_led);
42914319

42924320
// if illuminant is set as camera, x and y are set on-the-fly at
42934321
// commit time, so we need to set adaptation too

0 commit comments

Comments
 (0)