179 return _(
"color balance (legacy)");
184 return _(
"lift gamma gain|cdl|color grading|contrast|saturation|hue");
190 _(
"corrective or creative"),
191 _(
"linear, Lab, scene-referred"),
192 _(
"non-linear, RGB"),
193 _(
"non-linear, Lab, scene-referred"));
220 const int new_version)
222 if(old_version == 1 && new_version == 3)
224 typedef struct dt_iop_colorbalance_params_v1_t
227 } dt_iop_colorbalance_params_v1_t;
229 dt_iop_colorbalance_params_v1_t *o = (dt_iop_colorbalance_params_v1_t *)old_params;
237 n->lift[
i] = o->lift[
i];
238 n->gamma[
i] = o->gamma[
i];
239 n->gain[
i] = o->gain[
i];
245 if(old_version == 2 && new_version == 3)
247 typedef struct dt_iop_colorbalance_params_v2_t
251 float saturation, contrast, grey;
252 } dt_iop_colorbalance_params_v2_t;
254 dt_iop_colorbalance_params_v2_t *o = (dt_iop_colorbalance_params_v2_t *)old_params;
262 n->lift[
i] = o->lift[
i];
263 n->gamma[
i] = o->gamma[
i];
264 n->gain[
i] = o->gain[
i];
267 n->contrast = o->contrast;
268 n->saturation = o->saturation;
269 n->contrast = o->contrast;
278 const char *pi,
const int version,
const char *bpi,
const int blendop_version)
312 add_preset(self, _(
"split-toning teal-orange (2nd instance)"),
313 "gz02eJxjZGBg8HhYZX99cYN9kkCDfdCOOnsGhgZ7ruvN9m8CK+yXFNTaz5w50z5PqBku9u9/PVjNv//9jqfP+NgDAHs0HIc=", 3,
314 "gz05eJxjZWBgYGUAgRNODFDAzszAxMBQ5cwI4Tow4AUNdkBsD8E3gGwue9x8uB6q8s+c8bEF8Z9Y9Nnt2f3bbluCN03tg/EBIBckVg==", 8);
315 add_preset(self, _(
"split-toning teal-orange (1st instance)"),
316 "gz02eJxjZACBBvugHXX2E3fU219f3GAP4n/TqLFvfd1oL8HZaH/2jI/9prn1cLHUtDSwGgaGCY7//tfbAwBRixpm", 3,
317 "gz04eJxjZWBgYGUAgRNODFDApgwiq5wZIVyHD4E7bBnwggZ7CIYBRiBbBA8fXT1l/P5DX21i+pnA/Pfv8uw6OzzIMq9I5rgtSH//4wii1AMASbIlcw==", 8);
320 "gz02eJxjZACBBntN5gb7op/19u5AGsSX3dFgr+jYaL+vttb+0NcM+1Pnq+3XyFTZr/rYBJZPS0sD0hMcQDQA29kXSQ==", 3,
321 "gz11eJxjYGBgkGAAgRNODGiAEV0AJ2iwh+CRxQcA5qIZBA==", 8);
323 add_preset(self, _(
"similar to Kodak Portra"),
324 "gz02eJxjZACBBnsQfh3YYK8VU28P43s8rLKP6W+yP/Q1w36deyMYLymoBcsZGxcDaQGHs2d87AGnphWu", 3,
325 "gz11eJxjYGBgkGAAgRNODGiAEV0AJ2iwh+CRxQcA5qIZBA==", 8);
328 "gz02eJxjZACBBvvrixvsrXIb7IN21NnD+CA2iOa6nmxvZFxsX15ebp+e1gaWNwbyGRgEHNLS0uwBE7wWhw==", 3,
329 "gz11eJxjYGBgkGAAgRNODGiAEV0AJ2iwh+CRxQcA5qIZBA==", 8);
332 "gz02eJxjZACBBvvrixvsrXIb7IN21NnD+CA2iG59HWhvZFxsX15ebp+e1gaWT0tLA9ICDrNmRtoDACjOF7c=", 3,
333 "gz11eJxjYGBgkGAAgRNODGiAEV0AJ2iwh+CRxQcA5qIZBA==", 8);
336static inline float CDL(
float x,
float slope,
float offset,
float power)
339 out = slope *
x + offset;
340 out = (
out <= 0.0f) ? 0.0f : powf(
out, power);
358 const float contrast = (
d->contrast != 0.0f) ? 1.0f /
d->contrast : 1000000.0f,
359 grey =
d->grey / 100.0f;
362 const int run_contrast = (
d->contrast == 1.0f) ? 0 : 1;
363 const int run_saturation = (
d->saturation == 1.0f) ? 0: 1;
364 const int run_saturation_out = (
d->saturation_out == 1.0f) ? 0: 1;
377 gamma_inv = { (gamma[0] != 0.0) ? 1.0 / gamma[0] : 1000000.0,
378 (gamma[1] != 0.0) ? 1.0 / gamma[1] : 1000000.0,
379 (gamma[2] != 0.0) ? 1.0 / gamma[2] : 1000000.0 };
383 float *in = ((
float *)ivoid) +
k;
396 for(
int c = 0; c < 3; c++)
399 rgb[c] = (((
rgb[c] - 1.0f) * lift[c]) + 1.0f) * gain[c];
400 rgb[c] = (
rgb[c] < 0.0f) ? 0.0f : powf(
rgb[c], gamma_inv[c]);
421 gamma_inv = { (gamma[0] != 0.0) ? 1.0 / gamma[0] : 1000000.0,
422 (gamma[1] != 0.0) ? 1.0 / gamma[1] : 1000000.0,
423 (gamma[2] != 0.0) ? 1.0 / gamma[2] : 1000000.0 };
427 float *in = ((
float *)ivoid) +
k;
442 for(
int c = 0; c < 3; c++)
445 if (run_saturation)
rgb[c] = luma +
d->saturation * (
rgb[c] - luma);
448 rgb[c] = (
rgb[c] <= 0.0f) ? 0.0f : powf(
rgb[c], 1.0f/2.2f);
451 rgb[c] = (((
rgb[c] - 1.0f) * lift[c]) + 1.0f) * gain[c];
452 rgb[c] = (
rgb[c] <= 0.0f) ? 0.0f : powf(
rgb[c], gamma_inv[c] * 2.2f);
456 if (run_saturation_out)
460 for(
int c = 0; c < 3; c++)
rgb[c] = luma +
d->saturation_out * (
rgb[c] - luma);
464 if (run_contrast)
for(
int c = 0; c < 3; c++)
rgb[c] = (
rgb[c] <= 0.0f) ? 0.0f : powf(
rgb[c] / grey, contrast) * grey;
488 float *in = ((
float *)ivoid) +
k;
503 for(
int c = 0; c < 3; c++)
506 if (run_saturation)
rgb[c] = luma +
d->saturation * (
rgb[c] - luma);
509 rgb[c] =
CDL(
rgb[c], gain[c], lift[c], gamma[c]);
513 if (run_saturation_out)
517 for(
int c = 0; c < 3; c++)
rgb[c] = luma +
d->saturation_out * (
rgb[c] - luma);
521 if (run_contrast)
for(
int c = 0; c < 3; c++)
rgb[c] = (
rgb[c] <= 0.0f) ? 0.0f : powf(
rgb[c] / grey, contrast) * grey;
545 const int devid = pipe->
devid;
560 gamma_inv[4] = { (gamma[0] != 0.0f) ? 1.0f / gamma[0] : 1000000.0f,
561 (gamma[1] != 0.0f) ? 1.0f / gamma[1] : 1000000.0f,
562 (gamma[2] != 0.0f) ? 1.0f / gamma[2] : 1000000.0f, 0.0f },
566 contrast = (
d->contrast != 0.0f) ? 1.0f /
d->contrast : 1000000.0f,
567 grey =
d->grey / 100.0f,
568 saturation =
d->saturation;
581 if(err != CL_SUCCESS)
goto error;
594 gamma_inv[4] = { (gamma[0] != 0.0f) ? 1.0f / gamma[0] : 1000000.0f,
595 (gamma[1] != 0.0f) ? 1.0f / gamma[1] : 1000000.0f,
596 (gamma[2] != 0.0f) ? 1.0f / gamma[2] : 1000000.0f, 0.0f },
600 contrast = (
d->contrast != 0.0f) ? 1.0f /
d->contrast : 1000000.0f,
601 grey =
d->grey / 100.0f,
602 saturation =
d->saturation,
603 saturation_out =
d->saturation_out;
617 if(err != CL_SUCCESS)
goto error;
636 contrast = (
d->contrast != 0.0f) ? 1.0f /
d->contrast : 1000000.0f,
637 grey =
d->grey / 100.0f,
638 saturation =
d->saturation,
639 saturation_out =
d->saturation_out;
653 if(err != CL_SUCCESS)
goto error;
675 gtk_widget_queue_draw(GTK_WIDGET(slider));
715 gtk_widget_queue_draw(GTK_WIDGET(sat));
721 gtk_widget_queue_draw(GTK_WIDGET(sat));
765 for(
int c = 0; c < 3; c++)
767 rgb[c] =
CDL(
rgb[c], gain[c], lift[c], 2.0f - gamma[c]);
768 rgb[c] = CLAMP(
rgb[c], 0.0f, 1.0f);
773 p->grey =
XYZ[1] * 100.0f;
794 for(
int c = 0; c < 3; ++c)
g->color_patches_lift[c] =
RGB[c];
798 for(
int c = 0; c < 3; ++c)
805 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];
833 for(
int c = 0; c < 3; ++c)
g->color_patches_gamma[c] =
RGB[c];
837 for(
int c = 0; c < 3; ++c)
844 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);
872 for(
int c = 0; c < 3; c++)
g->color_patches_gain[c] =
RGB[c];
876 for(
int c = 0; c < 3; ++c)
883 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);
992 for(
int c = 0; c < 3; c++)
g->color_patches_lift[c] =
RGB[c];
997 for(
int c = 0; c < 3; c++)
g->color_patches_gamma[c] =
RGB[c];
1002 for(
int c = 0; c < 3; c++)
g->color_patches_gain[c] =
RGB[c];
1014 for (
int c = 0; c < 3; ++c)
1048 for (
int runs = 0 ; runs < 1000 ; ++runs)
1051 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);
1053 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);
1055 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);
1126 for (
int runs = 0 ; runs < 100 ; ++runs)
1145 if (picker ==
g->hue_lift)
1147 else if(picker ==
g->hue_gamma)
1149 else if(picker ==
g->hue_gain)
1151 else if(picker ==
g->lift_factor)
1153 else if(picker ==
g->gamma_factor)
1155 else if(picker ==
g->gain_factor)
1157 else if(picker ==
g->grey)
1159 else if(picker ==
g->auto_luma)
1161 else if(picker ==
g->auto_color)
1164 fprintf(stderr,
"[colorbalance] unknown color picker\n");
1171 const int program = 8;
1234 d->lift[
i] =
p->lift[
i];
1235 d->gamma[
i] =
p->gamma[
i];
1236 d->gain[
i] =
p->gain[
i];
1270 d->saturation =
p->saturation;
1271 d->saturation_out =
p->saturation_out;
1272 d->contrast =
p->contrast;
1292 gtk_widget_set_visible(
g->master_box, mode !=
LEGACY);
1295 control_mode ==
RGBL ?
"RGBL" :
1296 control_mode ==
BOTH ?
"BOTH" :
"HSL");
1297 gboolean show_rgbl = (control_mode ==
RGBL) || (control_mode ==
BOTH);
1298 gboolean show_hsl = (control_mode ==
HSL) || (control_mode ==
BOTH);
1300 gtk_widget_set_visible(
g->lift_r, show_rgbl);
1301 gtk_widget_set_visible(
g->lift_g, show_rgbl);
1302 gtk_widget_set_visible(
g->lift_b, show_rgbl);
1303 gtk_widget_set_visible(
g->gamma_r, show_rgbl);
1304 gtk_widget_set_visible(
g->gamma_g, show_rgbl);
1305 gtk_widget_set_visible(
g->gamma_b, show_rgbl);
1306 gtk_widget_set_visible(
g->gain_r, show_rgbl);
1307 gtk_widget_set_visible(
g->gain_g, show_rgbl);
1308 gtk_widget_set_visible(
g->gain_b, show_rgbl);
1310 gtk_widget_set_visible(
g->hue_lift, show_hsl);
1311 gtk_widget_set_visible(
g->sat_lift, show_hsl);
1312 gtk_widget_set_visible(
g->hue_gamma, show_hsl);
1313 gtk_widget_set_visible(
g->sat_gamma, show_hsl);
1314 gtk_widget_set_visible(
g->hue_gain, show_hsl);
1315 gtk_widget_set_visible(
g->sat_gain, show_hsl);
1361 if(
IS_NULL_PTR(w) || w ==
g->lift_r || w ==
g->lift_g || w ==
g->lift_b)
1363 if(
IS_NULL_PTR(w) || w ==
g->gamma_r || w ==
g->gamma_g || w ==
g->gamma_b)
1365 if(
IS_NULL_PTR(w) || w ==
g->gain_r || w ==
g->gain_g || w ==
g->gain_b)
1382#ifdef SHOW_COLOR_WHEELS
1386 if(gtk_widget_get_state_flags(widget) & GTK_STATE_FLAG_SELECTED) flt_bg = 0.6;
1387 float flt_dark = flt_bg / 1.5, flt_light = flt_bg * 1.5;
1389 uint32_t bg = ((255 << 24) | ((
int)floor(flt_bg * 255 + 0.5) << 16) | ((
int)floor(flt_bg * 255 + 0.5) << 8)
1390 | (
int)floor(flt_bg * 255 + 0.5));
1396 uint32_t light = ((255 << 24) | ((
int)floor(flt_light * 255 + 0.5) << 16)
1397 | ((
int)floor(flt_light * 255 + 0.5) << 8) | (
int)floor(flt_light * 255 + 0.5));
1399 GtkAllocation allocation;
1400 gtk_widget_get_allocation(widget, &allocation);
1401 int width = allocation.width,
height = allocation.height;
1404 double center_x = (float)
width / 2.0, center_y = (
float)
height / 2.0;
1406 double r_outside = diameter / 2.0, r_inside = r_outside * 0.87;
1407 double r_outside_2 = r_outside * r_outside, r_inside_2 = r_inside * r_inside;
1410 cairo_set_source_rgb(cr, flt_bg, flt_bg, flt_bg);
1414 gint stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24,
width);
1415 guint32 *buf = (guint32 *)malloc(
sizeof(guint32) *
height * stride / 4);
1417 for(
int y = 0; y <
height; y++)
1419 guint32 *
p = buf + y *
width;
1421 double dy = -(y + 0.5 - center_y);
1425 double dx =
x + 0.5 - center_x;
1426 double dist = dx * dx + dy * dy;
1427 if(dist < r_inside_2 || dist > r_outside_2)
1430 if((abs(dx) < 1 && abs(dy) < 3) || (abs(dx) < 3 && abs(dy) < 1)) col = light;
1435 double angle = atan2(dy, dx) - M_PI_2;
1436 if(angle < 0.0) angle += 2.0 *
M_PI;
1438 double hue = angle / (2.0 *
M_PI);
1443 *
p++ = (((int)floor(
rgb[0] * 255 + 0.5) << 16) | ((
int)floor(
rgb[1] * 255 + 0.5) << 8)
1444 | (
int)floor(
rgb[2] * 255 + 0.5));
1448 cairo_surface_t *source
1449 = cairo_image_surface_create_for_data((
unsigned char *)buf, CAIRO_FORMAT_RGB24,
width,
height, stride);
1451 cairo_set_source_surface(cr, source, 0.0, 0.0);
1456 float line_width = 1;
1457 cairo_set_line_width(cr, line_width);
1459 cairo_set_source_rgb(cr, flt_bg, flt_bg, flt_bg);
1461 cairo_arc(cr, center_x, center_y, r_outside, 0.0, 2.0 *
M_PI);
1463 cairo_arc(cr, center_x, center_y, r_inside, 0.0, 2.0 *
M_PI);
1466 cairo_set_source_rgb(cr, flt_dark, flt_dark, flt_dark);
1468 cairo_arc(cr, center_x, center_y, r_outside,
M_PI, 1.5 *
M_PI);
1470 cairo_arc(cr, center_x, center_y, r_inside, 0.0, 0.5 *
M_PI);
1473 cairo_set_source_rgb(cr, flt_light, flt_light, flt_light);
1475 cairo_arc(cr, center_x, center_y, r_outside, 0.0, 0.5 *
M_PI);
1477 cairo_arc(cr, center_x, center_y, r_inside,
M_PI, 1.5 *
M_PI);
1481 double r = 255 / 255.0,
g = 155 / 255.0,
b = 40 / 255.0;
1484 gtk_rgb_to_hsv(
r,
g, b, &h, &s, &
v);
1487 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.7);
1489 cairo_translate(cr, center_x, center_y);
1490 cairo_rotate(cr, h * 2.0 *
M_PI - M_PI_2);
1492 cairo_arc(cr, r_inside *
v, 0.0, 3.0, 0, 2.0 *
M_PI);
1497 cairo_surface_destroy(source);
1508 GtkWidget *old_container = gtk_bin_get_child(GTK_BIN(
g->main_box));
1510 for(
int i=0;
i<3;
i++)
1512 g_object_ref(G_OBJECT(
g->blocks[
i]));
1513 if(old_container) gtk_container_remove(GTK_CONTAINER(old_container),
g->blocks[
i]);
1516 if(old_container) gtk_widget_destroy(old_container);
1518 const gchar *long_label[]
1519 = { N_(
"shadows: lift / offset"),
1520 N_(
"mid-tones: gamma / power"),
1521 N_(
"highlights: gain / slope") };
1526 for(
int i=0;
i<3;
i++)
1529 gtk_label_set_text(GTK_LABEL(
g->main_label), _(long_label[0]));
1533 gtk_container_add(GTK_CONTAINER(new_container), label);
1534 if(old_container) gtk_widget_show(label);
1537 gtk_container_add(GTK_CONTAINER(new_container),
g->blocks[
i]);
1542 for(
int i=0;
i<3;
i++) g_object_unref(G_OBJECT(
g->blocks[
i]));
1544 gtk_container_add(GTK_CONTAINER(
g->main_box), new_container);
1545 if(old_container) gtk_widget_show(new_container);
1553#define HSL_CALLBACK(which) \
1554static void which##_callback(GtkWidget *slider, gpointer user_data) \
1556 dt_iop_module_t *self = (dt_iop_module_t *)user_data; \
1557 dt_iop_colorbalance_params_t *p = (dt_iop_colorbalance_params_t *)self->params; \
1558 dt_iop_colorbalance_gui_data_t *g = (dt_iop_colorbalance_gui_data_t *)dt_iop_gui_data(self); \
1560 if(dt_gui_widgets_suppressed()) return; \
1562 dt_iop_color_picker_reset(self, TRUE); \
1564 float hsl[3] = {dt_bauhaus_slider_get(g->hue_##which) / 360.0f, \
1565 dt_bauhaus_slider_get(g->sat_##which) / 100.0f, \
1568 if(slider == g->hue_##which) \
1569 update_saturation_slider_color(g->sat_##which, hsl[0]); \
1570 set_RGB_sliders(g->which##_r, g->which##_g, g->which##_b, hsl, p->which, p->mode); \
1571 dt_dev_add_history_item(self->dev, self, TRUE, TRUE); \
1594 gtk_widget_set_tooltip_text(
g->mode, _(
"color-grading mapping method"));
1602 gtk_box_pack_start(GTK_BOX(self->gui->widget), GTK_WIDGET(
g->controls),
TRUE,
TRUE, 0);
1603 gtk_widget_set_tooltip_text(
g->controls, _(
"color-grading mapping method"));
1604 g_signal_connect(G_OBJECT(
g->controls),
"value-changed", G_CALLBACK(
controls_callback), self);
1608 !g_strcmp0(mode,
"BOTH") ?
BOTH :
HSL);
1610 g->master_box = self->gui->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL,
DT_GUI_BOX_SPACING);
1618 gtk_widget_set_tooltip_text(
g->saturation, _(
"saturation correction before the color balance"));
1624 gtk_widget_set_tooltip_text(
g->saturation_out, _(
"saturation correction after the color balance"));
1629 gtk_widget_set_tooltip_text(
g->grey, _(
"adjust to match a neutral tone"));
1637 gtk_widget_set_tooltip_text(
g->contrast, _(
"contrast"));
1639#ifdef SHOW_COLOR_WHEELS
1641 gtk_box_pack_start(GTK_BOX(self->widget), hbox,
FALSE,
FALSE, 0);
1644 gtk_box_pack_start(GTK_BOX(hbox), area,
TRUE,
TRUE, 0);
1649 g_signal_connect(G_OBJECT(area),
"draw", G_CALLBACK(dt_iop_area_draw), self);
1658 gtk_box_pack_start(GTK_BOX(hbox), area,
TRUE,
TRUE, 0);
1663 g_signal_connect(G_OBJECT(area),
"draw", G_CALLBACK(dt_iop_area_draw), self);
1672 gtk_box_pack_start(GTK_BOX(hbox), area,
TRUE,
TRUE, 0);
1677 g_signal_connect(G_OBJECT(area),
"draw", G_CALLBACK(dt_iop_area_draw), self);
1687 gtk_widget_set_tooltip_text(
g->main_label, _(
"click to cycle layout"));
1688 GtkWidget *main_label_box = gtk_event_box_new();
1689 gtk_container_add(GTK_CONTAINER(main_label_box),
g->main_label);
1690 g_signal_connect(G_OBJECT(main_label_box),
"button-release-event", G_CALLBACK(
_cycle_layout_callback), self);
1692 g->main_box = gtk_event_box_new();
1694 char field_name[10];
1696#define ADD_CHANNEL(which, section, c, n, N, text, span) \
1697 sprintf(field_name, "%s[%d]", #which, CHANNEL_##N); \
1698 g->which##_##c = dt_bauhaus_slider_from_params(self, field_name); \
1699 dt_bauhaus_slider_set_soft_range(g->which##_##c, -span+1.0, span+1.0); \
1700 dt_bauhaus_slider_set_digits(g->which##_##c, 5); \
1701 dt_bauhaus_slider_set_offset(g->which##_##c, -1.0); \
1702 dt_bauhaus_slider_set_feedback(g->which##_##c, 0); \
1703 gtk_widget_set_tooltip_text(g->which##_##c, _(text[CHANNEL_##N])); \
1704 dt_bauhaus_widget_set_label(g->which##_##c, #n); \
1706#define ADD_BLOCK(blk, which, section, text, span, satspan) \
1707 g->blocks[blk] = self->gui->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING); \
1709 sprintf(field_name, "%s[%d]", #which, CHANNEL_FACTOR); \
1710 g->which##_factor = dt_color_picker_new(self, DT_COLOR_PICKER_AREA, \
1711 dt_bauhaus_slider_from_params(self, field_name)); \
1712 dt_bauhaus_slider_set_soft_range(g->which##_factor, -span+1.0, span+1.0); \
1713 dt_bauhaus_slider_set_digits(g->which##_factor, 4); \
1714 dt_bauhaus_slider_set_factor(g->which##_factor, 100.0); \
1715 dt_bauhaus_slider_set_offset(g->which##_factor, - 100.0); \
1716 dt_bauhaus_slider_set_format(g->which##_factor,"%"); \
1717 dt_bauhaus_slider_set_feedback(g->which##_factor, 0); \
1718 dt_bauhaus_slider_set_stop(g->which##_factor, 0.0, 0.0, 0.0, 0.0); \
1719 dt_bauhaus_slider_set_stop(g->which##_factor, 1.0, 1.0, 1.0, 1.0); \
1720 gtk_widget_set_tooltip_text(g->which##_factor, _(text[CHANNEL_FACTOR])); \
1721 dt_bauhaus_widget_set_label(g->which##_factor, N_("factor")); \
1723 g->hue_##which = dt_color_picker_new(self, DT_COLOR_PICKER_AREA, \
1724 dt_bauhaus_slider_new_with_range_and_feedback(dt_bauhaus_get_global(), DT_GUI_MODULE(self), \
1725 0.0f, 360.0f, 0, 0.0f, 2, 0)); \
1726 dt_bauhaus_widget_set_label(g->hue_##which, N_("hue")); \
1727 dt_bauhaus_slider_set_format(g->hue_##which, "\302\260"); \
1728 dt_bauhaus_slider_set_stop(g->hue_##which, 0.0f, 1.0f, 0.0f, 0.0f); \
1729 dt_bauhaus_slider_set_stop(g->hue_##which, 0.166f, 1.0f, 1.0f, 0.0f); \
1730 dt_bauhaus_slider_set_stop(g->hue_##which, 0.322f, 0.0f, 1.0f, 0.0f); \
1731 dt_bauhaus_slider_set_stop(g->hue_##which, 0.498f, 0.0f, 1.0f, 1.0f); \
1732 dt_bauhaus_slider_set_stop(g->hue_##which, 0.664f, 0.0f, 0.0f, 1.0f); \
1733 dt_bauhaus_slider_set_stop(g->hue_##which, 0.830f, 1.0f, 0.0f, 1.0f); \
1734 dt_bauhaus_slider_set_stop(g->hue_##which, 1.0f, 1.0f, 0.0f, 0.0f); \
1735 gtk_widget_set_tooltip_text(g->hue_##which, _("select the hue")); \
1736 g_signal_connect(G_OBJECT(g->hue_##which), "value-changed", \
1737 G_CALLBACK(which##_callback), self); \
1738 gtk_box_pack_start(GTK_BOX(self->gui->widget), g->hue_##which, TRUE, TRUE, 0); \
1740 g->sat_##which = dt_bauhaus_slider_new_with_range_and_feedback(dt_bauhaus_get_global(), DT_GUI_MODULE(self), \
1741 0.0f, 100.0f, 0, 0.0f, 2, 0); \
1742 dt_bauhaus_slider_set_soft_max(g->sat_##which, satspan); \
1743 dt_bauhaus_widget_set_label(g->sat_##which, N_("saturation")); \
1744 dt_bauhaus_slider_set_format(g->sat_##which, "%"); \
1745 dt_bauhaus_slider_set_stop(g->sat_##which, 0.0f, 0.2f, 0.2f, 0.2f); \
1746 dt_bauhaus_slider_set_stop(g->sat_##which, 1.0f, 1.0f, 1.0f, 1.0f); \
1747 gtk_widget_set_tooltip_text(g->sat_##which, _("select the saturation")); \
1748 g_signal_connect(G_OBJECT(g->sat_##which), "value-changed", \
1749 G_CALLBACK(which##_callback), self); \
1750 gtk_box_pack_start(GTK_BOX(self->gui->widget), g->sat_##which, TRUE, TRUE, 0); \
1752 ADD_CHANNEL(which, section, r, red, RED, text, span) \
1753 dt_bauhaus_slider_set_stop(g->which##_r, 0.0, 0.0, 1.0, 1.0); \
1754 dt_bauhaus_slider_set_stop(g->which##_r, 0.5, 1.0, 1.0, 1.0); \
1755 dt_bauhaus_slider_set_stop(g->which##_r, 1.0, 1.0, 0.0, 0.0); \
1756 ADD_CHANNEL(which, section, g, green, GREEN, text, span) \
1757 dt_bauhaus_slider_set_stop(g->which##_g, 0.0, 1.0, 0.0, 1.0); \
1758 dt_bauhaus_slider_set_stop(g->which##_g, 0.5, 1.0, 1.0, 1.0); \
1759 dt_bauhaus_slider_set_stop(g->which##_g, 1.0, 0.0, 1.0, 0.0); \
1760 ADD_CHANNEL(which, section, b, blue, BLUE, text, span) \
1761 dt_bauhaus_slider_set_stop(g->which##_b, 0.0, 1.0, 1.0, 0.0); \
1762 dt_bauhaus_slider_set_stop(g->which##_b, 0.5, 1.0, 1.0, 1.0); \
1763 dt_bauhaus_slider_set_stop(g->which##_b, 1.0, 0.0, 0.0, 1.0); \
1765 static const char *lift_messages[]
1766 = { N_(
"factor of lift/offset"),
1767 N_(
"factor of red for lift/offset"),
1768 N_(
"factor of green for lift/offset"),
1769 N_(
"factor of blue for lift/offset") };
1771 static const char *gamma_messages[]
1772 = { N_(
"factor of gamma/power"),
1773 N_(
"factor of red for gamma/power"),
1774 N_(
"factor of green for gamma/power"),
1775 N_(
"factor of blue for gamma/power") };
1777 static const char *gain_messages[]
1778 = { N_(
"factor of gain/slope"),
1779 N_(
"factor of red for gain/slope"),
1780 N_(
"factor of green for gain/slope"),
1781 N_(
"factor of blue for gain/slope") };
1783 ADD_BLOCK(0, lift, N_(
"shadows"), lift_messages, 0.05f, 5.0f)
1784 ADD_BLOCK(1, gamma, N_(
"mid-tones"), gamma_messages, 0.5f, 20.0f)
1785 ADD_BLOCK(2, gain, N_(
"highlights"), gain_messages, 0.5f, 25.0f)
1788 g->optimizer_box = self->gui->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL,
DT_GUI_BOX_SPACING);
1795 gtk_widget_set_tooltip_text(
g->auto_luma, _(
"fit the whole histogram and center the average luma"));
1796 gtk_box_pack_start(GTK_BOX(self->gui->widget),
g->auto_luma,
FALSE,
FALSE, 0);
1801 gtk_widget_set_tooltip_text(
g->auto_color, _(
"optimize the RGB curves to remove color casts"));
1802 gtk_box_pack_start(GTK_BOX(self->gui->widget),
g->auto_color,
FALSE,
FALSE, 0);
1807 gtk_box_pack_start(GTK_BOX(self->gui->widget), GTK_WIDGET(mode_box),
TRUE,
TRUE, 0);
1808 gtk_box_pack_start(GTK_BOX(self->gui->widget), GTK_WIDGET(
g->master_box),
TRUE,
TRUE, 0);
1809 gtk_box_pack_start(GTK_BOX(self->gui->widget), GTK_WIDGET(main_label_box),
TRUE,
TRUE, 0);
1810 gtk_box_pack_start(GTK_BOX(self->gui->widget), GTK_WIDGET(
g->main_box),
TRUE,
TRUE, 0);
1811 gtk_box_pack_start(GTK_BOX(self->gui->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)
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)
Convert RGB to HSL. Common helper used by iop modules.
void hsl2rgb(dt_aligned_pixel_t rgb, float h, float s, float l)
Convert HSL back to RGB. Common helper used by iop modules.
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
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)
Read the stored string for name as a private copy.
void dt_conf_set_string(const char *name, const char *val)
const char * dt_conf_get_string_const(const char *name)
Borrow the stored string for name without copying it.
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
#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)
What a photograph says about itself: the EXIF, IPTC and XMP tags a camera and a cataloguer write,...
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
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)
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)
GtkWidget * dt_ui_section_label_new(const gchar *str)
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_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 __OMP_PARALLEL_FOR_SIMD__(...)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ 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)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
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]
dt_iop_global_data_t * data
dt_iop_params_t * default_params
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.
#define __DT_CLONE_TARGETS__