85#define DT_IOP_COLORZONES_INSET DT_PIXEL_APPLY_DPI(5)
86#define DT_IOP_COLORZONES_CURVE_INFL .3f
87#define DT_IOP_COLORZONES_RES 256
88#define DT_IOP_COLORZONES_LUT_RES 0x10000
90#define DT_IOP_COLORZONES_BANDS 8
92#define DT_IOP_COLORZONES_MAXNODES 20
93#define DT_IOP_COLORZONES_DEFAULT_STEP (0.001f)
95#define DT_IOP_COLORZONES_MIN_X_DISTANCE 0.0025f
186 return _(
"color _zones");
193 _(
"linear or non-linear, Lab, display-referred"),
194 _(
"non-linear, Lab"),
195 _(
"non-linear, Lab, display-referred"));
214 const int new_version)
216#define DT_IOP_COLORZONES1_BANDS 6
218 if(old_version == 1 && new_version == 5)
220 typedef struct dt_iop_colorzones_params1_t
224 } dt_iop_colorzones_params1_t;
226 const dt_iop_colorzones_params1_t *old = old_params;
232 for(
int i = 0;
i < 3;
i++)
234 new->curve[
i][0].x = old->equalizer_x[
i][0];
235 new->curve[
i][0].y = old->equalizer_y[
i][0];
238 for(
int i = 0;
i < 3;
i++)
239 for(
int k = 0;
k < 6;
k++)
243 new->curve[
i][
k + 1].x = old->equalizer_x[
i][
k] + 0.001f;
245 new->curve[
i][
k + 1].x = old->equalizer_x[
i][
k] - 0.001f;
247 new->curve[
i][
k + 1].x = old->equalizer_x[
i][
k];
248 new->curve[
i][
k + 1].y = old->equalizer_y[
i][
k];
252 for(
int i = 0;
i < 3;
i++)
254 new->curve[
i][7].x = old->equalizer_x[
i][5];
255 new->curve[
i][7].y = old->equalizer_y[
i][5];
257 for(
int c = 0; c < 3; c++)
262 new->strength = 0.0f;
267 if(old_version == 2 && new_version == 5)
269 typedef struct dt_iop_colorzones_params2_t
273 } dt_iop_colorzones_params2_t;
275 const dt_iop_colorzones_params2_t *old = old_params;
280 for(
int c = 0; c < 3; c++)
282 new->curve[c][b].x = old->equalizer_x[c][b];
283 new->curve[c][b].y = old->equalizer_y[c][b];
285 for(
int c = 0; c < 3; c++)
290 new->strength = 0.0f;
295 if(old_version == 3 && new_version == 5)
297 typedef struct dt_iop_colorzones_params3_t
302 } dt_iop_colorzones_params3_t;
304 const dt_iop_colorzones_params3_t *old = old_params;
310 for(
int c = 0; c < 3; c++)
312 new->curve[c][b].x = old->equalizer_x[c][b];
313 new->curve[c][b].y = old->equalizer_y[c][b];
316 for(
int c = 0; c < 3; c++)
321 new->strength = old->strength;
326 if(old_version == 4 && new_version == 5)
328 typedef struct dt_iop_colorzones_params4_t
336 } dt_iop_colorzones_params4_t;
338 const dt_iop_colorzones_params4_t *old = old_params;
346 new->curve[c][
i].x = old->curve[c][
i].x;
347 new->curve[c][
i].y = old->curve[c][
i].y;
352 new->curve_num_nodes[c] = old->curve_num_nodes[c];
353 new->curve_type[c] = old->curve_type[c];
355 new->strength = old->strength;
356 new->mode = old->mode;
360#undef DT_IOP_COLORZONES1_BANDS
367 return (
x - offset) * zoom_factor;
372 return (
x / zoom_factor) + offset;
377 const int ch,
const double mouse_x,
const double mouse_y,
380 const int bands =
p->curve_num_nodes[
ch];
382 const float lin_mouse_x =
_mouse_to_curve(mouse_x, c->zoom_factor, c->offset_x);
383 const float lin_mouse_y =
_mouse_to_curve(mouse_y, c->zoom_factor, c->offset_y);
385 const float rad = radius / c->zoom_factor;
390 for(
int k = 1;
k < bands - 1;
k++)
392 const float f = expf(-(lin_mouse_x -
p->curve[
ch][
k].x) * (lin_mouse_x -
p->curve[
ch][
k].x) / (rad * rad));
393 p->curve[
ch][
k].y = (1.f -
f) *
p->curve[
ch][
k].y +
f * lin_mouse_y;
395 const int m = bands - 1;
396 const float mind = fminf((lin_mouse_x -
p->curve[
ch][0].x) * (lin_mouse_x -
p->curve[
ch][0].x),
397 (lin_mouse_x -
p->curve[
ch][
m].x) * (lin_mouse_x -
p->curve[
ch][
m].x));
398 const float f = expf(-mind / (rad * rad));
399 p->curve[
ch][0].y = (1.f -
f) *
p->curve[
ch][0].y +
f * lin_mouse_y;
400 p->curve[
ch][
m].y = (1.f -
f) *
p->curve[
ch][
m].y +
f * lin_mouse_y;
404 for(
int k = 0;
k < bands;
k++)
406 const float f = expf(-(lin_mouse_x -
p->curve[
ch][
k].x) * (lin_mouse_x -
p->curve[
ch][
k].x) / (rad * rad));
407 p->curve[
ch][
k].y = (1.f -
f) *
p->curve[
ch][
k].y +
f * lin_mouse_y;
417 return lut[bin1] *
f +
lut[bin0] * (1.f -
f);
434 const float normalize_C = 1.f / (128.0f * sqrtf(2.f));
440 for(
size_t k = 0;
k < (size_t)roi_out->
width * roi_out->
height;
k++)
442 float *in = (
float *)ivoid +
ch *
k;
447 dt_Lab_2_LCH(in, LCh);
453 select = LCh[0] * 0.01f;
456 select = LCh[1] * normalize_C;
463 select = CLAMP(select, 0.f, 1.f);
465 out[3] = fabsf(
lookup(
d->lut[display_channel], select) - .5f) * 4.f;
466 out[3] = CLAMP(
out[3], 0.f, 1.f);
480 const float normalize_C = 1.f / (128.0f * sqrtf(2.f));
482 for(
size_t k = 0;
k < (size_t)roi_out->
width * roi_out->
height;
k++)
484 float *in = (
float *)ivoid +
ch *
k;
489 dt_Lab_2_LCH(in, LCh);
495 select = LCh[0] * 0.01f;
498 select = LCh[1] * normalize_C;
505 select = CLAMP(select, 0.f, 1.f);
507 LCh[0] *= powf(2.0f, 4.0f * (
lookup(
d->lut[0], select) - .5f));
508 LCh[1] *= 2.f *
lookup(
d->lut[1], select);
509 LCh[2] +=
lookup(
d->lut[2], select) - .5f;
511 dt_LCH_2_Lab(LCh,
out);
524 for(
size_t k = 0;
k < (size_t)roi_out->
width * roi_out->
height;
k++)
526 float *in = (
float *)ivoid +
ch *
k;
528 const float a = in[1], b = in[2];
530 const float C = sqrtf(b * b + a * a);
536 select = fminf(1.0f, in[0] / 100.0f);
539 select = fminf(1.0f,
C / 128.0f);
544 blend = powf(1.0f -
C / 128.0f, 2.0f);
547 const float Lm = (blend * .5f + (1.0f - blend) *
lookup(
d->lut[0], select)) - .5f;
548 const float hm = (blend * .5f + (1.0f - blend) *
lookup(
d->lut[2], select)) - .5f;
551 const float Cm = 2.0f *
lookup(
d->lut[1], select);
552 const float L = in[0] * powf(2.0f, 4.0f * Lm);
585 cl_mem dev_L, dev_a, dev_b = NULL;
588 const int devid = pipe->
devid;
591 const int kernel_colorzones
610 if(err != CL_SUCCESS)
goto error;
628 const int version = 5;
652 for(
int c = 0; c < 3; c++)
675 for(
int c = 0; c < 3; c++)
698 for(
int c = 0; c < 3; c++)
719 for(
int c = 0; c < 3; c++)
750 for(
int c = 0; c < 3; c++)
759 const int colorzones_bands_hsl = 8;
761 for(
int k = 0;
k < colorzones_bands_hsl;
k++)
770 for(
int c = 0; c < 3; c++)
772 p.curve_num_nodes[c] = colorzones_bands_hsl;
788 c->display_mask =
FALSE;
791 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->bt_showmask)))
794 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->bt_showmask),
FALSE);
802 for(
int k = 0;
k <
p->curve_num_nodes[
ch];
k++)
805 p->curve[
ch][
k].x = (float)
k / (
float)(
p->curve_num_nodes[
ch] - 1);
807 p->curve[
ch][
k].x = ((float)
k + 0.5f) / (float)
p->curve_num_nodes[
ch];
808 p->curve[
ch][
k].y = 0.5f;
816 p->curve_num_nodes[
ch] = 2;
821 p->channel = channel;
823 p->splines_version = splines_version;
831 if(!select_by_picker)
836 dt_sRGB_to_XYZ(
rgb, xyz);
838 dt_Lab_2_LCH(lab, picked_color);
840 picker_max[0] = picker_min[0] = picked_color[0];
841 picker_max[1] = picker_min[1] = picked_color[1];
842 picker_max[2] = picker_min[2] = picked_color[2];
846 for(
int k = 0;
k < 3;
k++)
853 return select_by_picker;
858 const float *
const picker_color,
const float *
const picker_min,
859 const float *
const picker_max)
862 ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->colorpicker)) ||
863 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->colorpicker_set_values)) ))
879 for(; samples; samples = g_slist_next(samples))
881 sample = samples->data;
883 float picked_i = -1.0f;
884 float picked_min_i = -1.0f;
885 float picked_max_i = -1.0f;
888 for(
int k = 0;
k < 3;
k++)
894 pick_mean[3] = pick_min[3] = pick_max[3] = 1.f;
904 &converted_cst, work_profile);
906 &converted_cst, work_profile);
908 &converted_cst, work_profile);
910 dt_Lab_2_LCH(pick_mean, pick_mean);
911 dt_Lab_2_LCH(pick_min, pick_min);
912 dt_Lab_2_LCH(pick_max, pick_max);
918 picked_i = pick_mean[0] / 100.0f;
919 picked_min_i = pick_min[0] / 100.0f;
920 picked_max_i = pick_max[0] / 100.0f;
923 picked_i = pick_mean[1] / (128.0f * sqrtf(2.f));
924 picked_min_i = pick_min[1] / (128.0f * sqrtf(2.f));
925 picked_max_i = pick_max[1] / (128.0f * sqrtf(2.f));
928 picked_i = pick_mean[2];
929 picked_min_i = pick_min[2];
930 picked_max_i = pick_max[2];
936 picked_min_i =
_curve_to_mouse(picked_min_i, c->zoom_factor, c->offset_x);
937 picked_max_i =
_curve_to_mouse(picked_max_i, c->zoom_factor, c->offset_x);
939 cairo_set_source_rgba(cr, 0.5, 0.7, 0.5, 0.15);
940 cairo_rectangle(cr,
width * picked_min_i, 0,
width * fmax(picked_max_i - picked_min_i, 0.0f),
height);
942 cairo_set_source_rgba(cr, 0.5, 0.7, 0.5, 0.5);
943 cairo_move_to(cr,
width * picked_i, 0);
952 ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->colorpicker)) ||
953 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->colorpicker_set_values)) ))
956 float picked_i = -1.0f;
957 float picked_min_i = -1.0f;
958 float picked_max_i = -1.0f;
963 picked_i = picker_color[0] / 100.0f;
964 picked_min_i = picker_min[0] / 100.0f;
965 picked_max_i = picker_max[0] / 100.0f;
968 picked_i = picker_color[1] / (128.0f * sqrtf(2.f));
969 picked_min_i = picker_min[1] / (128.0f * sqrtf(2.f));
970 picked_max_i = picker_max[1] / (128.0f * sqrtf(2.f));
973 picked_i = picker_color[2];
974 picked_min_i = picker_min[2];
975 picked_max_i = picker_max[2];
980 picked_min_i =
_curve_to_mouse(picked_min_i, c->zoom_factor, c->offset_x);
981 picked_max_i =
_curve_to_mouse(picked_max_i, c->zoom_factor, c->offset_x);
985 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.25);
986 cairo_rectangle(cr,
width * picked_min_i, 0,
width * fmax(picked_max_i - picked_min_i, 0.0),
height);
989 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
990 cairo_set_operator(cr, CAIRO_OPERATOR_XOR);
992 cairo_move_to(cr,
width * picked_i, 0.0);
1001#define DT_COLORZONES_CELLSI 64
1003#define DT_COLORZONES_CELLSJ 36
1005#define COLORZONES_DRAW_BACKGROUD_BOX \
1006 dt_aligned_pixel_t Lab; \
1007 dt_LCH_2_Lab(LCh, Lab); \
1008 const float L0 = Lab[0]; \
1010 const float Lwhite = 100.0f, Lclip = 20.0f; \
1011 const float Lcap = fminf(100.0f, Lab[0]); \
1014 - (Lcap - L0) * (1.0f / 100.0f) * fminf(Lwhite - Lclip, fmaxf(0.0f, Lab[0] - Lclip)) / (Lwhite - Lclip); \
1015 const float clip2 = clip * clip * clip; \
1016 Lab[1] *= Lab[0] / L0 * clip2; \
1017 Lab[2] *= Lab[0] / L0 * clip2; \
1019 dt_aligned_pixel_t xyz; \
1020 dt_aligned_pixel_t rgb; \
1021 dt_Lab_to_XYZ(Lab, xyz); \
1022 dt_XYZ_to_sRGB(xyz, rgb); \
1024 cairo_set_source_rgb(cr, rgb[0], rgb[1], rgb[2]);
1027 const int select_by_picker,
const int width,
const int height,
1028 const float *picked_color)
1030 const float bg_sat_factor =
dt_conf_get_float(
"plugins/darkroom/colorzones/bg_sat_factor");
1031 const float normalize_C = (128.f * bg_sat_factor * sqrtf(2.f));
1036 for(
int j = 0; j < cellsj; j++)
1038 for(
int i = 0;
i < cellsi;
i++)
1042 const float jj =
_mouse_to_curve(1.0f - ((
float)j - .5f) / (
float)(cellsj - 1), c->zoom_factor, c->offset_y);
1044 =
_mouse_to_curve(1.0f - (((
float)j / (
float)(cellsj - 1))), c->zoom_factor, c->offset_y) + .5f;
1045 const float ii =
_mouse_to_curve(((
float)
i + .5f) / (
float)(cellsi - 1), c->zoom_factor, c->offset_x);
1046 const float iih =
_mouse_to_curve((
float)
i / (
float)(cellsi - 1), c->zoom_factor, c->offset_x);
1053 LCh[0] = 100.0f * ii;
1054 LCh[1] = normalize_C * .5f;
1055 LCh[2] = picked_color[2];
1059 LCh[1] = picked_color[1] * 2.f * bg_sat_factor * ii;
1060 LCh[2] = picked_color[2];
1064 LCh[1] = normalize_C * .5f;
1076 LCh[0] += -50.0f + 100.0f * jj;
1088 cairo_rectangle(cr,
width *
i / (
float)cellsi,
height * j / (
float)cellsj,
width / (
float)cellsi,
1104 if(c->minmax_curve_type[
ch] !=
p.curve_type[
ch] || c->minmax_curve_nodes[
ch] !=
p.curve_num_nodes[
ch])
1108 c->minmax_curve_nodes[
ch] =
p.curve_num_nodes[
ch];
1109 c->minmax_curve_type[
ch] =
p.curve_type[
ch];
1113 p.curve[
ch][
p.curve_num_nodes[
ch] - 2].y);
1117 for(
int k = 0;
k <
p.curve_num_nodes[
ch];
k++)
1123 p.curve[
ch][
p.curve_num_nodes[
ch] - 1].y);
1129 p.curve[
ch][
p.curve_num_nodes[
ch] - 2].y);
1133 for(
int k = 0;
k <
p.curve_num_nodes[
ch];
k++)
1140 p.curve[
ch][
p.curve_num_nodes[
ch] - 1].y);
1149 if(c->minmax_curve_type[
ch] !=
p.curve_type[
ch] || c->minmax_curve_nodes[
ch] !=
p.curve_num_nodes[
ch]
1150 || c->minmax_curve[
ch]->c.m_numAnchors !=
p.curve_num_nodes[
ch])
1154 c->minmax_curve_nodes[
ch] =
p.curve_num_nodes[
ch];
1155 c->minmax_curve_type[
ch] =
p.curve_type[
ch];
1157 for(
int k = 0;
k <
p.curve_num_nodes[
ch];
k++)
1162 for(
int k = 0;
k <
p.curve_num_nodes[
ch];
k++)
1170 const int ch = (int)c->channel;
1172 GtkAllocation allocation;
1173 gtk_widget_get_allocation(widget, &allocation);
1175 int width = allocation.width,
height = allocation.height;
1177 cairo_t *cr = cairo_create(cst);
1181 GtkStyleContext *context = gtk_widget_get_style_context(widget);
1182 gboolean color_found = gtk_style_context_lookup_color(context,
"graph_overlay", &color);
1190 gdk_cairo_set_source_rgba(cr, &color);
1193 cairo_translate(cr, inset, inset);
1198 cairo_set_source_rgb(cr, .1, .1, .1);
1202 cairo_set_source_rgb(cr, .3, .3, .3);
1212 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
1216 cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT);
1225 const int ch_hist =
p.channel;
1227 const gboolean is_linear =
FALSE;
1228 const float hist_max = is_linear ? self->
histogram_max[ch_hist]
1233 cairo_translate(cr, 0,
height);
1236 cairo_set_source_rgba(cr, .2, .2, .2, 0.5);
1238 c->offset_y * hist_max, is_linear);
1250 cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
1253 for(
int k = 0;
k <
p.curve_num_nodes[
ch];
k++)
1258 cairo_rel_line_to(cr, -arrw * .5f, 0);
1259 cairo_rel_line_to(cr, arrw * .5f, -arrw);
1260 cairo_rel_line_to(cr, arrw * .5f, arrw);
1261 cairo_close_path(cr);
1269 cairo_translate(cr, 0,
height);
1272 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1276 const int ch_inv = ((int)c->channel +
i + 1) % 3;
1279 cairo_set_source_rgba(cr, .7, .7, .7, 1.0);
1281 cairo_set_source_rgba(cr, .7, .7, .7, 0.3);
1283 cairo_move_to(cr, 0, -
height *
_curve_to_mouse(c->draw_ys[ch_inv][0], c->zoom_factor, c->offset_y));
1287 const float yy = c->draw_ys[ch_inv][
k];
1300 cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
1302 for(
int k = 0;
k <
p.curve_num_nodes[
ch];
k++)
1311 if(c->edit_by_area && (c->mouse_y > 0 || c->dragging))
1313 const int bands =
p.curve_num_nodes[
ch];
1323 for(
int k = 0;
k < bands;
k++)
1333 for(
int k = 0;
k < bands;
k++)
1347 for(
int k = 0;
k < bands;
k++)
1357 for(
int k = 0;
k < bands;
k++)
1367 cairo_set_source_rgba(cr, .7, .7, .7, .6);
1373 const float yy = c->draw_min_ys[
k];
1384 const float yy = c->draw_max_ys[
k];
1392 cairo_close_path(cr);
1396 cairo_set_source_rgba(cr, .9, .9, .9, .5);
1399 const float x = c->mouse_x, y =
_curve_to_mouse(c->draw_ys[
ch][
k], c->zoom_factor, c->offset_y);
1409 if(c->selected >= 0)
1411 cairo_set_source_rgb(cr, .9, .9, .9);
1412 const float x =
_curve_to_mouse(
p.curve[c->channel][c->selected].x, c->zoom_factor, c->offset_x),
1413 y =
_curve_to_mouse(
p.curve[c->channel][c->selected].y, c->zoom_factor, c->offset_y);
1420 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
1423 cairo_set_source_surface(crf, cst, 0, 0);
1425 cairo_surface_destroy(cst);
1434 GtkAllocation allocation;
1435 gtk_widget_get_allocation(widget, &allocation);
1437 int width = allocation.width,
height = allocation.height;
1439 cairo_t *cr = cairo_create(cst);
1442 GtkStyleContext *context = gtk_widget_get_style_context(widget);
1443 gboolean color_found = gtk_style_context_lookup_color(context,
"graph_overlay", &color);
1451 gdk_cairo_set_source_rgba(cr, &color);
1454 cairo_translate(cr, inset, inset);
1459 cairo_set_source_rgb(cr, .1, .1, .1);
1463 cairo_set_source_rgb(cr, .3, .3, .3);
1472 const float normalize_C = (128.f * sqrtf(2.f));
1474 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
1478 for(
int i = 0;
i < cellsi;
i++)
1480 const float ii =
_mouse_to_curve(((
float)
i + .5f) / (
float)(cellsi - 1), c->zoom_factor, c->offset_x);
1481 const float iih =
_mouse_to_curve((
float)
i / (
float)(cellsi - 1), c->zoom_factor, c->offset_x);
1489 LCh[0] = 100.0f * ii;
1490 LCh[1] = normalize_C * .5f;
1491 LCh[2] = picked_color[2];
1495 LCh[1] = picked_color[1] * 2.f * ii;
1496 LCh[2] = picked_color[2];
1500 LCh[1] = normalize_C * .5f;
1507 cairo_rectangle(cr,
width *
i / (
float)cellsi, 0,
width / (
float)cellsi,
height);
1511 cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT);
1518 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
1521 cairo_set_source_surface(crf, cst, 0, 0);
1523 cairo_surface_destroy(cst);
1527#undef COLORZONES_DRAW_BACKGROUD_BOX
1528#undef DT_COLORZONES_CELLSI
1529#undef DT_COLORZONES_CELLSJ
1535 if(event->button == 1 && event->type == GDK_2BUTTON_PRESS)
1538 c->zoom_factor = 1.f;
1539 c->offset_x = c->offset_y = 0.f;
1541 gtk_widget_queue_draw(self->
widget);
1552 gboolean point_valid =
TRUE;
1556 if((selected > 0 &&
x - curve[selected - 1].
x <= min_dist)
1557 || (selected < nodes - 1 && curve[selected + 1].
x -
x <= min_dist))
1558 point_valid =
FALSE;
1562 if((selected > 0 && (curve[selected - 1].
x >=
x)) || (selected < nodes - 1 && (curve[selected + 1].
x <=
x)))
1564 point_valid =
FALSE;
1575 int ch = c->channel;
1580 if(node == 0 || node ==
p->curve_num_nodes[
ch] - 1) dx = 0.f;
1582 float new_x = CLAMP(curve[node].
x + dx, 0.0f, 1.0f);
1583 const float new_y = CLAMP(curve[node].y + dy, 0.0f, 1.0f);
1589 curve[node].
x = new_x;
1590 curve[node].
y = new_y;
1596 curve[
p->curve_num_nodes[
ch] - 1].
x = 1.f - curve[node].
x;
1597 curve[
p->curve_num_nodes[
ch] - 1].
y = curve[node].
y;
1601 curve[0].
x = 1.f - curve[node].
x;
1602 curve[0].
y = curve[node].
y;
1621 curve[node].
x = new_x;
1622 curve[node].
y = new_y;
1628 gtk_widget_queue_draw(widget);
1637 curve[node].
y = 0.5f;
1644 for(
int k = node;
k < *nodes - 1;
k++)
1646 curve[
k].
x = curve[
k + 1].
x;
1647 curve[
k].
y = curve[
k + 1].
y;
1649 curve[*nodes - 1].
x = curve[*nodes - 1].
y = 0;
1660 gtk_widget_queue_draw(self->
widget);
1671 for(
int k = 1;
k < *nodes;
k++)
1680 if(selected == -1) selected = *nodes;
1684 if((selected > 0 &&
x - curve[selected - 1].
x <= min_dist)
1685 || (selected < *nodes && curve[selected].
x -
x <= min_dist))
1690 for(
int i = *nodes;
i > selected;
i--)
1692 curve[
i].
x = curve[
i - 1].
x;
1693 curve[
i].
y = curve[
i - 1].
y;
1696 curve[selected].
x =
x;
1697 curve[selected].
y = y;
1712 if(c->selected < 0 && !c->edit_by_area)
return TRUE;
1720 const int bands =
p->curve_num_nodes[c->channel];
1721 c->mouse_radius = CLAMP(c->mouse_radius * (1.0 + 0.1 * delta_y), 0.2 / bands, 1.0);
1722 gtk_widget_queue_draw(widget);
1741 GtkAllocation allocation;
1742 gtk_widget_get_allocation(widget, &allocation);
1744 const int height = allocation.height - 2 * inset;
1745 const int width = allocation.width - 2 * inset;
1747 const int ch = c->channel;
1748 const int nodes =
p->curve_num_nodes[
ch];
1751 const double old_m_x = c->mouse_x;
1752 const double old_m_y = fabs(c->mouse_y);
1754 c->mouse_x = CLAMP(event->x - inset, 0,
width) / (float)
width;
1755 c->mouse_y = 1.0 - CLAMP(event->y - inset, 0,
height) / (float)
height;
1758 if(event->state & GDK_BUTTON1_MASK)
1762 if(c->dragging && c->x_move >= 0)
1763 c->selected = c->x_move;
1769 if(c->selected >= 0)
1772 const float translate_mouse_x = old_m_x -
_curve_to_mouse(curve[c->selected].
x, c->zoom_factor, c->offset_x);
1773 const float translate_mouse_y = old_m_y -
_curve_to_mouse(curve[c->selected].
y, c->zoom_factor, c->offset_y);
1775 const float dx =
_mouse_to_curve(c->mouse_x - translate_mouse_x, c->zoom_factor, c->offset_x)
1776 -
_mouse_to_curve(old_m_x - translate_mouse_x, c->zoom_factor, c->offset_x);
1777 const float dy =
_mouse_to_curve(c->mouse_y - translate_mouse_y, c->zoom_factor, c->offset_y)
1778 -
_mouse_to_curve(old_m_y - translate_mouse_y, c->zoom_factor, c->offset_y);
1796 else if(event->y >
height)
1799 const int bands =
p->curve_num_nodes[c->channel];
1800 const float mouse_x =
_mouse_to_curve(c->mouse_x, c->zoom_factor, c->offset_x);
1801 float dist = fabsf(
p->curve[c->channel][0].x - mouse_x);
1802 for(
int k = 1;
k < bands;
k++)
1804 const float d2 = fabsf(
p->curve[c->channel][
k].x - mouse_x);
1819 if(event->state & GDK_BUTTON1_MASK)
1821 if(nodes < DT_IOP_COLORZONES_MAXNODES && c->selected == -1)
1823 const float linx =
_mouse_to_curve(c->mouse_x, c->zoom_factor, c->offset_x),
1827 c->selected =
_add_node(curve, &
p->curve_num_nodes[
ch], linx, liny);
1835 const float mx = c->mouse_x;
1836 const float my = c->mouse_y;
1839 float min = .04f * .04f;
1841 for(
int k = 0;
k < nodes;
k++)
1853 c->selected = nearest;
1855 if(c->selected >= 0) gtk_widget_grab_focus(widget);
1858 gtk_widget_queue_draw(widget);
1868 int ch = c->channel;
1869 int nodes =
p->curve_num_nodes[
ch];
1872 if(event->button == 1)
1874 if(c->edit_by_area && event->type != GDK_2BUTTON_PRESS && !
dt_modifier_is(event->state, GDK_CONTROL_MASK))
1879 else if(event->type == GDK_BUTTON_PRESS &&
dt_modifier_is(event->state, GDK_CONTROL_MASK)
1884 GtkAllocation allocation;
1885 gtk_widget_get_allocation(widget, &allocation);
1886 const int height = allocation.height - 2 * inset;
1887 const int width = allocation.width - 2 * inset;
1889 c->mouse_x = CLAMP(event->x - inset, 0,
width) / (float)
width;
1890 c->mouse_y = 1.0 - CLAMP(event->y - inset, 0,
height) / (float)
height;
1892 const float mx =
_mouse_to_curve(c->mouse_x, c->zoom_factor, c->offset_x);
1900 for(
int k = 1;
k < nodes;
k++)
1909 if(selected == -1) selected = nodes;
1914 if(y >= 0.0f && y <= 1.0f)
1917 selected =
_add_node(curve, &
p->curve_num_nodes[
ch], mx, y);
1920 const float min = .04f * .04f;
1922 for(
int k = 0;
k < nodes;
k++)
1924 const float other_y =
_curve_to_mouse(curve[
k].y, c->zoom_factor, c->offset_y);
1925 const float dist = (y - other_y) * (y - other_y);
1926 if(
dist <
min) c->selected = selected;
1931 gtk_widget_queue_draw(self->
widget);
1936 else if(event->type == GDK_2BUTTON_PRESS)
1939 p->curve_num_nodes[
ch] =
d->curve_num_nodes[
ch];
1940 p->curve_type[
ch] =
d->curve_type[
ch];
1949 gtk_widget_queue_draw(self->
widget);
1954 else if(event->button == 3 && c->selected >= 0)
1962 curve[nodes - 1].
y = 0.5f;
1963 curve[nodes - 1].
x = 1.f;
1967 const float reset_value = c->selected == 0 ? 0.f : 1.f;
1968 curve[c->selected].
y = 0.5f;
1969 curve[c->selected].
x = reset_value;
1973 gtk_widget_queue_draw(self->
widget);
1990 if(event->button == 1)
2003 c->mouse_y = fabs(c->mouse_y);
2004 gtk_widget_queue_draw(widget);
2012 c->mouse_y = -fabs(c->mouse_y);
2013 gtk_widget_queue_draw(widget);
2020 GtkAllocation allocation;
2021 gtk_widget_get_allocation(widget, &allocation);
2022 r.width = allocation.width;
2023 r.height = allocation.width;
2024 gtk_widget_get_preferred_size(widget, &
r, NULL);
2032 if(c->selected < 0)
return FALSE;
2036 float dx = 0.0f, dy = 0.0f;
2037 if(
key == GDK_KEY_Up)
2042 else if(
key == GDK_KEY_Down)
2047 else if(
key == GDK_KEY_Right)
2052 else if(
key == GDK_KEY_Left)
2058 if(!handled)
return FALSE;
2082 gtk_widget_queue_draw(self->
widget);
2091 if(w ==
g->select_by)
2095 gtk_widget_queue_draw(GTK_WIDGET(
g->area));
2096 gtk_widget_queue_draw(GTK_WIDGET(
g->bottom_area));
2117 gtk_widget_queue_draw(GTK_WIDGET(
g->area));
2125 g->edit_by_area = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
2127 gtk_widget_queue_draw(GTK_WIDGET(
g->area));
2139 dt_control_log(_(
"cannot display masks when the blending mask is displayed"));
2142 gtk_toggle_button_set_active(togglebutton,
FALSE);
2147 g->display_mask = gtk_toggle_button_get_active(togglebutton);
2149 if(module->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->
off), 1);
2157 if(picker ==
g->colorpicker_set_values)
2162 const int ch_curve =
g->channel;
2163 const int ch_val =
p->channel;
2167 p->curve_num_nodes[ch_curve] =
d->curve_num_nodes[ch_curve];
2168 p->curve_type[ch_curve] =
d->curve_type[ch_curve];
2171 curve[
k].
x =
d->curve[ch_curve][
k].x;
2172 curve[
k].
y =
d->curve[ch_curve][
k].y;
2176 int picker_set_upper_lower;
2178 picker_set_upper_lower = 1;
2180 picker_set_upper_lower = -1;
2182 picker_set_upper_lower = 0;
2185 const float feather = 0.02f;
2186 const float increment = 0.1f * picker_set_upper_lower;
2196 if(
x > 0.f &&
x < 1.f)
_add_node(curve, &
p->curve_num_nodes[ch_curve],
x, .5f);
2204 if(
x > 0.f &&
x < 1.f)
_add_node(curve, &
p->curve_num_nodes[ch_curve],
x, .5f + increment);
2212 if(
x > 0.f &&
x < 1.f)
_add_node(curve, &
p->curve_num_nodes[ch_curve],
x, .5f + 2.f * increment);
2220 if(
x > 0.f &&
x < 1.f)
_add_node(curve, &
p->curve_num_nodes[ch_curve],
x, .5f + increment);
2229 if(
x > 0.f &&
x < 1.f)
_add_node(curve, &
p->curve_num_nodes[ch_curve],
x, .5f);
2243 c->zoom_factor = 1.f;
2262 c->channel =
dt_conf_get_int(
"plugins/darkroom/colorzones/gui_channel");
2266 c->minmax_curve_nodes[
ch] =
p->curve_num_nodes[
ch];
2267 c->minmax_curve_type[
ch] =
p->curve_type[
ch];
2269 for(
int k = 0;
k <
p->curve_num_nodes[
ch];
k++)
2273 c->mouse_x = c->mouse_y = -1.0;
2275 c->offset_x = c->offset_y = 0.f;
2276 c->zoom_factor = 1.f;
2280 c->edit_by_area = 0;
2281 c->display_mask =
FALSE;
2289 gtk_box_pack_start(GTK_BOX(vbox), hbox,
FALSE,
FALSE, 0);
2297 gtk_widget_show(gtk_notebook_get_nth_page(c->channel_tabs, c->channel));
2298 gtk_notebook_set_current_page(c->channel_tabs, c->channel);
2300 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(c->channel_tabs),
TRUE,
TRUE, 0);
2301 gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(
" "),
FALSE,
FALSE, 0);
2305 gtk_widget_set_tooltip_text(c->colorpicker, _(
"pick GUI color from image\nctrl+click or right-click to select an area"));
2311 gtk_widget_set_tooltip_text(c->colorpicker_set_values, _(
"create a curve based on an area from the image\n"
2312 "drag to create a flat curve\n"
2313 "ctrl+drag to create a positive curve\n"
2314 "shift+drag to create a negative curve"));
2317 c->area = GTK_DRAWING_AREA(gtk_drawing_area_new());
2318 gtk_widget_set_hexpand(GTK_WIDGET(c->area),
TRUE);
2320 gtk_box_pack_start(GTK_BOX(vbox),
2322 "plugins/darkroom/colorzones/graphheight", 280, 100),
2326 gtk_widget_set_name(GTK_WIDGET(dabox),
"iop-bottom-bar");
2327 c->bottom_area = gtk_drawing_area_new();
2328 gtk_box_pack_start(GTK_BOX(dabox), GTK_WIDGET(c->bottom_area),
TRUE,
TRUE, 0);
2329 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(dabox),
TRUE,
TRUE, 0);
2330 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(vbox),
TRUE,
TRUE, 0);
2335 gchar *label = N_(
"edit by area");
2336 c->chk_edit_by_area = gtk_check_button_new_with_label(_(label));
2337 gtk_label_set_ellipsize(GTK_LABEL(gtk_bin_get_child(GTK_BIN(c->chk_edit_by_area))), PANGO_ELLIPSIZE_START);
2338 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->chk_edit_by_area), c->edit_by_area);
2339 gtk_widget_set_tooltip_text(c->chk_edit_by_area, _(
"edit the curve nodes by area"));
2340 gtk_box_pack_start(GTK_BOX(hbox_select_by), c->chk_edit_by_area,
TRUE,
TRUE, 0);
2346 gtk_widget_set_tooltip_text(c->bt_showmask, _(
"display selection"));
2348 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->bt_showmask),
FALSE);
2349 gtk_box_pack_end(GTK_BOX(hbox_select_by), c->bt_showmask,
FALSE,
FALSE, 0);
2351 gtk_box_pack_start(GTK_BOX(self->
widget), hbox_select_by,
TRUE,
TRUE, 0);
2356 gtk_widget_set_tooltip_text(c->select_by, _(
"choose selection criterion, will be the abscissa in the graph"));
2359 gtk_widget_set_tooltip_text(c->mode, _(
"choose between a smoother or stronger effect"));
2363 gtk_widget_set_tooltip_text(c->strength, _(
"make effect stronger or weaker"));
2365 gtk_widget_add_events(GTK_WIDGET(c->area), GDK_POINTER_MOTION_MASK
2366 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
2367 | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK
2369 g_object_set_data(G_OBJECT(c->area),
"iop-instance", self);
2370 gtk_widget_set_can_focus(GTK_WIDGET(c->area),
TRUE);
2381 gtk_widget_add_events(GTK_WIDGET(c->bottom_area), GDK_BUTTON_PRESS_MASK);
2396 gtk_box_pack_start(GTK_BOX(self->
widget), c->interpolator,
TRUE,
TRUE, 0);
2397 gtk_widget_set_tooltip_text(c->interpolator,
2398 _(
"change this method if you see oscillations or cusps in the curve\n"
2399 "- cubic spline is better to produce smooth curves but oscillates when nodes are too close\n"
2400 "- centripetal is better to avoids cusps and oscillations with close nodes but is less smooth\n"
2401 "- monotonic is better for accuracy of pure analytical functions (log, gamma, exp)\n"));
2414 gtk_widget_queue_draw(self->
widget);
2420 dt_conf_set_int(
"plugins/darkroom/colorzones/gui_channel", c->channel);
2431 const int program = 2;
2462 printf(
"p.channel = %d;\n",
p->channel);
2465 printf(
"p.curve[%d][%i].x = %f;\n",
k,
i,
p->curve[
k][
i].x);
2466 printf(
"p.curve[%d][%i].y = %f;\n",
k,
i,
p->curve[
k][
i].y);
2480 if(
d->curve_type[
ch] !=
p->curve_type[
ch] ||
d->curve_nodes[
ch] !=
p->curve_num_nodes[
ch])
2484 d->curve_nodes[
ch] =
p->curve_num_nodes[
ch];
2485 d->curve_type[
ch] =
p->curve_type[
ch];
2493 for(
int k = 0;
k <
p->curve_num_nodes[
ch];
k++)
2509 for(
int k = 0;
k <
p->curve_num_nodes[
ch];
k++)
2525 if(
d->curve_type[
ch] !=
p->curve_type[
ch] ||
d->curve_nodes[
ch] !=
p->curve_num_nodes[
ch]
2526 ||
d->curve[
ch]->c.m_numAnchors !=
p->curve_num_nodes[
ch])
2530 d->curve_nodes[
ch] =
p->curve_num_nodes[
ch];
2531 d->curve_type[
ch] =
p->curve_type[
ch];
2533 for(
int k = 0;
k <
p->curve_num_nodes[
ch];
k++)
2538 for(
int k = 0;
k <
p->curve_num_nodes[
ch];
k++)
2563 d->mode = default_params->
mode;
2579 module->params = calloc(1, sizeof(dt_iop_colorzones_params_t));
2580 module->default_params = calloc(1, sizeof(dt_iop_colorzones_params_t));
2581 module->default_enabled = 0;
2582 module->params_size = sizeof(dt_iop_colorzones_params_t);
2583 module->gui_data = NULL;
2584 module->request_histogram |= (DT_REQUEST_ON);
2589#undef DT_IOP_COLORZONES_INSET
2590#undef DT_IOP_COLORZONES_CURVE_INFL
2591#undef DT_IOP_COLORZONES_RES
2592#undef DT_IOP_COLORZONES_LUT_RES
2593#undef DT_IOP_COLORZONES_BANDS
2594#undef DT_IOP_COLORZONES_MAXNODES
2595#undef DT_IOP_COLORZONES_DEFAULT_STEP
2596#undef DT_IOP_COLORZONES_MIN_X_DISTANCE
static double dist(double x1, double y1, double x2, double y2)
static void error(char *msg)
int dt_bauhaus_combobox_get(GtkWidget *widget)
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
void dt_bauhaus_combobox_remove_at(GtkWidget *widget, int pos)
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)
@ DEVELOP_BLEND_CS_RGB_DISPLAY
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
static float lookup(read_only image2d_t lut, const float x)
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_COLOR_PICKER_POINT_AREA
@ DT_LIB_COLORPICKER_STATISTIC_MAX
@ DT_LIB_COLORPICKER_STATISTIC_MIN
@ DT_LIB_COLORPICKER_STATISTIC_MEAN
static dt_aligned_pixel_t rgb
const dt_aligned_pixel_t f
static const float const float const float min
const dt_colormatrix_t dt_aligned_pixel_t out
static const float const float C
static gboolean _area_draw_callback(GtkWidget *widget, cairo_t *crf, dt_iop_module_t *self)
#define DT_COLORZONES_CELLSI
static void _reset_parameters(dt_iop_colorzones_params_t *p, const int channel, const int splines_version)
static void _edit_by_area_callback(GtkWidget *widget, dt_iop_module_t *self)
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)
#define DT_IOP_COLORZONES_RES
void init(dt_iop_module_t *module)
const char ** description(struct dt_iop_module_t *self)
static gboolean _bottom_area_button_press_callback(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self)
#define DT_IOP_COLORZONES_INSET
static gboolean _area_key_press_callback(GtkWidget *widget, GdkEventKey *event, dt_iop_module_t *self)
__DT_CLONE_TARGETS__ void process_v1(struct dt_iop_module_t *self, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
static gboolean _area_leave_notify_callback(GtkWidget *widget, GdkEventCrossing *event, dt_iop_module_t *self)
static void _reset_nodes(dt_iop_colorzones_params_t *p, const int ch, const _Bool touch_edges)
#define DT_COLORZONES_CELLSJ
static void _reset_display_selection(dt_iop_module_t *self)
static void _delete_node(dt_iop_module_t *self, dt_iop_colorzones_node_t *curve, int *nodes, int node, gboolean zero)
void gui_focus(struct dt_iop_module_t *self, gboolean in)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static float _mouse_to_curve(const float x, const float zoom_factor, const float offset)
void gui_reset(struct dt_iop_module_t *self)
void gui_update(struct dt_iop_module_t *self)
dt_iop_colorzones_channel_t
@ DT_IOP_COLORZONES_MAX_CHANNELS
static void dt_iop_colorzones_get_params(dt_iop_colorzones_params_t *p, dt_iop_colorzones_gui_data_t *c, const int ch, const double mouse_x, const double mouse_y, const float radius)
static void _interpolator_callback(GtkWidget *widget, dt_iop_module_t *self)
static float strength(float value, float strength)
void gui_init(struct dt_iop_module_t *self)
static gboolean _area_button_release_callback(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
#define DT_IOP_COLORZONES_MIN_X_DISTANCE
__DT_CLONE_TARGETS__ void process_display(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
#define DT_IOP_COLORZONES_BANDS
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
static gboolean _area_enter_notify_callback(GtkWidget *widget, GdkEventCrossing *event, dt_iop_module_t *self)
static int _select_base_display_color(dt_iop_module_t *self, float *picked_color, float *picker_min, float *picker_max)
void cleanup_global(dt_iop_module_so_t *module)
static void _draw_color_picker(dt_iop_module_t *self, cairo_t *cr, dt_iop_colorzones_params_t *p, dt_iop_colorzones_gui_data_t *c, const int width, const int height, const float *const picker_color, const float *const picker_min, const float *const picker_max)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
#define DT_IOP_COLORZONES_MAXNODES
void gui_cleanup(struct dt_iop_module_t *self)
static gboolean _area_button_press_callback(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self)
void init_presets(dt_iop_module_so_t *self)
__DT_CLONE_TARGETS__ void process_v3(struct dt_iop_module_t *self, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
#define COLORZONES_DRAW_BACKGROUD_BOX
static gboolean _area_scrolled_callback(GtkWidget *widget, GdkEventScroll *event, dt_iop_module_t *self)
#define DT_IOP_COLORZONES_LUT_RES
static gboolean _move_point_internal(dt_iop_module_t *self, GtkWidget *widget, int node, float dx, float dy, guint state)
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 int _add_node(dt_iop_colorzones_node_t *curve, int *nodes, float x, float y)
#define DT_IOP_COLORZONES_DEFAULT_STEP
#define DT_IOP_COLORZONES1_BANDS
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
dt_iop_colorzones_modes_t
@ DT_IOP_COLORZONES_MODE_STRONG
@ DT_IOP_COLORZONES_MODE_SMOOTH
static gboolean _area_motion_notify_callback(GtkWidget *widget, GdkEventMotion *event, dt_iop_module_t *self)
static void _draw_background(cairo_t *cr, dt_iop_colorzones_params_t *p, dt_iop_colorzones_gui_data_t *c, const int select_by_picker, const int width, const int height, const float *picked_color)
static float _curve_to_mouse(const float x, const float zoom_factor, const float offset)
void init_global(dt_iop_module_so_t *module)
static gboolean _bottom_area_draw_callback(GtkWidget *widget, cairo_t *crf, dt_iop_module_t *self)
static gboolean _area_resized_callback(GtkWidget *widget, GdkEvent *event, gpointer user_data)
static gboolean _sanity_check(const float x, const int selected, const int nodes, const dt_iop_colorzones_node_t *curve)
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 _display_mask_callback(GtkToggleButton *togglebutton, dt_iop_module_t *module)
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void _channel_tabs_switch_callback(GtkNotebook *notebook, GtkWidget *page, guint page_num, dt_iop_module_t *self)
dt_iop_colorzones_splines_version_t
@ DT_IOP_COLORZONES_SPLINES_V1
@ DT_IOP_COLORZONES_SPLINES_V2
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
float dt_conf_get_float(const char *name)
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
void dt_control_log(const char *msg,...)
void dt_control_queue_redraw_widget(GtkWidget *widget)
threadsafe request of redraw of specific widget. Use this function if you need to redraw a specific w...
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_free_align(ptr)
static void * dt_calloc_align(size_t size)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Enable aggressive floating-point arithmetic optimizations, in denormals handling. Set through user pr...
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR__(...)
static const dt_aligned_pixel_simd_t value
static gboolean dt_modifier_is(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
#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_database_start_transaction(db)
#define dt_database_release_transaction(db)
#define dt_dev_add_history_item(dev, module, enable, redraw)
#define dt_dev_pixelpipe_update_history_main(dev)
gboolean dt_dev_pixelpipe_has_preview_output(const dt_develop_t *dev, const dt_dev_pixelpipe_t *pipe, const dt_iop_roi_t *roi)
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
static void dt_draw_curve_calc_values(dt_draw_curve_t *c, const float min, const float max, const int res, float *x, float *y)
static void dt_draw_histogram_8_zoomed(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel, const float zoom_factor, const float zoom_offset_x, const float zoom_offset_y, gboolean linear)
static float dt_draw_curve_calc_value(dt_draw_curve_t *c, const float x)
static void dt_draw_curve_destroy(dt_draw_curve_t *c)
static void dt_draw_curve_calc_values_V2(dt_draw_curve_t *c, const float min, const float max, const int res, float *x, float *y, const gboolean periodic)
static void dt_draw_curve_set_point(dt_draw_curve_t *c, const int num, const float x, const float y)
static int dt_draw_curve_add_point(dt_draw_curve_t *c, const float x, const float y)
static dt_draw_curve_t * dt_draw_curve_new(const float min, const float max, unsigned int type)
void dtgtk_cairo_paint_showmask(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_colorpicker(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
static guint dt_keys_mainpad_alternatives(const guint key_val)
Remap keypad keys to usual mainpad ones.
gboolean dt_gui_get_scroll_unit_delta(const GdkEventScroll *event, int *delta)
GtkWidget * dt_ui_resizable_drawing_area(GtkWidget *area, char *config_str, int default_height, int min_height)
Make a self-drawing widget (typically a GtkDrawingArea graph or scope) vertically resizable.
GtkWidget * dt_ui_notebook_page(GtkNotebook *notebook, const char *text, const char *tooltip)
GtkNotebook * dt_ui_notebook_new()
GdkModifierType dt_key_modifier_state()
static cairo_surface_t * dt_cairo_image_surface_create(cairo_format_t format, int width, int height)
#define DT_GUI_BOX_SPACING
#define DT_PIXEL_APPLY_DPI(value)
void dt_gui_presets_add_generic(const char *name, dt_dev_operation_t op, const int32_t version, const void *params, const int32_t params_size, const int32_t enabled, const dt_develop_blend_colorspace_t blend_cst)
void dt_gui_throttle_cancel(gpointer source)
void dt_gui_throttle_queue(gpointer source, dt_gui_throttle_callback_t callback, gpointer user_data)
static void dt_iop_image_copy_by_size(float *const __restrict__ out, const float *const __restrict__ in, const size_t width, const size_t height, const size_t ch)
void dt_iop_throttled_history_update(gpointer data)
void dt_iop_request_focus(dt_iop_module_t *module)
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_MODULE
@ 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)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_output_profile_info(const struct dt_dev_pixelpipe_t *pipe)
void dt_ioppr_transform_image_colorspace(struct dt_iop_module_t *self, const float *const image_in, float *const image_out, const int width, const int height, const int cst_from, const int cst_to, int *converted_cst, const dt_iop_order_iccprofile_info_t *const profile_info)
void dt_ioppr_transform_image_colorspace_rgb(const float *const restrict image_in, float *const restrict image_out, const int width, const int height, const dt_iop_order_iccprofile_info_t *const profile_info_from, const dt_iop_order_iccprofile_info_t *const profile_info_to, const char *message)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_iop_work_profile_info(struct dt_iop_module_t *module, GList *iop_list)
dt_iop_colorzones_channel_t
#define DT_IOP_COLORZONES_BANDS
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)
void * dt_opencl_copy_host_to_device(const int devid, void *host, const int width, const int height, const int bpp)
void dt_opencl_release_mem_object(cl_mem mem)
struct _GtkWidget GtkWidget
const float uint32_t state[4]
struct dt_gui_gtk_t * gui
const struct dt_database_t * db
struct dt_bauhaus_t * bauhaus
struct dt_develop_t * develop
lib_colorpicker_sample_statistics scope
dt_dev_request_flags_t request_histogram
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_dev_pixelpipe_type_t type
struct dt_develop_t::@19 color_picker
Authoritative darkroom color-picker state.
struct dt_iop_module_t * gui_module
struct dt_dev_pixelpipe_t * pipe
dt_draw_curve_t * curve[DT_IOP_COLORZONES_MAX_CHANNELS]
dt_iop_colorzones_channel_t channel
int curve_type[DT_IOP_COLORZONES_MAX_CHANNELS]
int curve_nodes[DT_IOP_COLORZONES_MAX_CHANNELS]
GtkWidget * colorpicker_set_values
GtkWidget * chk_edit_by_area
dt_draw_curve_t * minmax_curve[DT_IOP_COLORZONES_MAX_CHANNELS]
float draw_ys[DT_IOP_COLORZONES_MAX_CHANNELS][256]
int minmax_curve_type[DT_IOP_COLORZONES_MAX_CHANNELS]
int minmax_curve_nodes[DT_IOP_COLORZONES_MAX_CHANNELS]
dt_iop_colorzones_channel_t channel
GtkNotebook * channel_tabs
dt_iop_colorzones_modes_t mode
dt_iop_colorzones_channel_t channel
int curve_type[DT_IOP_COLORZONES_MAX_CHANNELS]
dt_iop_colorzones_node_t curve[DT_IOP_COLORZONES_MAX_CHANNELS][20]
int curve_num_nodes[DT_IOP_COLORZONES_MAX_CHANNELS]
GModule *dt_dev_operation_t op
dt_iop_global_data_t * data
dt_dev_request_colorpick_flags_t request_color_pick
GtkDarktableToggleButton * off
dt_iop_params_t * default_params
struct dt_develop_t * dev
dt_iop_gui_data_t * gui_data
uint32_t histogram_max[4]
dt_iop_global_data_t * global_data
dt_aligned_pixel_t picked_color_min
dt_aligned_pixel_t picked_color_max
dt_iop_colorspace_type_t histogram_cst
dt_aligned_pixel_t picked_color
Region of interest passed through the pixelpipe.