178 return _(
"color balance (legacy)");
183 return _(
"lift gamma gain|cdl|color grading|contrast|saturation|hue");
189 _(
"corrective or creative"),
190 _(
"linear, Lab, scene-referred"),
191 _(
"non-linear, RGB"),
192 _(
"non-linear, Lab, scene-referred"));
219 const int new_version)
221 if(old_version == 1 && new_version == 3)
223 typedef struct dt_iop_colorbalance_params_v1_t
226 } dt_iop_colorbalance_params_v1_t;
228 dt_iop_colorbalance_params_v1_t *o = (dt_iop_colorbalance_params_v1_t *)old_params;
236 n->lift[
i] = o->lift[
i];
237 n->gamma[
i] = o->gamma[
i];
238 n->gain[
i] = o->gain[
i];
244 if(old_version == 2 && new_version == 3)
246 typedef struct dt_iop_colorbalance_params_v2_t
250 float saturation, contrast, grey;
251 } dt_iop_colorbalance_params_v2_t;
253 dt_iop_colorbalance_params_v2_t *o = (dt_iop_colorbalance_params_v2_t *)old_params;
261 n->lift[
i] = o->lift[
i];
262 n->gamma[
i] = o->gamma[
i];
263 n->gain[
i] = o->gain[
i];
266 n->contrast = o->contrast;
267 n->saturation = o->saturation;
268 n->contrast = o->contrast;
277 const char *pi,
const int version,
const char *bpi,
const int blendop_version)
311 add_preset(self, _(
"split-toning teal-orange (2nd instance)"),
312 "gz02eJxjZGBg8HhYZX99cYN9kkCDfdCOOnsGhgZ7ruvN9m8CK+yXFNTaz5w50z5PqBku9u9/PVjNv//9jqfP+NgDAHs0HIc=", 3,
313 "gz05eJxjZWBgYGUAgRNODFDAzszAxMBQ5cwI4Tow4AUNdkBsD8E3gGwue9x8uB6q8s+c8bEF8Z9Y9Nnt2f3bbluCN03tg/EBIBckVg==", 8);
314 add_preset(self, _(
"split-toning teal-orange (1st instance)"),
315 "gz02eJxjZACBBvugHXX2E3fU219f3GAP4n/TqLFvfd1oL8HZaH/2jI/9prn1cLHUtDSwGgaGCY7//tfbAwBRixpm", 3,
316 "gz04eJxjZWBgYGUAgRNODFDApgwiq5wZIVyHD4E7bBnwggZ7CIYBRiBbBA8fXT1l/P5DX21i+pnA/Pfv8uw6OzzIMq9I5rgtSH//4wii1AMASbIlcw==", 8);
319 "gz02eJxjZACBBntN5gb7op/19u5AGsSX3dFgr+jYaL+vttb+0NcM+1Pnq+3XyFTZr/rYBJZPS0sD0hMcQDQA29kXSQ==", 3,
320 "gz11eJxjYGBgkGAAgRNODGiAEV0AJ2iwh+CRxQcA5qIZBA==", 8);
322 add_preset(self, _(
"similar to Kodak Portra"),
323 "gz02eJxjZACBBnsQfh3YYK8VU28P43s8rLKP6W+yP/Q1w36deyMYLymoBcsZGxcDaQGHs2d87AGnphWu", 3,
324 "gz11eJxjYGBgkGAAgRNODGiAEV0AJ2iwh+CRxQcA5qIZBA==", 8);
327 "gz02eJxjZACBBvvrixvsrXIb7IN21NnD+CA2iOa6nmxvZFxsX15ebp+e1gaWNwbyGRgEHNLS0uwBE7wWhw==", 3,
328 "gz11eJxjYGBgkGAAgRNODGiAEV0AJ2iwh+CRxQcA5qIZBA==", 8);
331 "gz02eJxjZACBBvvrixvsrXIb7IN21NnD+CA2iG59HWhvZFxsX15ebp+e1gaWT0tLA9ICDrNmRtoDACjOF7c=", 3,
332 "gz11eJxjYGBgkGAAgRNODGiAEV0AJ2iwh+CRxQcA5qIZBA==", 8);
335static inline float CDL(
float x,
float slope,
float offset,
float power)
338 out = slope *
x + offset;
339 out = (
out <= 0.0f) ? 0.0f : powf(
out, power);
357 const float contrast = (
d->contrast != 0.0f) ? 1.0f /
d->contrast : 1000000.0f,
358 grey =
d->grey / 100.0f;
361 const int run_contrast = (
d->contrast == 1.0f) ? 0 : 1;
362 const int run_saturation = (
d->saturation == 1.0f) ? 0: 1;
363 const int run_saturation_out = (
d->saturation_out == 1.0f) ? 0: 1;
376 gamma_inv = { (gamma[0] != 0.0) ? 1.0 / gamma[0] : 1000000.0,
377 (gamma[1] != 0.0) ? 1.0 / gamma[1] : 1000000.0,
378 (gamma[2] != 0.0) ? 1.0 / gamma[2] : 1000000.0 };
382 float *in = ((
float *)ivoid) +
k;
395 for(
int c = 0; c < 3; c++)
398 rgb[c] = (((
rgb[c] - 1.0f) * lift[c]) + 1.0f) * gain[c];
399 rgb[c] = (
rgb[c] < 0.0f) ? 0.0f : powf(
rgb[c], gamma_inv[c]);
420 gamma_inv = { (gamma[0] != 0.0) ? 1.0 / gamma[0] : 1000000.0,
421 (gamma[1] != 0.0) ? 1.0 / gamma[1] : 1000000.0,
422 (gamma[2] != 0.0) ? 1.0 / gamma[2] : 1000000.0 };
426 float *in = ((
float *)ivoid) +
k;
441 for(
int c = 0; c < 3; c++)
444 if (run_saturation)
rgb[c] = luma +
d->saturation * (
rgb[c] - luma);
447 rgb[c] = (
rgb[c] <= 0.0f) ? 0.0f : powf(
rgb[c], 1.0f/2.2f);
450 rgb[c] = (((
rgb[c] - 1.0f) * lift[c]) + 1.0f) * gain[c];
451 rgb[c] = (
rgb[c] <= 0.0f) ? 0.0f : powf(
rgb[c], gamma_inv[c] * 2.2f);
455 if (run_saturation_out)
459 for(
int c = 0; c < 3; c++)
rgb[c] = luma +
d->saturation_out * (
rgb[c] - luma);
463 if (run_contrast)
for(
int c = 0; c < 3; c++)
rgb[c] = (
rgb[c] <= 0.0f) ? 0.0f : powf(
rgb[c] / grey, contrast) * grey;
487 float *in = ((
float *)ivoid) +
k;
502 for(
int c = 0; c < 3; c++)
505 if (run_saturation)
rgb[c] = luma +
d->saturation * (
rgb[c] - luma);
508 rgb[c] =
CDL(
rgb[c], gain[c], lift[c], gamma[c]);
512 if (run_saturation_out)
516 for(
int c = 0; c < 3; c++)
rgb[c] = luma +
d->saturation_out * (
rgb[c] - luma);
520 if (run_contrast)
for(
int c = 0; c < 3; c++)
rgb[c] = (
rgb[c] <= 0.0f) ? 0.0f : powf(
rgb[c] / grey, contrast) * grey;
544 const int devid = pipe->
devid;
559 gamma_inv[4] = { (gamma[0] != 0.0f) ? 1.0f / gamma[0] : 1000000.0f,
560 (gamma[1] != 0.0f) ? 1.0f / gamma[1] : 1000000.0f,
561 (gamma[2] != 0.0f) ? 1.0f / gamma[2] : 1000000.0f, 0.0f },
565 contrast = (
d->contrast != 0.0f) ? 1.0f /
d->contrast : 1000000.0f,
566 grey =
d->grey / 100.0f,
567 saturation =
d->saturation;
580 if(err != CL_SUCCESS)
goto error;
593 gamma_inv[4] = { (gamma[0] != 0.0f) ? 1.0f / gamma[0] : 1000000.0f,
594 (gamma[1] != 0.0f) ? 1.0f / gamma[1] : 1000000.0f,
595 (gamma[2] != 0.0f) ? 1.0f / gamma[2] : 1000000.0f, 0.0f },
599 contrast = (
d->contrast != 0.0f) ? 1.0f /
d->contrast : 1000000.0f,
600 grey =
d->grey / 100.0f,
601 saturation =
d->saturation,
602 saturation_out =
d->saturation_out;
616 if(err != CL_SUCCESS)
goto error;
635 contrast = (
d->contrast != 0.0f) ? 1.0f /
d->contrast : 1000000.0f,
636 grey =
d->grey / 100.0f,
637 saturation =
d->saturation,
638 saturation_out =
d->saturation_out;
652 if(err != CL_SUCCESS)
goto error;
674 gtk_widget_queue_draw(GTK_WIDGET(slider));
714 gtk_widget_queue_draw(GTK_WIDGET(sat));
720 gtk_widget_queue_draw(GTK_WIDGET(sat));
764 for(
int c = 0; c < 3; c++)
766 rgb[c] =
CDL(
rgb[c], gain[c], lift[c], 2.0f - gamma[c]);
767 rgb[c] = CLAMP(
rgb[c], 0.0f, 1.0f);
772 p->grey =
XYZ[1] * 100.0f;
793 for(
int c = 0; c < 3; ++c)
g->color_patches_lift[c] =
RGB[c];
797 for(
int c = 0; c < 3; ++c)
804 for(
int c = 0; c < 3; ++c)
RGB[c] = powf(
XYZ[1], 1.0f/(2.0f -
p->gamma[c+1])) -
RGB[c] *
p->gain[c+1];
832 for(
int c = 0; c < 3; ++c)
g->color_patches_gamma[c] =
RGB[c];
836 for(
int c = 0; c < 3; ++c)
843 for(
int c = 0; c < 3; ++c)
RGB[c] = logf(
XYZ[1])/ logf(
RGB[c] *
p->gain[c + 1] +
p->lift[c + 1] - 1.0f);
871 for(
int c = 0; c < 3; c++)
g->color_patches_gain[c] =
RGB[c];
875 for(
int c = 0; c < 3; ++c)
882 for(
int c = 0; c < 3; ++c)
RGB[c] = (powf(
XYZ[1], 1.0f/(2.0f -
p->gamma[c+1])) -
p->lift[c+1] + 1.0f) /
MAX(
RGB[c], 0.000001f);
991 for(
int c = 0; c < 3; c++)
g->color_patches_lift[c] =
RGB[c];
996 for(
int c = 0; c < 3; c++)
g->color_patches_gamma[c] =
RGB[c];
1001 for(
int c = 0; c < 3; c++)
g->color_patches_gain[c] =
RGB[c];
1013 for (
int c = 0; c < 3; ++c)
1047 for (
int runs = 0 ; runs < 1000 ; ++runs)
1050 for (
int c = 0; c < 3; ++c) RGB_gain[c] = CLAMP((powf(greys[
GAIN], 1.0f / (2.0f - RGB_gamma[c])) - RGB_lift[c]) /
MAX(samples_gain[c], 0.000001f), 0.75f, 1.25f);
1052 for (
int c = 0; c < 3; ++c) RGB_lift[c] = CLAMP(powf(greys[
LIFT], 1.0f / (2.0f - RGB_gamma[c])) - samples_lift[c] * RGB_gain[c], -0.025f, 0.025f);
1054 for (
int c = 0; c < 3; ++c) RGB_gamma[c] = 2.0f - CLAMP(logf(
MAX(greys[
GAMMA], 0.000001f)) / logf(
MAX(RGB_gain[c] * samples_gamma[c] + RGB_lift[c], 0.000001f)), 0.75f, 1.25f);
1125 for (
int runs = 0 ; runs < 100 ; ++runs)
1144 if (picker ==
g->hue_lift)
1146 else if(picker ==
g->hue_gamma)
1148 else if(picker ==
g->hue_gain)
1150 else if(picker ==
g->lift_factor)
1152 else if(picker ==
g->gamma_factor)
1154 else if(picker ==
g->gain_factor)
1156 else if(picker ==
g->grey)
1158 else if(picker ==
g->auto_luma)
1160 else if(picker ==
g->auto_color)
1163 fprintf(stderr,
"[colorbalance] unknown color picker\n");
1170 const int program = 8;
1233 d->lift[
i] =
p->lift[
i];
1234 d->gamma[
i] =
p->gamma[
i];
1235 d->gain[
i] =
p->gain[
i];
1269 d->saturation =
p->saturation;
1270 d->saturation_out =
p->saturation_out;
1271 d->contrast =
p->contrast;
1291 gtk_widget_set_visible(
g->master_box, mode !=
LEGACY);
1294 control_mode ==
RGBL ?
"RGBL" :
1295 control_mode ==
BOTH ?
"BOTH" :
"HSL");
1296 gboolean show_rgbl = (control_mode ==
RGBL) || (control_mode ==
BOTH);
1297 gboolean show_hsl = (control_mode ==
HSL) || (control_mode ==
BOTH);
1299 gtk_widget_set_visible(
g->lift_r, show_rgbl);
1300 gtk_widget_set_visible(
g->lift_g, show_rgbl);
1301 gtk_widget_set_visible(
g->lift_b, show_rgbl);
1302 gtk_widget_set_visible(
g->gamma_r, show_rgbl);
1303 gtk_widget_set_visible(
g->gamma_g, show_rgbl);
1304 gtk_widget_set_visible(
g->gamma_b, show_rgbl);
1305 gtk_widget_set_visible(
g->gain_r, show_rgbl);
1306 gtk_widget_set_visible(
g->gain_g, show_rgbl);
1307 gtk_widget_set_visible(
g->gain_b, show_rgbl);
1309 gtk_widget_set_visible(
g->hue_lift, show_hsl);
1310 gtk_widget_set_visible(
g->sat_lift, show_hsl);
1311 gtk_widget_set_visible(
g->hue_gamma, show_hsl);
1312 gtk_widget_set_visible(
g->sat_gamma, show_hsl);
1313 gtk_widget_set_visible(
g->hue_gain, show_hsl);
1314 gtk_widget_set_visible(
g->sat_gain, show_hsl);
1360 if(
IS_NULL_PTR(w) || w ==
g->lift_r || w ==
g->lift_g || w ==
g->lift_b)
1362 if(
IS_NULL_PTR(w) || w ==
g->gamma_r || w ==
g->gamma_g || w ==
g->gamma_b)
1364 if(
IS_NULL_PTR(w) || w ==
g->gain_r || w ==
g->gain_g || w ==
g->gain_b)
1381#ifdef SHOW_COLOR_WHEELS
1385 if(gtk_widget_get_state_flags(widget) & GTK_STATE_FLAG_SELECTED) flt_bg = 0.6;
1386 float flt_dark = flt_bg / 1.5, flt_light = flt_bg * 1.5;
1388 uint32_t bg = ((255 << 24) | ((
int)floor(flt_bg * 255 + 0.5) << 16) | ((
int)floor(flt_bg * 255 + 0.5) << 8)
1389 | (
int)floor(flt_bg * 255 + 0.5));
1395 uint32_t light = ((255 << 24) | ((
int)floor(flt_light * 255 + 0.5) << 16)
1396 | ((
int)floor(flt_light * 255 + 0.5) << 8) | (
int)floor(flt_light * 255 + 0.5));
1398 GtkAllocation allocation;
1399 gtk_widget_get_allocation(widget, &allocation);
1400 int width = allocation.width,
height = allocation.height;
1403 double center_x = (float)
width / 2.0, center_y = (
float)
height / 2.0;
1405 double r_outside = diameter / 2.0, r_inside = r_outside * 0.87;
1406 double r_outside_2 = r_outside * r_outside, r_inside_2 = r_inside * r_inside;
1409 cairo_set_source_rgb(cr, flt_bg, flt_bg, flt_bg);
1413 gint stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24,
width);
1414 guint32 *buf = (guint32 *)malloc(
sizeof(guint32) *
height * stride / 4);
1416 for(
int y = 0; y <
height; y++)
1418 guint32 *
p = buf + y *
width;
1420 double dy = -(y + 0.5 - center_y);
1424 double dx =
x + 0.5 - center_x;
1425 double dist = dx * dx + dy * dy;
1426 if(dist < r_inside_2 || dist > r_outside_2)
1429 if((abs(dx) < 1 && abs(dy) < 3) || (abs(dx) < 3 && abs(dy) < 1)) col = light;
1434 double angle = atan2(dy, dx) - M_PI_2;
1435 if(angle < 0.0) angle += 2.0 *
M_PI;
1437 double hue = angle / (2.0 *
M_PI);
1442 *
p++ = (((int)floor(
rgb[0] * 255 + 0.5) << 16) | ((
int)floor(
rgb[1] * 255 + 0.5) << 8)
1443 | (
int)floor(
rgb[2] * 255 + 0.5));
1447 cairo_surface_t *source
1448 = cairo_image_surface_create_for_data((
unsigned char *)buf, CAIRO_FORMAT_RGB24,
width,
height, stride);
1450 cairo_set_source_surface(cr, source, 0.0, 0.0);
1455 float line_width = 1;
1456 cairo_set_line_width(cr, line_width);
1458 cairo_set_source_rgb(cr, flt_bg, flt_bg, flt_bg);
1460 cairo_arc(cr, center_x, center_y, r_outside, 0.0, 2.0 *
M_PI);
1462 cairo_arc(cr, center_x, center_y, r_inside, 0.0, 2.0 *
M_PI);
1465 cairo_set_source_rgb(cr, flt_dark, flt_dark, flt_dark);
1467 cairo_arc(cr, center_x, center_y, r_outside,
M_PI, 1.5 *
M_PI);
1469 cairo_arc(cr, center_x, center_y, r_inside, 0.0, 0.5 *
M_PI);
1472 cairo_set_source_rgb(cr, flt_light, flt_light, flt_light);
1474 cairo_arc(cr, center_x, center_y, r_outside, 0.0, 0.5 *
M_PI);
1476 cairo_arc(cr, center_x, center_y, r_inside,
M_PI, 1.5 *
M_PI);
1480 double r = 255 / 255.0,
g = 155 / 255.0,
b = 40 / 255.0;
1483 gtk_rgb_to_hsv(
r,
g, b, &h, &s, &
v);
1486 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.7);
1488 cairo_translate(cr, center_x, center_y);
1489 cairo_rotate(cr, h * 2.0 *
M_PI - M_PI_2);
1491 cairo_arc(cr, r_inside *
v, 0.0, 3.0, 0, 2.0 *
M_PI);
1496 cairo_surface_destroy(source);
1507 GtkWidget *old_container = gtk_bin_get_child(GTK_BIN(
g->main_box));
1509 for(
int i=0;
i<3;
i++)
1511 g_object_ref(G_OBJECT(
g->blocks[
i]));
1512 if(old_container) gtk_container_remove(GTK_CONTAINER(old_container),
g->blocks[
i]);
1515 if(old_container) gtk_widget_destroy(old_container);
1517 const gchar *long_label[]
1518 = { N_(
"shadows: lift / offset"),
1519 N_(
"mid-tones: gamma / power"),
1520 N_(
"highlights: gain / slope") };
1525 for(
int i=0;
i<3;
i++)
1528 gtk_label_set_text(GTK_LABEL(
g->main_label), _(long_label[0]));
1532 gtk_container_add(GTK_CONTAINER(new_container), label);
1533 if(old_container) gtk_widget_show(label);
1536 gtk_container_add(GTK_CONTAINER(new_container),
g->blocks[
i]);
1541 for(
int i=0;
i<3;
i++) g_object_unref(G_OBJECT(
g->blocks[
i]));
1543 gtk_container_add(GTK_CONTAINER(
g->main_box), new_container);
1544 if(old_container) gtk_widget_show(new_container);
1552#define HSL_CALLBACK(which) \
1553static void which##_callback(GtkWidget *slider, gpointer user_data) \
1555 dt_iop_module_t *self = (dt_iop_module_t *)user_data; \
1556 dt_iop_colorbalance_params_t *p = (dt_iop_colorbalance_params_t *)self->params; \
1557 dt_iop_colorbalance_gui_data_t *g = (dt_iop_colorbalance_gui_data_t *)self->gui_data; \
1559 if(darktable.gui->reset) return; \
1561 dt_iop_color_picker_reset(self, TRUE); \
1563 float hsl[3] = {dt_bauhaus_slider_get(g->hue_##which) / 360.0f, \
1564 dt_bauhaus_slider_get(g->sat_##which) / 100.0f, \
1567 if(slider == g->hue_##which) \
1568 update_saturation_slider_color(g->sat_##which, hsl[0]); \
1569 set_RGB_sliders(g->which##_r, g->which##_g, g->which##_b, hsl, p->which, p->mode); \
1570 dt_dev_add_history_item(darktable.develop, self, TRUE, TRUE); \
1593 gtk_widget_set_tooltip_text(
g->mode, _(
"color-grading mapping method"));
1601 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(
g->controls),
TRUE,
TRUE, 0);
1602 gtk_widget_set_tooltip_text(
g->controls, _(
"color-grading mapping method"));
1603 g_signal_connect(G_OBJECT(
g->controls),
"value-changed", G_CALLBACK(
controls_callback), self);
1607 !g_strcmp0(mode,
"BOTH") ?
BOTH :
HSL);
1617 gtk_widget_set_tooltip_text(
g->saturation, _(
"saturation correction before the color balance"));
1623 gtk_widget_set_tooltip_text(
g->saturation_out, _(
"saturation correction after the color balance"));
1628 gtk_widget_set_tooltip_text(
g->grey, _(
"adjust to match a neutral tone"));
1636 gtk_widget_set_tooltip_text(
g->contrast, _(
"contrast"));
1638#ifdef SHOW_COLOR_WHEELS
1640 gtk_box_pack_start(GTK_BOX(self->widget), hbox,
FALSE,
FALSE, 0);
1643 gtk_box_pack_start(GTK_BOX(hbox), area,
TRUE,
TRUE, 0);
1648 g_signal_connect(G_OBJECT(area),
"draw", G_CALLBACK(dt_iop_area_draw), self);
1657 gtk_box_pack_start(GTK_BOX(hbox), area,
TRUE,
TRUE, 0);
1662 g_signal_connect(G_OBJECT(area),
"draw", G_CALLBACK(dt_iop_area_draw), self);
1671 gtk_box_pack_start(GTK_BOX(hbox), area,
TRUE,
TRUE, 0);
1676 g_signal_connect(G_OBJECT(area),
"draw", G_CALLBACK(dt_iop_area_draw), self);
1686 gtk_widget_set_tooltip_text(
g->main_label, _(
"click to cycle layout"));
1687 GtkWidget *main_label_box = gtk_event_box_new();
1688 gtk_container_add(GTK_CONTAINER(main_label_box),
g->main_label);
1689 g_signal_connect(G_OBJECT(main_label_box),
"button-release-event", G_CALLBACK(
_cycle_layout_callback), self);
1691 g->main_box = gtk_event_box_new();
1693 char field_name[10];
1695#define ADD_CHANNEL(which, section, c, n, N, text, span) \
1696 sprintf(field_name, "%s[%d]", #which, CHANNEL_##N); \
1697 g->which##_##c = dt_bauhaus_slider_from_params(self, field_name); \
1698 dt_bauhaus_slider_set_soft_range(g->which##_##c, -span+1.0, span+1.0); \
1699 dt_bauhaus_slider_set_digits(g->which##_##c, 5); \
1700 dt_bauhaus_slider_set_offset(g->which##_##c, -1.0); \
1701 dt_bauhaus_slider_set_feedback(g->which##_##c, 0); \
1702 gtk_widget_set_tooltip_text(g->which##_##c, _(text[CHANNEL_##N])); \
1703 dt_bauhaus_widget_set_label(g->which##_##c, #n); \
1705#define ADD_BLOCK(blk, which, section, text, span, satspan) \
1706 g->blocks[blk] = self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING); \
1708 sprintf(field_name, "%s[%d]", #which, CHANNEL_FACTOR); \
1709 g->which##_factor = dt_color_picker_new(self, DT_COLOR_PICKER_AREA, \
1710 dt_bauhaus_slider_from_params(self, field_name)); \
1711 dt_bauhaus_slider_set_soft_range(g->which##_factor, -span+1.0, span+1.0); \
1712 dt_bauhaus_slider_set_digits(g->which##_factor, 4); \
1713 dt_bauhaus_slider_set_factor(g->which##_factor, 100.0); \
1714 dt_bauhaus_slider_set_offset(g->which##_factor, - 100.0); \
1715 dt_bauhaus_slider_set_format(g->which##_factor,"%"); \
1716 dt_bauhaus_slider_set_feedback(g->which##_factor, 0); \
1717 dt_bauhaus_slider_set_stop(g->which##_factor, 0.0, 0.0, 0.0, 0.0); \
1718 dt_bauhaus_slider_set_stop(g->which##_factor, 1.0, 1.0, 1.0, 1.0); \
1719 gtk_widget_set_tooltip_text(g->which##_factor, _(text[CHANNEL_FACTOR])); \
1720 dt_bauhaus_widget_set_label(g->which##_factor, N_("factor")); \
1722 g->hue_##which = dt_color_picker_new(self, DT_COLOR_PICKER_AREA, \
1723 dt_bauhaus_slider_new_with_range_and_feedback(darktable.bauhaus, DT_GUI_MODULE(self), \
1724 0.0f, 360.0f, 0, 0.0f, 2, 0)); \
1725 dt_bauhaus_widget_set_label(g->hue_##which, N_("hue")); \
1726 dt_bauhaus_slider_set_format(g->hue_##which, "\302\260"); \
1727 dt_bauhaus_slider_set_stop(g->hue_##which, 0.0f, 1.0f, 0.0f, 0.0f); \
1728 dt_bauhaus_slider_set_stop(g->hue_##which, 0.166f, 1.0f, 1.0f, 0.0f); \
1729 dt_bauhaus_slider_set_stop(g->hue_##which, 0.322f, 0.0f, 1.0f, 0.0f); \
1730 dt_bauhaus_slider_set_stop(g->hue_##which, 0.498f, 0.0f, 1.0f, 1.0f); \
1731 dt_bauhaus_slider_set_stop(g->hue_##which, 0.664f, 0.0f, 0.0f, 1.0f); \
1732 dt_bauhaus_slider_set_stop(g->hue_##which, 0.830f, 1.0f, 0.0f, 1.0f); \
1733 dt_bauhaus_slider_set_stop(g->hue_##which, 1.0f, 1.0f, 0.0f, 0.0f); \
1734 gtk_widget_set_tooltip_text(g->hue_##which, _("select the hue")); \
1735 g_signal_connect(G_OBJECT(g->hue_##which), "value-changed", \
1736 G_CALLBACK(which##_callback), self); \
1737 gtk_box_pack_start(GTK_BOX(self->widget), g->hue_##which, TRUE, TRUE, 0); \
1739 g->sat_##which = dt_bauhaus_slider_new_with_range_and_feedback(darktable.bauhaus, DT_GUI_MODULE(self), \
1740 0.0f, 100.0f, 0, 0.0f, 2, 0); \
1741 dt_bauhaus_slider_set_soft_max(g->sat_##which, satspan); \
1742 dt_bauhaus_widget_set_label(g->sat_##which, N_("saturation")); \
1743 dt_bauhaus_slider_set_format(g->sat_##which, "%"); \
1744 dt_bauhaus_slider_set_stop(g->sat_##which, 0.0f, 0.2f, 0.2f, 0.2f); \
1745 dt_bauhaus_slider_set_stop(g->sat_##which, 1.0f, 1.0f, 1.0f, 1.0f); \
1746 gtk_widget_set_tooltip_text(g->sat_##which, _("select the saturation")); \
1747 g_signal_connect(G_OBJECT(g->sat_##which), "value-changed", \
1748 G_CALLBACK(which##_callback), self); \
1749 gtk_box_pack_start(GTK_BOX(self->widget), g->sat_##which, TRUE, TRUE, 0); \
1751 ADD_CHANNEL(which, section, r, red, RED, text, span) \
1752 dt_bauhaus_slider_set_stop(g->which##_r, 0.0, 0.0, 1.0, 1.0); \
1753 dt_bauhaus_slider_set_stop(g->which##_r, 0.5, 1.0, 1.0, 1.0); \
1754 dt_bauhaus_slider_set_stop(g->which##_r, 1.0, 1.0, 0.0, 0.0); \
1755 ADD_CHANNEL(which, section, g, green, GREEN, text, span) \
1756 dt_bauhaus_slider_set_stop(g->which##_g, 0.0, 1.0, 0.0, 1.0); \
1757 dt_bauhaus_slider_set_stop(g->which##_g, 0.5, 1.0, 1.0, 1.0); \
1758 dt_bauhaus_slider_set_stop(g->which##_g, 1.0, 0.0, 1.0, 0.0); \
1759 ADD_CHANNEL(which, section, b, blue, BLUE, text, span) \
1760 dt_bauhaus_slider_set_stop(g->which##_b, 0.0, 1.0, 1.0, 0.0); \
1761 dt_bauhaus_slider_set_stop(g->which##_b, 0.5, 1.0, 1.0, 1.0); \
1762 dt_bauhaus_slider_set_stop(g->which##_b, 1.0, 0.0, 0.0, 1.0); \
1764 static const char *lift_messages[]
1765 = { N_(
"factor of lift/offset"),
1766 N_(
"factor of red for lift/offset"),
1767 N_(
"factor of green for lift/offset"),
1768 N_(
"factor of blue for lift/offset") };
1770 static const char *gamma_messages[]
1771 = { N_(
"factor of gamma/power"),
1772 N_(
"factor of red for gamma/power"),
1773 N_(
"factor of green for gamma/power"),
1774 N_(
"factor of blue for gamma/power") };
1776 static const char *gain_messages[]
1777 = { N_(
"factor of gain/slope"),
1778 N_(
"factor of red for gain/slope"),
1779 N_(
"factor of green for gain/slope"),
1780 N_(
"factor of blue for gain/slope") };
1782 ADD_BLOCK(0, lift, N_(
"shadows"), lift_messages, 0.05f, 5.0f)
1783 ADD_BLOCK(1, gamma, N_(
"mid-tones"), gamma_messages, 0.5f, 20.0f)
1784 ADD_BLOCK(2, gain, N_(
"highlights"), gain_messages, 0.5f, 25.0f)
1787 g->optimizer_box = self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL,
DT_GUI_BOX_SPACING);
1794 gtk_widget_set_tooltip_text(
g->auto_luma, _(
"fit the whole histogram and center the average luma"));
1795 gtk_box_pack_start(GTK_BOX(self->widget),
g->auto_luma,
FALSE,
FALSE, 0);
1800 gtk_widget_set_tooltip_text(
g->auto_color, _(
"optimize the RGB curves to remove color casts"));
1801 gtk_box_pack_start(GTK_BOX(self->widget),
g->auto_color,
FALSE,
FALSE, 0);
1806 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(mode_box),
TRUE,
TRUE, 0);
1807 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(
g->master_box),
TRUE,
TRUE, 0);
1808 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(main_label_box),
TRUE,
TRUE, 0);
1809 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(
g->main_box),
TRUE,
TRUE, 0);
1810 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(
g->optimizer_box),
TRUE,
TRUE, 0);
static double dist(double x1, double y1, double x2, double y2)
static void error(char *msg)
void dt_bauhaus_slider_set_soft_range(GtkWidget *widget, float soft_min, float soft_max)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
void dt_bauhaus_slider_set_stop(GtkWidget *widget, float stop, float r, float g, float b)
int dt_bauhaus_combobox_get(GtkWidget *widget)
void dt_bauhaus_slider_set_offset(GtkWidget *widget, float offset)
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)
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
void dt_bauhaus_slider_set_factor(GtkWidget *widget, float factor)
int dt_develop_blend_legacy_params_from_so(dt_iop_module_so_t *module_so, const void *const old_params, const int old_version, void *new_params, const int new_version, const int length)
int dt_develop_blend_version(void)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
void dt_iop_color_picker_reset(dt_iop_module_t *module, gboolean keep)
GtkWidget * dt_color_picker_new(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w)
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)
const char ** description(struct dt_iop_module_t *self)
static void _check_tuner_picker_labels(dt_iop_module_t *self)
__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)
void gui_reset(dt_iop_module_t *self)
static void apply_autocolor(dt_iop_module_t *self)
static void apply_lift_auto(dt_iop_module_t *self)
static void add_preset(dt_iop_module_so_t *self, const char *name, const char *pi, const int version, const char *bpi, const int blendop_version)
static void apply_gain_neutralize(dt_iop_module_t *self)
void gui_update(dt_iop_module_t *self)
static void apply_autoluma(dt_iop_module_t *self)
static void _configure_slider_blocks(gpointer instance, dt_iop_module_t *self)
static float CDL(float x, float slope, float offset, float power)
static void apply_gamma_auto(dt_iop_module_t *self)
static void _cycle_layout_callback(GtkWidget *label, GdkEventButton *event, dt_iop_module_t *self)
dt_iop_colorbalance_mode_t
static void set_HSL_sliders(GtkWidget *hue, GtkWidget *sat, float RGB[4])
static void apply_gain_auto(dt_iop_module_t *self)
static void apply_gamma_neutralize(dt_iop_module_t *self)
void gui_init(dt_iop_module_t *self)
static void apply_lift_neutralize(dt_iop_module_t *self)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
#define HSL_CALLBACK(which)
static void set_RGB_sliders(GtkWidget *R, GtkWidget *G, GtkWidget *B, float hsl[3], float *p, int mode)
void cleanup_global(dt_iop_module_so_t *module)
struct dt_iop_colorbalance_global_data_t dt_iop_colorbalance_global_data_t
void cleanup_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
void input_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
#define ADD_BLOCK(blk, which, section, text, span, satspan)
static void update_saturation_slider_color(GtkWidget *slider, float hue)
void gui_cleanup(struct dt_iop_module_t *self)
void init_presets(dt_iop_module_so_t *self)
void init_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void set_visible_widgets(dt_iop_colorbalance_gui_data_t *g)
static void apply_autogrey(dt_iop_module_t *self)
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 controls_callback(GtkWidget *combo, dt_iop_module_t *self)
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
void rgb2hsl(const dt_aligned_pixel_t rgb, float *h, float *s, float *l)
void hsl2rgb(dt_aligned_pixel_t rgb, float h, float s, float l)
dt_prophotorgb_to_XYZ(rgb, XYZ)
static dt_aligned_pixel_t rgb
dt_XYZ_to_sRGB(XYZ, result)
dt_XYZ_to_prophotorgb(XYZ, rgb)
static dt_aligned_pixel_t XYZ
const dt_colormatrix_t dt_aligned_pixel_t out
static dt_aligned_pixel_t RGB
gchar * dt_conf_get_string(const char *name)
void dt_conf_set_string(const char *name, const char *val)
const char * dt_conf_get_string_const(const char *name)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_free_align(ptr)
static void * dt_calloc_align(size_t size)
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR_SIMD__(...)
#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_dev_add_history_item(dev, module, enable, redraw)
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
GtkWidget * dtgtk_drawing_area_new_with_aspect_ratio(double aspect)
unsigned char * dt_exif_xmp_decode(const char *input, const int len, int *output_len)
static GtkWidget * dt_ui_section_label_new(const gchar *str)
#define DT_GUI_BOX_SPACING
void dt_gui_presets_add_with_blendop(const char *name, dt_dev_operation_t op, const int32_t version, const void *params, const int32_t params_size, const void *blend_params, const int32_t enabled)
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)
@ IOP_FLAGS_INCLUDE_IN_STYLES
@ IOP_FLAGS_SUPPORTS_BLENDING
#define IOP_GUI_ALLOC(module)
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
GtkWidget * dt_bauhaus_combobox_from_params(dt_iop_module_t *self, const char *param)
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
float dt_aligned_pixel_t[4]
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_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)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
@ DT_SIGNAL_PREFERENCES_CHANGE
This signal is raised after preferences have been changed no parameters no return.
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
struct _GtkWidget GtkWidget
struct dt_gui_gtk_t * gui
struct dt_control_signal_t * signals
struct dt_bauhaus_t * bauhaus
struct dt_develop_t * develop
struct dt_iop_module_t *void * data
dt_iop_buffer_type_t datatype
dt_iop_colorbalance_mode_t mode
float gamma[CHANNEL_SIZE]
int kernel_colorbalance_cdl
int kernel_colorbalance_lgg
_colorbalance_patch_t color_patches_flags[LEVELS]
_colorbalance_patch_t luma_patches_flags[LEVELS]
float color_patches_gamma[3]
float luma_patches[LEVELS]
GtkWidget * saturation_out
float color_patches_gain[3]
GtkWidget * optimizer_box
float color_patches_lift[3]
dt_iop_colorbalance_mode_t mode
float gamma[CHANNEL_SIZE]
GModule *dt_dev_operation_t op
dt_iop_global_data_t * data
dt_iop_params_t * default_params
dt_iop_gui_data_t * gui_data
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.