90#include "external/cie_colorimetric_tables.c"
98#define INITIALBLACKBODYTEMPERATURE 4000
100#define DT_IOP_LOWEST_TEMPERATURE 1901
101#define DT_IOP_HIGHEST_TEMPERATURE 25000
103#define DT_IOP_LOWEST_TINT 0.135
104#define DT_IOP_HIGHEST_TINT 2.326
106#define DT_IOP_NUM_OF_STD_TEMP_PRESETS 4
109#define DT_IOP_TEMP_AS_SHOT 0
110#define DT_IOP_TEMP_SPOT 1
111#define DT_IOP_TEMP_USER 2
112#define DT_IOP_TEMP_D65 3
171 void *new_params,
const int new_version)
173 if(old_version == 2 && new_version == 3)
175 typedef struct dt_iop_temperature_params_v2_t
179 } dt_iop_temperature_params_v2_t;
181 dt_iop_temperature_params_v2_t *
o = (dt_iop_temperature_params_v2_t *)old_params;
184 n->
red =
o->coeffs[0];
185 n->green =
o->coeffs[1];
186 n->blue =
o->coeffs[2];
196 p->red = a[0];
p->green = a[1];
p->blue = a[2];
p->g2 = a[3];
201 a[0] =
p->red; a[1] =
p->green; a[2] =
p->blue; a[3] =
p->g2;
208 if(g_str_has_suffix(img->
filename,
"-hdr.dng"))
211 static const char *
const ignored_cameras[] = {
212 "Canon PowerShot A610",
213 "Canon PowerShot S3 IS",
214 "Canon PowerShot A620",
215 "Canon PowerShot A720 IS",
216 "Canon PowerShot A630",
217 "Canon PowerShot A640",
218 "Canon PowerShot A650",
219 "Canon PowerShot SX110 IS",
230 for(
int i=0;
i <
sizeof(ignored_cameras)/
sizeof(ignored_cameras[1]);
i++)
240 return C_(
"modulename",
"white balance");
247 _(
"linear, raw, scene-referred"),
249 _(
"linear, raw, scene-referred"));
281typedef double((*spd)(
unsigned long int wavelength,
double TempK));
290 const long double lambda = (
double)wavelength * 1e-9;
307#define c1 3.7417715246641281639549488324352159753e-16L
308#define c2 0.014387769599838156481252937624049081933L
310 return (
double)(
c1 / (powl(lambda, 5) * (expl(
c2 / (lambda * TempK)) - 1.0L)));
323 cmsCIExyY WhitePoint = { 0.3127, 0.3290, 1.0 };
329 cmsWhitePointFromTemp(&WhitePoint, TempK);
331 const double M = (0.0241 + 0.2562 * WhitePoint.x - 0.7341 * WhitePoint.y),
332 m1 = (-1.3515 - 1.7703 * WhitePoint.x + 5.9114 * WhitePoint.y) /
M,
333 m2 = (0.0300 - 31.4424 * WhitePoint.x + 30.0717 * WhitePoint.y) /
M;
335 const unsigned long int j
336 = ((wavelength - cie_daylight_components[0].wavelength)
337 / (cie_daylight_components[1].wavelength - cie_daylight_components[0].wavelength));
339 return (cie_daylight_components[j].
S[0] + m1 * cie_daylight_components[j].
S[1]
340 + m2 * cie_daylight_components[j].
S[2]);
349 cmsCIEXYZ Source = {.X = 0.0, .Y = 0.0, .Z = 0.0 };
355 for(
size_t i = 0;
i < cie_1931_std_colorimetric_observer_count;
i++)
357 const unsigned long int lambda = cie_1931_std_colorimetric_observer[0].wavelength
358 + (cie_1931_std_colorimetric_observer[1].wavelength
359 - cie_1931_std_colorimetric_observer[0].wavelength) *
i;
360 const double P = I(lambda, TempK);
361 Source.X +=
P * cie_1931_std_colorimetric_observer[
i].xyz.X;
362 Source.Y +=
P * cie_1931_std_colorimetric_observer[
i].xyz.Y;
363 Source.Z +=
P * cie_1931_std_colorimetric_observer[
i].xyz.Z;
367 const double _max = fmax(fmax(Source.X, Source.Y), Source.Z);
408 for(*TempK = (maxtemp + mintemp) / 2.0; (maxtemp - mintemp) > 1.0; *TempK = (maxtemp + mintemp) / 2.0)
411 if(_xyz.Z / _xyz.X >
XYZ.Z /
XYZ.X)
417 *tint = (_xyz.Y / _xyz.X) / (
XYZ.Y /
XYZ.X);
430 double XYZ[3] = { xyz.X, xyz.Y, xyz.Z };
433 for(
int k = 0;
k < 4;
k++)
436 for(
int i = 0;
i < 3;
i++)
438 CAM[
k] +=
g->XYZ_to_CAM[
k][
i] *
XYZ[
i];
442 for(
int k = 0;
k < 4;
k++) mul[
k] = 1.0 / CAM[
k];
467 for(
int k = 0; k < 4; k++) CAM[k] = CAM[k] > 0.0f ? 1.0 / CAM[
k] : 0.0f;
470 for(
int k = 0;
k < 3;
k++)
473 for(
int i = 0;
i < 4;
i++)
475 XYZ[
k] +=
g->CAM_to_XYZ[
k][
i] * CAM[
i];
479 return (cmsCIEXYZ){
XYZ[0],
XYZ[1],
XYZ[2] };
492 const uint32_t filters =
piece->dsc_in.filters;
493 const uint8_t(*
const xtrans)[6] = (
const uint8_t(*
const)[6])
piece->dsc_in.xtrans;
498 const float *
const in = (
const float *
const)ivoid;
499 float *
const out = (
float *
const)
ovoid;
500 const float *
const d_coeffs =
d->coeffs;
505 for(
int j = 0; j <
height; j++)
507 const size_t row_start = (size_t)j *
width;
508 const float coeffs[12] =
510 d_coeffs[
FCxtrans(j, 0, roi_out, xtrans)], d_coeffs[
FCxtrans(j, 1, roi_out, xtrans)],
511 d_coeffs[
FCxtrans(j, 2, roi_out, xtrans)], d_coeffs[
FCxtrans(j, 3, roi_out, xtrans)],
512 d_coeffs[
FCxtrans(j, 4, roi_out, xtrans)], d_coeffs[
FCxtrans(j, 5, roi_out, xtrans)],
513 d_coeffs[
FCxtrans(j, 6, roi_out, xtrans)], d_coeffs[
FCxtrans(j, 7, roi_out, xtrans)],
514 d_coeffs[
FCxtrans(j, 8, roi_out, xtrans)], d_coeffs[
FCxtrans(j, 9, roi_out, xtrans)],
515 d_coeffs[
FCxtrans(j, 10, roi_out, xtrans)], d_coeffs[
FCxtrans(j, 11, roi_out, xtrans)],
522 const size_t p = row_start +
i;
523 out[
p + 0] = in[
p + 0] * coeffs[0];
524 out[
p + 1] = in[
p + 1] * coeffs[1];
525 out[
p + 2] = in[
p + 2] * coeffs[2];
526 out[
p + 3] = in[
p + 3] * coeffs[3];
527 out[
p + 4] = in[
p + 4] * coeffs[4];
528 out[
p + 5] = in[
p + 5] * coeffs[5];
529 out[
p + 6] = in[
p + 6] * coeffs[6];
530 out[
p + 7] = in[
p + 7] * coeffs[7];
531 out[
p + 8] = in[
p + 8] * coeffs[8];
532 out[
p + 9] = in[
p + 9] * coeffs[9];
533 out[
p + 10] = in[
p + 10] * coeffs[10];
534 out[
p + 11] = in[
p + 11] * coeffs[11];
538 const size_t p = row_start +
i;
539 out[
p] = in[
p] * coeffs[
i % 12];
546 const int cfa_x = roi_out->
x & 1;
548 for(
int j = 0; j <
height; j++)
550 const int offset_j = j + roi_out->
y;
551 const size_t row_start = (size_t)j *
width;
552 const int id0 =
FC(offset_j, cfa_x + 0, filters);
553 const int id1 =
FC(offset_j, cfa_x + 1, filters);
554 const float coeff0 = d_coeffs[id0];
555 const float coeff1 = d_coeffs[id1];
560 const size_t p = row_start +
i;
561 out[
p + 0] = in[
p + 0] * coeff0;
562 out[
p + 1] = in[
p + 1] * coeff1;
566 const size_t p = row_start +
i;
567 out[
p] = in[
p] * d_coeffs[
FC(offset_j,
i + roi_out->
x, filters)];
574 const size_t ch =
piece->dsc_in.channels;
575 const size_t npixels = (size_t)roi_out->
width * roi_out->
height;
580 for(
size_t k = 0;
k < npixels;
k++)
582 const size_t p = 4 *
k;
583 out[
p + 0] = in[
p + 0] *
d->coeffs[0];
584 out[
p + 1] = in[
p + 1] *
d->coeffs[1];
585 out[
p + 2] = in[
p + 2] *
d->coeffs[2];
586 out[
p + 3] = in[
p + 3];
593 for(
size_t k = 0;
k <
ch * npixels;
k +=
ch)
595 for(ptrdiff_t c = 0; c < 3; c++)
597 const size_t p =
k + c;
598 out[
p] = in[
p] *
d->coeffs[c];
620 const uint32_t filters =
piece->dsc_in.filters;
621 cl_mem dev_coeffs = NULL;
622 cl_mem dev_xtrans = NULL;
662 if(err != CL_SUCCESS)
goto error;
684 const gboolean
state = current_state && !mono;
685 dt_iop_fmt_log(self,
"force_enable: class=%s mono=%d current=%d -> %d",
687 mono, current_state,
state);
727 d->coeffs[0] =
p->red;
728 d->coeffs[1] =
p->green;
729 d->coeffs[2] =
p->blue;
734 d->coeffs[3] = g2_usable ?
p->g2 :
p->green;
735 dt_iop_fmt_log(self,
"commit: class=%s matrix_supported=%d coeffs=[%.4f %.4f %.4f %.4f] g2_in=%.4f g2_usable=%d -> enabled=%d",
738 d->coeffs[0],
d->coeffs[1],
d->coeffs[2],
d->coeffs[3],
p->g2, g2_usable,
piece->enabled);
743 piece->dsc_out.temperature.enabled = 1;
744 for(
int k = 0;
k < 4;
k++)
746 piece->dsc_out.temperature.coeffs[
k] =
d->coeffs[
k];
747 piece->dsc_out.processed_maximum[
k] =
piece->dsc_in.processed_maximum[
k] *
d->coeffs[
k];
756 gboolean is_D65 =
TRUE;
757 for(
int c = 0; c < 3; c++)
758 if(
d->coeffs[c] != (
float)
g->daylight_wb[c]) is_D65 =
FALSE;
780 const gboolean color_rgb =
g->colored_sliders &&
792 if(!color_rgb)
return;
811 if(!
g->blackbody_is_confusing)
831 const double white[3] = {
832 1.0/
g->daylight_wb[0],
833 1.0/
g->daylight_wb[1],
834 1.0/
g->daylight_wb[2],
857 if(gtk_widget_get_visible(GTK_WIDGET(
g->scale_r)))
859 gtk_widget_queue_draw(GTK_WIDGET(
g->scale_r));
860 gtk_widget_queue_draw(GTK_WIDGET(
g->scale_g));
861 gtk_widget_queue_draw(GTK_WIDGET(
g->scale_b));
874 if(!
g->colored_sliders)
return;
878 const int blackbody_is_confusing =
g->blackbody_is_confusing;
884 const double dayligh_white[3] = {
885 1.0/
g->daylight_wb[0],
886 1.0/
g->daylight_wb[1],
887 1.0/
g->daylight_wb[2],
890 double cur_coeffs[4] = {0.0};
891 temp2mul(self, cur_temp, 1.0, cur_coeffs);
892 const double cur_white[3] = {
898 if(blackbody_is_confusing)
908 double coeffs_tint[4];
909 temp2mul(self, K, cur_tint, coeffs_K);
910 temp2mul(self, cur_temp, tint, coeffs_tint);
911 coeffs_K[0] /= coeffs_K[1];
912 coeffs_K[2] /= coeffs_K[1];
913 coeffs_K[3] /= coeffs_K[1];
915 coeffs_tint[0] /= coeffs_tint[1];
916 coeffs_tint[2] /= coeffs_tint[1];
917 coeffs_tint[3] /= coeffs_tint[1];
918 coeffs_tint[1] = 1.0;
920 dt_aligned_pixel_t sRGB_K = { dayligh_white[0]*coeffs_K[0], dayligh_white[1]*coeffs_K[1],
921 dayligh_white[2]*coeffs_K[2] };
922 dt_aligned_pixel_t sRGB_tint = {cur_white[0]*coeffs_tint[0], cur_white[1]*coeffs_tint[1],
923 cur_white[2]*coeffs_tint[2]};
924 const float maxsRGB_K = fmaxf(fmaxf(sRGB_K[0], sRGB_K[1]), sRGB_K[2]);
925 const float maxsRGB_tint = fmaxf(fmaxf(sRGB_tint[0], sRGB_tint[1]),sRGB_tint[2]);
931 sRGB_K[
ch] = fmaxf(sRGB_K[
ch] / maxsRGB_K, 0.f);
934 if(maxsRGB_tint > 1.f)
938 sRGB_tint[
ch] = fmaxf(sRGB_tint[
ch] / maxsRGB_tint, 0.f);
961 dt_XYZ_to_Rec709_D65(XYZ_temp, sRGB_temp);
962 dt_XYZ_to_Rec709_D65(XYZ_tint, sRGB_tint);
964 const float maxsRGB_temp = fmaxf(fmaxf(sRGB_temp[0], sRGB_temp[1]), sRGB_temp[2]);
965 const float maxsRGB_tint = fmaxf(fmaxf(sRGB_tint[0], sRGB_tint[1]), sRGB_tint[2]);
967 if(maxsRGB_temp > 1.f)
971 sRGB_temp[
ch] = fmaxf(sRGB_temp[
ch] / maxsRGB_temp, 0.f);
975 if(maxsRGB_tint > 1.f)
979 sRGB_tint[
ch] = fmaxf(sRGB_tint[
ch] / maxsRGB_tint, 0.f);
988 if(gtk_widget_get_visible(GTK_WIDGET(
g->scale_k)))
990 gtk_widget_queue_draw(GTK_WIDGET(
g->scale_k));
991 gtk_widget_queue_draw(GTK_WIDGET(
g->scale_tint));
1029 g->as_shot_wb[0] =
g->as_shot_wb[1] =
g->as_shot_wb[2] =
g->as_shot_wb[3] = 1.f;
1031 g->as_shot_wb[0] /=
g->as_shot_wb[1];
1032 g->as_shot_wb[2] /=
g->as_shot_wb[1];
1033 g->as_shot_wb[3] /=
g->as_shot_wb[1];
1034 g->as_shot_wb[1] = 1.0;
1037 float TempK_def, tint_def;
1038 mul2temp(self,
d, &TempK_def, &tint_def);
1049 memset(
g->preset_num, 0,
sizeof(
g->preset_num));
1067 gboolean found =
FALSE;
1070 if(
p->red ==
g->as_shot_wb[0] &&
p->green ==
g->as_shot_wb[1] &&
p->blue ==
g->as_shot_wb[2])
1078 if((
p->red == (
float)
g->daylight_wb[0]) &&
1079 (
p->green == (
float)
g->daylight_wb[1]) &&
1080 (
p->blue == (
float)
g->daylight_wb[2]))
1090 if (!found || isnan(
g->mod_temp))
1092 g->mod_temp = tempK;
1097 gtk_widget_set_visible(
g->buttonbar,
g->button_bar_visible);
1110 gtk_widget_queue_draw(self->
gui->
widget);
1131 bwb[0] = mul[0] / mul[1];
1132 bwb[2] = mul[2] / mul[1];
1134 bwb[3] = mul[3] / mul[1];
1149 const double RGB_to_XYZ[3][4] = { { 0.4124564, 0.3575761, 0.1804375, 0 },
1150 { 0.2126729, 0.7151522, 0.0721750, 0 },
1151 { 0.0193339, 0.1191920, 0.9503041, 0 } };
1154 const double XYZ_to_RGB[4][3] = { { 3.2404542, -1.5371385, -0.4985314 },
1155 { -0.9692660, 1.8760108, 0.0415560 },
1156 { 0.0556434, -0.2040259, 1.0572252 },
1164 memcpy(
g->XYZ_to_CAM, XYZ_to_RGB,
sizeof(
g->XYZ_to_CAM));
1165 memcpy(
g->CAM_to_XYZ, RGB_to_XYZ,
sizeof(
g->CAM_to_XYZ));
1171 g->XYZ_to_CAM,
g->CAM_to_XYZ))
1173 const char *camera =
module->dev->image_storage.camera_makermodel;
1174 dt_control_alert(_(
"Camera data missing"), _(
"color matrix not found for image"), camera);
1180 const dt_image_t *img = &
module->dev->image_storage;
1186 for(
int k = 0; ok &&
k < num_coeffs;
k++)
1208 dt_control_alert(_(
"Camera data missing"), _(
"failed to read camera white balance information!"),
1211 fprintf(stderr,
"[temperature] failed to read camera white balance information from `%s'!\n",
1219 for(
int c = 0; c < 4; c++) coeffs[c] = bwb[c];
1245 const gboolean is_modern =
1248 module->default_enabled = 0;
1249 module->hide_enable_button = 0;
1256 module->hide_enable_button = 1;
1264 module->default_enabled = 1;
1268 double coeffs[4] = { 0 };
1271 d->red = coeffs[0]/coeffs[1];
1272 d->blue = coeffs[2]/coeffs[1];
1273 d->g2 = coeffs[3]/coeffs[1];
1280 d->red = coeffs[0]/coeffs[1];
1281 d->blue = coeffs[2]/coeffs[1];
1282 d->g2 = coeffs[3]/coeffs[1];
1288 dt_iop_fmt_log(module,
"reload_defaults: class=%s matrix_supported=%d mono=%d modern=%d -> default_enabled=%d coeffs=[%.4f %.4f %.4f %.4f]",
1290 is_raw, monochrome, is_modern, module->
default_enabled,
d->red,
d->green,
d->blue,
d->g2);
1309 const int program = 2;
1339 temp2mul(self,
g->mod_temp,
g->mod_tint,
g->mod_coeff);
1342 g->mod_coeff[0] /=
g->mod_coeff[1];
1343 g->mod_coeff[2] /=
g->mod_coeff[1];
1344 g->mod_coeff[3] /=
g->mod_coeff[1];
1345 g->mod_coeff[1] = 1.0;
1382 if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton)))
1389 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(togglebutton),
TRUE);
1406 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->btn_user), pos ==
DT_IOP_TEMP_USER);
1407 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->btn_d65), pos ==
DT_IOP_TEMP_D65);
1417 if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->colorpicker)))
1420 g_signal_emit_by_name(G_OBJECT(
g->colorpicker),
"button-press-event", NULL, &ret_val);
1433 if(self->
gui->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->
gui->
off), 1);
1439 TempK =
g->mod_temp;
1477 p->green = grayrgb[1] > 0.001f ? 1.0f / grayrgb[1] : 1.0f;
1478 p->red = fmaxf(0.0f, fminf(8.0f, (grayrgb[0] > 0.001f ? 1.0f / grayrgb[0] : 1.0f) /
p->green));
1479 p->blue = fmaxf(0.0f, fminf(8.0f, (grayrgb[2] > 0.001f ? 1.0f / grayrgb[2] : 1.0f) /
p->green));
1480 p->g2 = fmaxf(0.0f, fminf(8.0f, (grayrgb[3] > 0.001f ? 1.0f / grayrgb[3] : 1.0f) /
p->green));
1511 gtk_widget_set_tooltip_text(
g->scale_r, _(
"green channel coefficient"));
1513 gtk_widget_set_tooltip_text(
g->scale_g, _(
"magenta channel coefficient"));
1515 gtk_widget_set_tooltip_text(
g->scale_b, _(
"cyan channel coefficient"));
1517 gtk_widget_set_tooltip_text(
g->scale_g2, _(
"yellow channel coefficient"));
1519 gtk_box_reorder_child(GTK_BOX(
g->cs.container),
g->scale_b, 0);
1520 gtk_box_reorder_child(GTK_BOX(
g->cs.container),
g->scale_g2, 1);
1521 gtk_box_reorder_child(GTK_BOX(
g->cs.container),
g->scale_g, 2);
1522 gtk_box_reorder_child(GTK_BOX(
g->cs.container),
g->scale_r, 3);
1527 gtk_widget_set_tooltip_text(
g->scale_r, _(
"red channel coefficient"));
1529 gtk_widget_set_tooltip_text(
g->scale_g, _(
"green channel coefficient"));
1531 gtk_widget_set_tooltip_text(
g->scale_b, _(
"blue channel coefficient"));
1533 gtk_widget_set_tooltip_text(
g->scale_g2, _(
"emerald channel coefficient"));
1535 gtk_box_reorder_child(GTK_BOX(
g->cs.container),
g->scale_r, 0);
1536 gtk_box_reorder_child(GTK_BOX(
g->cs.container),
g->scale_g, 1);
1537 gtk_box_reorder_child(GTK_BOX(
g->cs.container),
g->scale_b, 2);
1538 gtk_box_reorder_child(GTK_BOX(
g->cs.container),
g->scale_g2, 3);
1548 g->colored_sliders =
TRUE;
1549 g->blackbody_is_confusing =
FALSE;
1551 const int feedback =
TRUE;
1552 g->button_bar_visible =
TRUE;
1554 GtkBox *box_enabled = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL,
DT_GUI_BOX_SPACING));
1559 gtk_widget_set_tooltip_text(
g->btn_asshot, _(
"set white balance to as shot"));
1568 gtk_widget_set_tooltip_text(
g->colorpicker, _(
"set white balance to detected from area"));
1573 gtk_widget_set_tooltip_text(
g->btn_user, _(
"set white balance to user modified"));
1579 gtk_widget_set_tooltip_text(
g->btn_d65, _(
"set white balance to camera reference point\nin most cases it should be D65"));
1583 gtk_box_pack_end(GTK_BOX(
g->buttonbar),
g->btn_d65,
TRUE,
TRUE, 0);
1584 gtk_box_pack_end(GTK_BOX(
g->buttonbar),
g->btn_user,
TRUE,
TRUE, 0);
1585 gtk_box_pack_end(GTK_BOX(
g->buttonbar),
g->colorpicker,
TRUE,
TRUE, 0);
1586 gtk_box_pack_end(GTK_BOX(
g->buttonbar),
g->btn_asshot,
TRUE,
TRUE, 0);
1587 gtk_box_pack_start(box_enabled,
g->buttonbar,
TRUE,
TRUE, 0);
1591 gtk_widget_set_tooltip_text(
g->presets, _(
"choose white balance setting"));
1592 gtk_box_pack_start(box_enabled,
g->presets,
TRUE,
TRUE, 0);
1595 for(
int k = 0;
k < 4;
k++)
1597 g->daylight_wb[
k] = 1.0;
1598 g->as_shot_wb[
k] = 1.f;
1601 GtkWidget *temp_label_box = gtk_event_box_new();
1603 gtk_widget_set_tooltip_text(
g->temp_label, _(
"click to cycle color mode on sliders"));
1604 gtk_container_add(GTK_CONTAINER(temp_label_box),
g->temp_label);
1606 gtk_box_pack_start(box_enabled, temp_label_box,
TRUE,
TRUE, 0);
1610 0, 5000.0, 0, feedback);
1613 gtk_widget_set_tooltip_text(
g->scale_k, _(
"color temperature (in Kelvin)"));
1614 gtk_box_pack_start(box_enabled,
g->scale_k,
TRUE,
TRUE, 0);
1617 0, 1.0, 3, feedback);
1619 gtk_widget_set_tooltip_text(
g->scale_tint, _(
"color tint of the image, from magenta (value < 1) to green (value > 1)"));
1620 gtk_box_pack_start(box_enabled,
g->scale_tint,
TRUE,
TRUE, 0);
1624 "plugins/darkroom/temperature/expand_coefficients",
1625 _(
"channel coefficients"),
1626 GTK_BOX(box_enabled), GTK_PACK_END);
1628 self->
gui->
widget = GTK_WIDGET(
g->cs.container);
1639 gtk_widget_set_no_show_all(
g->scale_g2,
TRUE);
1641 g_signal_connect(G_OBJECT(
g->scale_k),
"value-changed", G_CALLBACK(
temp_tint_callback), self);
1642 g_signal_connect(G_OBJECT(
g->scale_tint),
"value-changed", G_CALLBACK(
temp_tint_callback), self);
1650 GtkWidget *label_disabled = gtk_label_new(_(
"white balance disabled for camera"));
1651 gtk_widget_set_halign(label_disabled, GTK_ALIGN_START);
1652 gtk_label_set_ellipsize(GTK_LABEL(label_disabled), PANGO_ELLIPSIZE_END);
1654 gtk_stack_add_named(GTK_STACK(self->
gui->
widget), GTK_WIDGET(box_enabled),
"enabled");
1655 gtk_stack_add_named(GTK_STACK(self->
gui->
widget), label_disabled,
"disabled");
static void error(char *msg)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
void dt_bauhaus_combobox_clear(GtkWidget *widget)
void dt_bauhaus_slider_clear_stops(GtkWidget *widget)
void dt_bauhaus_slider_set_default(GtkWidget *widget, float def)
void dt_bauhaus_slider_set_stop(GtkWidget *widget, float stop, float r, float g, float b)
float dt_bauhaus_slider_get(GtkWidget *widget)
GtkWidget * dt_bauhaus_slider_new_with_range_and_feedback(dt_bauhaus_t *bh, dt_gui_module_t *self, float min, float max, float step, float defval, int digits, int feedback)
void dt_bauhaus_slider_set_feedback(GtkWidget *widget, int feedback)
int dt_bauhaus_combobox_get(GtkWidget *widget)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
float dt_bauhaus_slider_get_hard_max(GtkWidget *widget)
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
#define DT_BAUHAUS_SLIDER_MAX_STOPS
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
void dt_gui_new_collapsible_section(dt_gui_collapsible_section_t *cs, const char *confname, const char *label, GtkBox *parent, GtkPackType pack)
Create a collapsible section and pack it into the parent box.
void dt_gui_update_collapsible_section(dt_gui_collapsible_section_t *cs)
void dt_iop_color_picker_reset(dt_iop_module_t *module, gboolean keep)
GtkWidget * dt_color_picker_new_with_cst(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w, const dt_iop_colorspace_type_t cst)
__DT_CLONE_TARGETS__ int dt_colorspaces_conversion_matrices_rgb(const float *adobe_XYZ_to_CAM, double(*out_RGB_to_CAM)[3], double(*out_CAM_to_RGB)[4], const float *embedded_matrix, double *mul)
Compute the sRGB->camera and camera->sRGB matrices, and the default white balance multipliers.
int dt_colorspaces_conversion_matrices_xyz(const float adobe_XYZ_to_CAM[4][3], float in_XYZ_to_CAM[9], double XYZ_to_CAM[4][3], double CAM_to_XYZ[3][4])
Compute the XYZ->camera and camera->XYZ matrices for an image.
The colour-profile module's API: which profiles exist, and how to apply one.
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
static dt_aligned_pixel_t XYZ
const dt_colormatrix_t dt_aligned_pixel_t out
static const dt_colormatrix_t M
gboolean dt_conf_is_equal(const char *name, const char *value)
gboolean dt_image_is_matrix_correction_supported(const dt_image_t *img)
dt_image_pipe_class_t dt_image_pipe_class(const dt_image_t *img)
const char * dt_image_pipe_class_name(const dt_image_pipe_class_t klass)
gboolean dt_image_is_monochrome(const dt_image_t *img)
gboolean dt_image_needs_rawprepare(const dt_image_t *img)
void dt_control_alert(const char *title, const char *message, const char *item)
Tell the user something that must not go unseen: what it says stays true after a toast would have fad...
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
static int FCxtrans(const int row, const int col, global const unsigned char(*const xtrans)[6])
static int FC(const int row, const int col, const unsigned int filters)
#define dt_dev_add_history_item(dev, module, enable, redraw)
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
#define FILTERS_ARE_CYGM(filters)
const char ** dt_iop_set_description(dt_iop_module_t *module, const char *main_text, const char *purpose, const char *input, const char *process, const char *output)
@ DT_REQUEST_COLORPICK_OFF
#define dt_iop_fmt_log(module, fmt,...)
Debug helper to trace a module's input-format-driven decisions on the -d pipe channel (DT_DEBUG_PIPE)...
GtkWidget * dt_iop_togglebutton_new(dt_iop_module_t *self, const char *section, const gchar *label, const gchar *ctrl_label, GCallback callback, gboolean local, guint accel_key, GdkModifierType mods, DTGTKCairoPaintIconFunc paint, GtkWidget *box)
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
static dt_iop_gui_data_t * dt_iop_gui_data(const struct dt_iop_module_t *m)
The module's GUI data blob, NULL-safe for headless callers: IOP process() implementations read it for...
#define IOP_GUI_ALLOC(module)
static float kernel(const float *x, const float *y)
struct dt_iop_tonecurve_params_t preset
GtkWidget * dt_ui_section_label_new(const gchar *str)
static const dt_dev_pixelpipe_t * pipe
static const dt_dev_pixelpipe_t const dt_dev_pixelpipe_iop_t * piece
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
static void * dt_calloc_align(size_t size)
dt_alloc_align() followed by a zero fill.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
int dt_opencl_create_kernel(const int prog, const char *name)
void * dt_opencl_copy_host_to_device_constant(const int devid, const size_t size, void *host)
void dt_opencl_free_kernel(const int kernel)
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
void dt_opencl_release_mem_object(cl_mem mem)
#define __OMP_PARALLEL_FOR__(...)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
const float uint32_t state[4]
dt_aligned_pixel_t wb_coeffs
struct dt_develop_t::@14 proxy
gboolean camera_missing_sample
char camera_makermodel[128]
float d65_color_matrix[9]
float adobe_XYZ_to_CAM[4][3]
char filename[DT_MAX_FILENAME_LEN]
dt_aligned_pixel_t wb_coeffs
dt_iop_gui_data_t * gui_data
dt_iop_global_data_t * data
dt_dev_request_colorpick_flags_t request_color_pick
int32_t hide_enable_button
dt_iop_params_t * default_params
struct dt_iop_module_gui_t * gui
struct dt_develop_t * dev
dt_iop_global_data_t * global_data
dt_aligned_pixel_t picked_color_min
dt_aligned_pixel_t picked_color_max
dt_aligned_pixel_t picked_color
Region of interest passed through the pixelpipe.
int kernel_whitebalance_1f_xtrans
int kernel_whitebalance_4f
int kernel_whitebalance_1f
dt_gui_collapsible_section_t cs
GtkWidget * balance_label
int blackbody_is_confusing
gboolean button_bar_visible
#define __DT_CLONE_TARGETS__
#define DT_IOP_HIGHEST_TINT
static cmsCIEXYZ temperature_tint_to_XYZ(double TempK, double tint)
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static double spd_blackbody(unsigned long int wavelength, double TempK)
const char ** description(struct dt_iop_module_t *self)
static cmsCIEXYZ spectrum_to_XYZ(double TempK, spd I)
__DT_CLONE_TARGETS__ int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
static cmsCIEXYZ mul2xyz(dt_iop_module_t *self, const dt_iop_temperature_params_t *p)
static void _publish_wb_coeffs(dt_iop_module_t *self, const dt_iop_temperature_params_t *p)
void reload_defaults(dt_iop_module_t *module)
static double spd_daylight(unsigned long int wavelength, double TempK)
#define INITIALBLACKBODYTEMPERATURE
static void temp2mul(dt_iop_module_t *self, double TempK, double tint, double mul[4])
#define DT_IOP_LOWEST_TINT
void color_rgb_sliders(struct dt_iop_module_t *self)
static void gui_sliders_update(struct dt_iop_module_t *self)
static void XYZ_to_temperature(cmsCIEXYZ XYZ, float *TempK, float *tint)
#define DT_IOP_LOWEST_TEMPERATURE
static int ignore_missing_wb(dt_image_t *img)
static int calculate_bogus_daylight_wb(dt_iop_module_t *module, double bwb[4])
static cmsCIEXYZ temperature_to_XYZ(double TempK)
static void _temp_array_from_params(double a[4], const dt_iop_temperature_params_t *p)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void output_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
void gui_reset(struct dt_iop_module_t *self)
#define DT_IOP_HIGHEST_TEMPERATURE
static gboolean btn_toggled(GtkWidget *togglebutton, GdkEventButton *event, dt_iop_module_t *self)
void gui_update(struct dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
void gui_init(struct dt_iop_module_t *self)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
#define DT_IOP_TEMP_AS_SHOT
void cleanup_global(dt_iop_module_so_t *module)
void commit_proxy(dt_iop_module_t *self)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
static void _temp_params_from_array(dt_iop_temperature_params_t *p, const double a[4])
static void mul2temp(dt_iop_module_t *self, dt_iop_temperature_params_t *p, float *TempK, float *tint)
static void temp_tint_callback(GtkWidget *slider, dt_iop_module_t *self)
void gui_cleanup(struct dt_iop_module_t *self)
typedef double((*spd)(unsigned long int wavelength, double TempK))
gboolean force_enable(struct dt_iop_module_t *self, const gboolean current_state)
static void find_coeffs(dt_iop_module_t *module, double coeffs[4])
#define DT_IOP_NUM_OF_STD_TEMP_PRESETS
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void prepare_matrices(dt_iop_module_t *module)
void init_global(dt_iop_module_so_t *module)
int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
static void xyz2mul(dt_iop_module_t *self, cmsCIEXYZ xyz, double mul[4])
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void color_temptint_sliders(struct dt_iop_module_t *self)
static void preset_tune_callback(GtkWidget *widget, dt_iop_module_t *self)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
static int _max(int a, int b)
Telling the user something happened.