96#define DT_IOP_COLORZONES_INSET DT_PIXEL_APPLY_DPI(5)
97#define DT_IOP_COLORZONES_CURVE_INFL .3f
98#define DT_IOP_COLORZONES_RES 256
99#define DT_IOP_COLORZONES_LUT_RES 0x10000
101#define DT_IOP_COLORZONES_BANDS 8
103#define DT_IOP_COLORZONES_MAXNODES 20
104#define DT_IOP_COLORZONES_DEFAULT_STEP (0.001f)
106#define DT_IOP_COLORZONES_MIN_X_DISTANCE 0.0025f
197 return _(
"color _zones");
204 _(
"linear or non-linear, Lab, display-referred"),
205 _(
"non-linear, Lab"),
206 _(
"non-linear, Lab, display-referred"));
225 const int new_version)
227#define DT_IOP_COLORZONES1_BANDS 6
229 if(old_version == 1 && new_version == 5)
231 typedef struct dt_iop_colorzones_params1_t
235 } dt_iop_colorzones_params1_t;
237 const dt_iop_colorzones_params1_t *old = old_params;
243 for(
int i = 0;
i < 3;
i++)
245 new->curve[
i][0].x = old->equalizer_x[
i][0];
246 new->curve[
i][0].y = old->equalizer_y[
i][0];
249 for(
int i = 0;
i < 3;
i++)
250 for(
int k = 0;
k < 6;
k++)
254 new->curve[
i][
k + 1].x = old->equalizer_x[
i][
k] + 0.001f;
256 new->curve[
i][
k + 1].x = old->equalizer_x[
i][
k] - 0.001f;
258 new->curve[
i][
k + 1].x = old->equalizer_x[
i][
k];
259 new->curve[
i][
k + 1].y = old->equalizer_y[
i][
k];
263 for(
int i = 0;
i < 3;
i++)
265 new->curve[
i][7].x = old->equalizer_x[
i][5];
266 new->curve[
i][7].y = old->equalizer_y[
i][5];
268 for(
int c = 0; c < 3; c++)
273 new->strength = 0.0f;
278 if(old_version == 2 && new_version == 5)
280 typedef struct dt_iop_colorzones_params2_t
284 } dt_iop_colorzones_params2_t;
286 const dt_iop_colorzones_params2_t *old = old_params;
291 for(
int c = 0; c < 3; c++)
293 new->curve[c][b].x = old->equalizer_x[c][b];
294 new->curve[c][b].y = old->equalizer_y[c][b];
296 for(
int c = 0; c < 3; c++)
301 new->strength = 0.0f;
306 if(old_version == 3 && new_version == 5)
308 typedef struct dt_iop_colorzones_params3_t
313 } dt_iop_colorzones_params3_t;
315 const dt_iop_colorzones_params3_t *old = old_params;
321 for(
int c = 0; c < 3; c++)
323 new->curve[c][b].x = old->equalizer_x[c][b];
324 new->curve[c][b].y = old->equalizer_y[c][b];
327 for(
int c = 0; c < 3; c++)
332 new->strength = old->strength;
337 if(old_version == 4 && new_version == 5)
339 typedef struct dt_iop_colorzones_params4_t
347 } dt_iop_colorzones_params4_t;
349 const dt_iop_colorzones_params4_t *old = old_params;
357 new->curve[c][
i].x = old->curve[c][
i].x;
358 new->curve[c][
i].y = old->curve[c][
i].y;
363 new->curve_num_nodes[c] = old->curve_num_nodes[c];
364 new->curve_type[c] = old->curve_type[c];
366 new->strength = old->strength;
367 new->mode = old->mode;
371#undef DT_IOP_COLORZONES1_BANDS
378 return (
x - offset) * zoom_factor;
383 return (
x / zoom_factor) + offset;
388 const int ch,
const double mouse_x,
const double mouse_y,
391 const int bands =
p->curve_num_nodes[
ch];
393 const float lin_mouse_x =
_mouse_to_curve(mouse_x, c->zoom_factor, c->offset_x);
394 const float lin_mouse_y =
_mouse_to_curve(mouse_y, c->zoom_factor, c->offset_y);
396 const float rad = radius / c->zoom_factor;
401 for(
int k = 1;
k < bands - 1;
k++)
403 const float f = expf(-(lin_mouse_x -
p->curve[
ch][
k].x) * (lin_mouse_x -
p->curve[
ch][
k].x) / (rad * rad));
404 p->curve[
ch][
k].y = (1.f -
f) *
p->curve[
ch][
k].y +
f * lin_mouse_y;
406 const int m = bands - 1;
407 const float mind = fminf((lin_mouse_x -
p->curve[
ch][0].x) * (lin_mouse_x -
p->curve[
ch][0].x),
408 (lin_mouse_x -
p->curve[
ch][
m].x) * (lin_mouse_x -
p->curve[
ch][
m].x));
409 const float f = expf(-mind / (rad * rad));
410 p->curve[
ch][0].y = (1.f -
f) *
p->curve[
ch][0].y +
f * lin_mouse_y;
411 p->curve[
ch][
m].y = (1.f -
f) *
p->curve[
ch][
m].y +
f * lin_mouse_y;
415 for(
int k = 0;
k < bands;
k++)
417 const float f = expf(-(lin_mouse_x -
p->curve[
ch][
k].x) * (lin_mouse_x -
p->curve[
ch][
k].x) / (rad * rad));
418 p->curve[
ch][
k].y = (1.f -
f) *
p->curve[
ch][
k].y +
f * lin_mouse_y;
428 return lut[bin1] *
f +
lut[bin0] * (1.f -
f);
445 const float normalize_C = 1.f / (128.0f * sqrtf(2.f));
451 for(
size_t k = 0;
k < (size_t)roi_out->
width * roi_out->
height;
k++)
453 float *in = (
float *)ivoid +
ch *
k;
458 dt_Lab_2_LCH(in, LCh);
464 select = LCh[0] * 0.01f;
467 select = LCh[1] * normalize_C;
474 select = CLAMP(select, 0.f, 1.f);
476 out[3] = fabsf(
lookup(
d->lut[display_channel], select) - .5f) * 4.f;
477 out[3] = CLAMP(
out[3], 0.f, 1.f);
491 const float normalize_C = 1.f / (128.0f * sqrtf(2.f));
493 for(
size_t k = 0;
k < (size_t)roi_out->
width * roi_out->
height;
k++)
495 float *in = (
float *)ivoid +
ch *
k;
500 dt_Lab_2_LCH(in, LCh);
506 select = LCh[0] * 0.01f;
509 select = LCh[1] * normalize_C;
516 select = CLAMP(select, 0.f, 1.f);
518 LCh[0] *= powf(2.0f, 4.0f * (
lookup(
d->lut[0], select) - .5f));
519 LCh[1] *= 2.f *
lookup(
d->lut[1], select);
520 LCh[2] +=
lookup(
d->lut[2], select) - .5f;
522 dt_LCH_2_Lab(LCh,
out);
535 for(
size_t k = 0;
k < (size_t)roi_out->
width * roi_out->
height;
k++)
537 float *in = (
float *)ivoid +
ch *
k;
539 const float a = in[1], b = in[2];
541 const float C = sqrtf(b * b + a * a);
547 select = fminf(1.0f, in[0] / 100.0f);
550 select = fminf(1.0f,
C / 128.0f);
555 blend = powf(1.0f -
C / 128.0f, 2.0f);
558 const float Lm = (blend * .5f + (1.0f - blend) *
lookup(
d->lut[0], select)) - .5f;
559 const float hm = (blend * .5f + (1.0f - blend) *
lookup(
d->lut[2], select)) - .5f;
562 const float Cm = 2.0f *
lookup(
d->lut[1], select);
563 const float L = in[0] * powf(2.0f, 4.0f * Lm);
596 cl_mem dev_L, dev_a, dev_b = NULL;
599 const int devid = pipe->
devid;
602 const int kernel_colorzones
621 if(err != CL_SUCCESS)
goto error;
639 const int version = 5;
663 for(
int c = 0; c < 3; c++)
669 version, &
p,
sizeof(
p), 1);
686 for(
int c = 0; c < 3; c++)
692 version, &
p,
sizeof(
p), 1);
709 for(
int c = 0; c < 3; c++)
715 version, &
p,
sizeof(
p), 1);
730 for(
int c = 0; c < 3; c++)
736 version, &
p,
sizeof(
p), 1);
761 for(
int c = 0; c < 3; c++)
767 version, &
p,
sizeof(
p), 1);
770 const int colorzones_bands_hsl = 8;
772 for(
int k = 0;
k < colorzones_bands_hsl;
k++)
781 for(
int c = 0; c < 3; c++)
783 p.curve_num_nodes[c] = colorzones_bands_hsl;
787 version, &
p,
sizeof(
p), 1);
799 c->display_mask =
FALSE;
802 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->bt_showmask)))
805 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->bt_showmask),
FALSE);
813 for(
int k = 0;
k <
p->curve_num_nodes[
ch];
k++)
816 p->curve[
ch][
k].x = (float)
k / (
float)(
p->curve_num_nodes[
ch] - 1);
818 p->curve[
ch][
k].x = ((float)
k + 0.5f) / (float)
p->curve_num_nodes[
ch];
819 p->curve[
ch][
k].y = 0.5f;
827 p->curve_num_nodes[
ch] = 2;
832 p->channel = channel;
834 p->splines_version = splines_version;
842 if(!select_by_picker)
847 dt_sRGB_to_XYZ(
rgb, xyz);
849 dt_Lab_2_LCH(lab, picked_color);
851 picker_max[0] = picker_min[0] = picked_color[0];
852 picker_max[1] = picker_min[1] = picked_color[1];
853 picker_max[2] = picker_min[2] = picked_color[2];
857 for(
int k = 0;
k < 3;
k++)
864 return select_by_picker;
869 const float *
const picker_color,
const float *
const picker_min,
870 const float *
const picker_max)
873 ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->colorpicker)) ||
874 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->colorpicker_set_values)) ))
890 for(; samples; samples = g_slist_next(samples))
892 sample = samples->data;
894 float picked_i = -1.0f;
895 float picked_min_i = -1.0f;
896 float picked_max_i = -1.0f;
899 for(
int k = 0;
k < 3;
k++)
905 pick_mean[3] = pick_min[3] = pick_max[3] = 1.f;
915 &converted_cst, work_profile);
917 &converted_cst, work_profile);
919 &converted_cst, work_profile);
921 dt_Lab_2_LCH(pick_mean, pick_mean);
922 dt_Lab_2_LCH(pick_min, pick_min);
923 dt_Lab_2_LCH(pick_max, pick_max);
929 picked_i = pick_mean[0] / 100.0f;
930 picked_min_i = pick_min[0] / 100.0f;
931 picked_max_i = pick_max[0] / 100.0f;
934 picked_i = pick_mean[1] / (128.0f * sqrtf(2.f));
935 picked_min_i = pick_min[1] / (128.0f * sqrtf(2.f));
936 picked_max_i = pick_max[1] / (128.0f * sqrtf(2.f));
939 picked_i = pick_mean[2];
940 picked_min_i = pick_min[2];
941 picked_max_i = pick_max[2];
947 picked_min_i =
_curve_to_mouse(picked_min_i, c->zoom_factor, c->offset_x);
948 picked_max_i =
_curve_to_mouse(picked_max_i, c->zoom_factor, c->offset_x);
950 cairo_set_source_rgba(cr, 0.5, 0.7, 0.5, 0.15);
951 cairo_rectangle(cr,
width * picked_min_i, 0,
width * fmax(picked_max_i - picked_min_i, 0.0f),
height);
953 cairo_set_source_rgba(cr, 0.5, 0.7, 0.5, 0.5);
954 cairo_move_to(cr,
width * picked_i, 0);
963 ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->colorpicker)) ||
964 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->colorpicker_set_values)) ))
967 float picked_i = -1.0f;
968 float picked_min_i = -1.0f;
969 float picked_max_i = -1.0f;
974 picked_i = picker_color[0] / 100.0f;
975 picked_min_i = picker_min[0] / 100.0f;
976 picked_max_i = picker_max[0] / 100.0f;
979 picked_i = picker_color[1] / (128.0f * sqrtf(2.f));
980 picked_min_i = picker_min[1] / (128.0f * sqrtf(2.f));
981 picked_max_i = picker_max[1] / (128.0f * sqrtf(2.f));
984 picked_i = picker_color[2];
985 picked_min_i = picker_min[2];
986 picked_max_i = picker_max[2];
991 picked_min_i =
_curve_to_mouse(picked_min_i, c->zoom_factor, c->offset_x);
992 picked_max_i =
_curve_to_mouse(picked_max_i, c->zoom_factor, c->offset_x);
996 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.25);
997 cairo_rectangle(cr,
width * picked_min_i, 0,
width * fmax(picked_max_i - picked_min_i, 0.0),
height);
1000 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
1001 cairo_set_operator(cr, CAIRO_OPERATOR_XOR);
1003 cairo_move_to(cr,
width * picked_i, 0.0);
1012#define DT_COLORZONES_CELLSI 64
1014#define DT_COLORZONES_CELLSJ 36
1016#define COLORZONES_DRAW_BACKGROUD_BOX \
1017 dt_aligned_pixel_t Lab; \
1018 dt_LCH_2_Lab(LCh, Lab); \
1019 const float L0 = Lab[0]; \
1021 const float Lwhite = 100.0f, Lclip = 20.0f; \
1022 const float Lcap = fminf(100.0f, Lab[0]); \
1025 - (Lcap - L0) * (1.0f / 100.0f) * fminf(Lwhite - Lclip, fmaxf(0.0f, Lab[0] - Lclip)) / (Lwhite - Lclip); \
1026 const float clip2 = clip * clip * clip; \
1027 Lab[1] *= Lab[0] / L0 * clip2; \
1028 Lab[2] *= Lab[0] / L0 * clip2; \
1030 dt_aligned_pixel_t xyz; \
1031 dt_aligned_pixel_t rgb; \
1032 dt_Lab_to_XYZ(Lab, xyz); \
1033 dt_XYZ_to_sRGB(xyz, rgb); \
1035 cairo_set_source_rgb(cr, rgb[0], rgb[1], rgb[2]);
1038 const int select_by_picker,
const int width,
const int height,
1039 const float *picked_color)
1041 const float bg_sat_factor =
dt_conf_get_float(
"plugins/darkroom/colorzones/bg_sat_factor");
1042 const float normalize_C = (128.f * bg_sat_factor * sqrtf(2.f));
1047 for(
int j = 0; j < cellsj; j++)
1049 for(
int i = 0;
i < cellsi;
i++)
1053 const float jj =
_mouse_to_curve(1.0f - ((
float)j - .5f) / (
float)(cellsj - 1), c->zoom_factor, c->offset_y);
1055 =
_mouse_to_curve(1.0f - (((
float)j / (
float)(cellsj - 1))), c->zoom_factor, c->offset_y) + .5f;
1056 const float ii =
_mouse_to_curve(((
float)
i + .5f) / (
float)(cellsi - 1), c->zoom_factor, c->offset_x);
1057 const float iih =
_mouse_to_curve((
float)
i / (
float)(cellsi - 1), c->zoom_factor, c->offset_x);
1064 LCh[0] = 100.0f * ii;
1065 LCh[1] = normalize_C * .5f;
1066 LCh[2] = picked_color[2];
1070 LCh[1] = picked_color[1] * 2.f * bg_sat_factor * ii;
1071 LCh[2] = picked_color[2];
1075 LCh[1] = normalize_C * .5f;
1087 LCh[0] += -50.0f + 100.0f * jj;
1099 cairo_rectangle(cr,
width *
i / (
float)cellsi,
height * j / (
float)cellsj,
width / (
float)cellsi,
1115 if(c->minmax_curve_type[
ch] !=
p.curve_type[
ch] || c->minmax_curve_nodes[
ch] !=
p.curve_num_nodes[
ch])
1119 c->minmax_curve_nodes[
ch] =
p.curve_num_nodes[
ch];
1120 c->minmax_curve_type[
ch] =
p.curve_type[
ch];
1124 p.curve[
ch][
p.curve_num_nodes[
ch] - 2].y);
1128 for(
int k = 0;
k <
p.curve_num_nodes[
ch];
k++)
1134 p.curve[
ch][
p.curve_num_nodes[
ch] - 1].y);
1140 p.curve[
ch][
p.curve_num_nodes[
ch] - 2].y);
1144 for(
int k = 0;
k <
p.curve_num_nodes[
ch];
k++)
1151 p.curve[
ch][
p.curve_num_nodes[
ch] - 1].y);
1160 if(c->minmax_curve_type[
ch] !=
p.curve_type[
ch] || c->minmax_curve_nodes[
ch] !=
p.curve_num_nodes[
ch]
1161 || c->minmax_curve[
ch]->c.m_numAnchors !=
p.curve_num_nodes[
ch])
1165 c->minmax_curve_nodes[
ch] =
p.curve_num_nodes[
ch];
1166 c->minmax_curve_type[
ch] =
p.curve_type[
ch];
1168 for(
int k = 0;
k <
p.curve_num_nodes[
ch];
k++)
1173 for(
int k = 0;
k <
p.curve_num_nodes[
ch];
k++)
1181 const int ch = (int)c->channel;
1183 GtkAllocation allocation;
1184 gtk_widget_get_allocation(widget, &allocation);
1186 int width = allocation.width,
height = allocation.height;
1188 cairo_t *cr = cairo_create(cst);
1192 GtkStyleContext *context = gtk_widget_get_style_context(widget);
1193 gboolean color_found = gtk_style_context_lookup_color(context,
"graph_overlay", &
color);
1201 gdk_cairo_set_source_rgba(cr, &
color);
1204 cairo_translate(cr, inset, inset);
1209 cairo_set_source_rgb(cr, .1, .1, .1);
1213 cairo_set_source_rgb(cr, .3, .3, .3);
1223 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
1227 cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT);
1236 const int ch_hist =
p.channel;
1238 const gboolean is_linear =
FALSE;
1239 const float hist_max = is_linear ? self->
histogram_max[ch_hist]
1244 cairo_translate(cr, 0,
height);
1247 cairo_set_source_rgba(cr, .2, .2, .2, 0.5);
1249 c->offset_y * hist_max, is_linear);
1261 cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
1264 for(
int k = 0;
k <
p.curve_num_nodes[
ch];
k++)
1269 cairo_rel_line_to(cr, -arrw * .5f, 0);
1270 cairo_rel_line_to(cr, arrw * .5f, -arrw);
1271 cairo_rel_line_to(cr, arrw * .5f, arrw);
1272 cairo_close_path(cr);
1280 cairo_translate(cr, 0,
height);
1283 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1287 const int ch_inv = ((int)c->channel +
i + 1) % 3;
1290 cairo_set_source_rgba(cr, .7, .7, .7, 1.0);
1292 cairo_set_source_rgba(cr, .7, .7, .7, 0.3);
1294 cairo_move_to(cr, 0, -
height *
_curve_to_mouse(c->draw_ys[ch_inv][0], c->zoom_factor, c->offset_y));
1298 const float yy = c->draw_ys[ch_inv][
k];
1311 cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
1313 for(
int k = 0;
k <
p.curve_num_nodes[
ch];
k++)
1322 if(c->edit_by_area && (c->mouse_y > 0 || c->dragging))
1324 const int bands =
p.curve_num_nodes[
ch];
1334 for(
int k = 0;
k < bands;
k++)
1344 for(
int k = 0;
k < bands;
k++)
1358 for(
int k = 0;
k < bands;
k++)
1368 for(
int k = 0;
k < bands;
k++)
1378 cairo_set_source_rgba(cr, .7, .7, .7, .6);
1384 const float yy = c->draw_min_ys[
k];
1395 const float yy = c->draw_max_ys[
k];
1403 cairo_close_path(cr);
1407 cairo_set_source_rgba(cr, .9, .9, .9, .5);
1410 const float x = c->mouse_x, y =
_curve_to_mouse(c->draw_ys[
ch][
k], c->zoom_factor, c->offset_y);
1420 if(c->selected >= 0)
1422 cairo_set_source_rgb(cr, .9, .9, .9);
1423 const float x =
_curve_to_mouse(
p.curve[c->channel][c->selected].x, c->zoom_factor, c->offset_x),
1424 y =
_curve_to_mouse(
p.curve[c->channel][c->selected].y, c->zoom_factor, c->offset_y);
1431 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
1434 cairo_set_source_surface(crf, cst, 0, 0);
1436 cairo_surface_destroy(cst);
1445 GtkAllocation allocation;
1446 gtk_widget_get_allocation(widget, &allocation);
1448 int width = allocation.width,
height = allocation.height;
1450 cairo_t *cr = cairo_create(cst);
1453 GtkStyleContext *context = gtk_widget_get_style_context(widget);
1454 gboolean color_found = gtk_style_context_lookup_color(context,
"graph_overlay", &
color);
1462 gdk_cairo_set_source_rgba(cr, &
color);
1465 cairo_translate(cr, inset, inset);
1470 cairo_set_source_rgb(cr, .1, .1, .1);
1474 cairo_set_source_rgb(cr, .3, .3, .3);
1483 const float normalize_C = (128.f * sqrtf(2.f));
1485 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
1489 for(
int i = 0;
i < cellsi;
i++)
1491 const float ii =
_mouse_to_curve(((
float)
i + .5f) / (
float)(cellsi - 1), c->zoom_factor, c->offset_x);
1492 const float iih =
_mouse_to_curve((
float)
i / (
float)(cellsi - 1), c->zoom_factor, c->offset_x);
1500 LCh[0] = 100.0f * ii;
1501 LCh[1] = normalize_C * .5f;
1502 LCh[2] = picked_color[2];
1506 LCh[1] = picked_color[1] * 2.f * ii;
1507 LCh[2] = picked_color[2];
1511 LCh[1] = normalize_C * .5f;
1518 cairo_rectangle(cr,
width *
i / (
float)cellsi, 0,
width / (
float)cellsi,
height);
1522 cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT);
1529 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
1532 cairo_set_source_surface(crf, cst, 0, 0);
1534 cairo_surface_destroy(cst);
1538#undef COLORZONES_DRAW_BACKGROUD_BOX
1539#undef DT_COLORZONES_CELLSI
1540#undef DT_COLORZONES_CELLSJ
1546 if(event->button == 1 && event->type == GDK_2BUTTON_PRESS)
1549 c->zoom_factor = 1.f;
1550 c->offset_x = c->offset_y = 0.f;
1552 gtk_widget_queue_draw(self->
gui->
widget);
1563 gboolean point_valid =
TRUE;
1569 point_valid =
FALSE;
1575 point_valid =
FALSE;
1586 int ch = c->channel;
1591 if(node == 0 || node ==
p->curve_num_nodes[
ch] - 1) dx = 0.f;
1593 float new_x = CLAMP(curve[node].
x + dx, 0.0f, 1.0f);
1594 const float new_y = CLAMP(curve[node].y + dy, 0.0f, 1.0f);
1600 curve[node].
x = new_x;
1601 curve[node].
y = new_y;
1607 curve[
p->curve_num_nodes[
ch] - 1].
x = 1.f - curve[node].
x;
1608 curve[
p->curve_num_nodes[
ch] - 1].
y = curve[node].
y;
1612 curve[0].
x = 1.f - curve[node].
x;
1613 curve[0].
y = curve[node].
y;
1632 curve[node].
x = new_x;
1633 curve[node].
y = new_y;
1639 gtk_widget_queue_draw(widget);
1648 curve[node].
y = 0.5f;
1655 for(
int k = node;
k < *nodes - 1;
k++)
1657 curve[
k].
x = curve[
k + 1].
x;
1658 curve[
k].
y = curve[
k + 1].
y;
1660 curve[*nodes - 1].
x = curve[*nodes - 1].
y = 0;
1671 gtk_widget_queue_draw(self->
gui->
widget);
1682 for(
int k = 1;
k < *nodes;
k++)
1703 curve[
i].
x = curve[
i - 1].
x;
1704 curve[
i].
y = curve[
i - 1].
y;
1723 if(c->selected < 0 && !c->edit_by_area)
return TRUE;
1731 const int bands =
p->curve_num_nodes[c->channel];
1732 c->mouse_radius = CLAMP(c->mouse_radius * (1.0 + 0.1 * delta_y), 0.2 / bands, 1.0);
1733 gtk_widget_queue_draw(widget);
1752 GtkAllocation allocation;
1753 gtk_widget_get_allocation(widget, &allocation);
1755 const int height = allocation.height - 2 * inset;
1756 const int width = allocation.width - 2 * inset;
1758 const int ch = c->channel;
1759 const int nodes =
p->curve_num_nodes[
ch];
1762 const double old_m_x = c->mouse_x;
1763 const double old_m_y = fabs(c->mouse_y);
1765 c->mouse_x = CLAMP(event->x - inset, 0,
width) / (float)
width;
1766 c->mouse_y = 1.0 - CLAMP(event->y - inset, 0,
height) / (float)
height;
1769 if(event->state & GDK_BUTTON1_MASK)
1773 if(c->dragging && c->x_move >= 0)
1774 c->selected = c->x_move;
1780 if(c->selected >= 0)
1783 const float translate_mouse_x = old_m_x -
_curve_to_mouse(curve[c->selected].
x, c->zoom_factor, c->offset_x);
1784 const float translate_mouse_y = old_m_y -
_curve_to_mouse(curve[c->selected].
y, c->zoom_factor, c->offset_y);
1786 const float dx =
_mouse_to_curve(c->mouse_x - translate_mouse_x, c->zoom_factor, c->offset_x)
1787 -
_mouse_to_curve(old_m_x - translate_mouse_x, c->zoom_factor, c->offset_x);
1788 const float dy =
_mouse_to_curve(c->mouse_y - translate_mouse_y, c->zoom_factor, c->offset_y)
1789 -
_mouse_to_curve(old_m_y - translate_mouse_y, c->zoom_factor, c->offset_y);
1807 else if(event->y >
height)
1810 const int bands =
p->curve_num_nodes[c->channel];
1811 const float mouse_x =
_mouse_to_curve(c->mouse_x, c->zoom_factor, c->offset_x);
1812 float dist = fabsf(
p->curve[c->channel][0].x - mouse_x);
1813 for(
int k = 1;
k < bands;
k++)
1815 const float d2 = fabsf(
p->curve[c->channel][
k].x - mouse_x);
1830 if(event->state & GDK_BUTTON1_MASK)
1832 if(nodes < DT_IOP_COLORZONES_MAXNODES && c->
selected == -1)
1834 const float linx =
_mouse_to_curve(c->mouse_x, c->zoom_factor, c->offset_x),
1838 c->selected =
_add_node(curve, &
p->curve_num_nodes[
ch], linx, liny);
1846 const float mx = c->mouse_x;
1847 const float my = c->mouse_y;
1850 float min = .04f * .04f;
1852 for(
int k = 0;
k < nodes;
k++)
1864 c->selected = nearest;
1866 if(c->selected >= 0) gtk_widget_grab_focus(widget);
1869 gtk_widget_queue_draw(widget);
1879 int ch = c->channel;
1880 int nodes =
p->curve_num_nodes[
ch];
1883 if(event->button == 1)
1895 GtkAllocation allocation;
1896 gtk_widget_get_allocation(widget, &allocation);
1897 const int height = allocation.height - 2 * inset;
1898 const int width = allocation.width - 2 * inset;
1900 c->mouse_x = CLAMP(event->x - inset, 0,
width) / (float)
width;
1901 c->mouse_y = 1.0 - CLAMP(event->y - inset, 0,
height) / (float)
height;
1903 const float mx =
_mouse_to_curve(c->mouse_x, c->zoom_factor, c->offset_x);
1911 for(
int k = 1;
k < nodes;
k++)
1925 if(y >= 0.0f && y <= 1.0f)
1931 const float min = .04f * .04f;
1933 for(
int k = 0;
k < nodes;
k++)
1935 const float other_y =
_curve_to_mouse(curve[
k].y, c->zoom_factor, c->offset_y);
1936 const float dist = (y - other_y) * (y - other_y);
1942 gtk_widget_queue_draw(self->
gui->
widget);
1947 else if(event->type == GDK_2BUTTON_PRESS)
1950 p->curve_num_nodes[
ch] =
d->curve_num_nodes[
ch];
1951 p->curve_type[
ch] =
d->curve_type[
ch];
1960 gtk_widget_queue_draw(self->
gui->
widget);
1965 else if(event->button == 3 && c->selected >= 0)
1973 curve[nodes - 1].
y = 0.5f;
1974 curve[nodes - 1].
x = 1.f;
1978 const float reset_value = c->selected == 0 ? 0.f : 1.f;
1979 curve[c->selected].
y = 0.5f;
1980 curve[c->selected].
x = reset_value;
1984 gtk_widget_queue_draw(self->
gui->
widget);
2001 if(event->button == 1)
2014 c->mouse_y = fabs(c->mouse_y);
2015 gtk_widget_queue_draw(widget);
2023 c->mouse_y = -fabs(c->mouse_y);
2024 gtk_widget_queue_draw(widget);
2031 GtkAllocation allocation;
2032 gtk_widget_get_allocation(widget, &allocation);
2033 r.width = allocation.width;
2034 r.height = allocation.width;
2035 gtk_widget_get_preferred_size(widget, &
r, NULL);
2043 if(c->selected < 0)
return FALSE;
2047 float dx = 0.0f, dy = 0.0f;
2048 if(
key == GDK_KEY_Up)
2053 else if(
key == GDK_KEY_Down)
2058 else if(
key == GDK_KEY_Right)
2063 else if(
key == GDK_KEY_Left)
2069 if(!handled)
return FALSE;
2092 gtk_widget_queue_draw(self->
gui->
widget);
2101 if(w ==
g->select_by)
2105 gtk_widget_queue_draw(GTK_WIDGET(
g->area));
2106 gtk_widget_queue_draw(GTK_WIDGET(
g->bottom_area));
2127 gtk_widget_queue_draw(GTK_WIDGET(
g->area));
2135 g->edit_by_area = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
2137 gtk_widget_queue_draw(GTK_WIDGET(
g->area));
2149 dt_control_log(_(
"cannot display masks when the blending mask is displayed"));
2152 gtk_toggle_button_set_active(togglebutton,
FALSE);
2157 g->display_mask = gtk_toggle_button_get_active(togglebutton);
2159 if(module->
gui->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->
gui->
off), 1);
2167 if(picker ==
g->colorpicker_set_values)
2172 const int ch_curve =
g->channel;
2173 const int ch_val =
p->channel;
2177 p->curve_num_nodes[ch_curve] =
d->curve_num_nodes[ch_curve];
2178 p->curve_type[ch_curve] =
d->curve_type[ch_curve];
2181 curve[
k].
x =
d->curve[ch_curve][
k].x;
2182 curve[
k].
y =
d->curve[ch_curve][
k].y;
2186 int picker_set_upper_lower;
2188 picker_set_upper_lower = 1;
2190 picker_set_upper_lower = -1;
2192 picker_set_upper_lower = 0;
2195 const float feather = 0.02f;
2196 const float increment = 0.1f * picker_set_upper_lower;
2206 if(
x > 0.f &&
x < 1.f)
_add_node(curve, &
p->curve_num_nodes[ch_curve],
x, .5f);
2214 if(
x > 0.f &&
x < 1.f)
_add_node(curve, &
p->curve_num_nodes[ch_curve],
x, .5f + increment);
2222 if(
x > 0.f &&
x < 1.f)
_add_node(curve, &
p->curve_num_nodes[ch_curve],
x, .5f + 2.f * increment);
2230 if(
x > 0.f &&
x < 1.f)
_add_node(curve, &
p->curve_num_nodes[ch_curve],
x, .5f + increment);
2239 if(
x > 0.f &&
x < 1.f)
_add_node(curve, &
p->curve_num_nodes[ch_curve],
x, .5f);
2253 c->zoom_factor = 1.f;
2272 c->channel =
dt_conf_get_int(
"plugins/darkroom/colorzones/gui_channel");
2276 c->minmax_curve_nodes[
ch] =
p->curve_num_nodes[
ch];
2277 c->minmax_curve_type[
ch] =
p->curve_type[
ch];
2279 for(
int k = 0;
k <
p->curve_num_nodes[
ch];
k++)
2283 c->mouse_x = c->mouse_y = -1.0;
2285 c->offset_x = c->offset_y = 0.f;
2286 c->zoom_factor = 1.f;
2290 c->edit_by_area = 0;
2291 c->display_mask =
FALSE;
2299 gtk_box_pack_start(GTK_BOX(vbox), hbox,
FALSE,
FALSE, 0);
2307 gtk_widget_show(gtk_notebook_get_nth_page(c->channel_tabs, c->channel));
2308 gtk_notebook_set_current_page(c->channel_tabs, c->channel);
2314 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(c->channel_tabs),
TRUE,
TRUE, 0);
2315 gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(
" "),
FALSE,
FALSE, 0);
2319 gtk_widget_set_tooltip_text(c->colorpicker, _(
"pick GUI color from image\nctrl+click or right-click to select an area"));
2325 gtk_widget_set_tooltip_text(c->colorpicker_set_values, _(
"create a curve based on an area from the image\n"
2326 "drag to create a flat curve\n"
2327 "ctrl+drag to create a positive curve\n"
2328 "shift+drag to create a negative curve"));
2331 c->area = GTK_DRAWING_AREA(gtk_drawing_area_new());
2332 gtk_widget_set_hexpand(GTK_WIDGET(c->area),
TRUE);
2334 gtk_box_pack_start(GTK_BOX(vbox),
2336 "plugins/darkroom/colorzones/graphheight", 280, 100),
2340 gtk_widget_set_name(GTK_WIDGET(dabox),
"iop-bottom-bar");
2341 c->bottom_area = gtk_drawing_area_new();
2342 gtk_box_pack_start(GTK_BOX(dabox), GTK_WIDGET(c->bottom_area),
TRUE,
TRUE, 0);
2343 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(dabox),
TRUE,
TRUE, 0);
2344 gtk_box_pack_start(GTK_BOX(self->
gui->
widget), GTK_WIDGET(vbox),
TRUE,
TRUE, 0);
2349 gchar *label = N_(
"edit by area");
2350 c->chk_edit_by_area = gtk_check_button_new_with_label(_(label));
2351 gtk_label_set_ellipsize(GTK_LABEL(gtk_bin_get_child(GTK_BIN(c->chk_edit_by_area))), PANGO_ELLIPSIZE_START);
2352 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->chk_edit_by_area), c->edit_by_area);
2353 gtk_widget_set_tooltip_text(c->chk_edit_by_area, _(
"edit the curve nodes by area"));
2354 gtk_box_pack_start(GTK_BOX(hbox_select_by), c->chk_edit_by_area,
TRUE,
TRUE, 0);
2360 gtk_widget_set_tooltip_text(c->bt_showmask, _(
"display selection"));
2362 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->bt_showmask),
FALSE);
2363 gtk_box_pack_end(GTK_BOX(hbox_select_by), c->bt_showmask,
FALSE,
FALSE, 0);
2370 gtk_widget_set_tooltip_text(c->select_by, _(
"choose selection criterion, will be the abscissa in the graph"));
2373 gtk_widget_set_tooltip_text(c->mode, _(
"choose between a smoother or stronger effect"));
2377 gtk_widget_set_tooltip_text(c->strength, _(
"make effect stronger or weaker"));
2379 gtk_widget_add_events(GTK_WIDGET(c->area), GDK_POINTER_MOTION_MASK
2380 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
2381 | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK
2383 g_object_set_data(G_OBJECT(c->area),
"iop-instance", self);
2384 gtk_widget_set_can_focus(GTK_WIDGET(c->area),
TRUE);
2395 gtk_widget_add_events(GTK_WIDGET(c->bottom_area), GDK_BUTTON_PRESS_MASK);
2411 gtk_widget_set_tooltip_text(c->interpolator,
2412 _(
"change this method if you see oscillations or cusps in the curve\n"
2413 "- cubic spline is better to produce smooth curves but oscillates when nodes are too close\n"
2414 "- centripetal is better to avoids cusps and oscillations with close nodes but is less smooth\n"
2415 "- monotonic is better for accuracy of pure analytical functions (log, gamma, exp)\n"));
2427 gtk_widget_queue_draw(self->
gui->
widget);
2433 dt_conf_set_int(
"plugins/darkroom/colorzones/gui_channel", c->channel);
2443 const int program = 2;
2474 printf(
"p.channel = %d;\n",
p->channel);
2477 printf(
"p.curve[%d][%i].x = %f;\n",
k,
i,
p->curve[
k][
i].x);
2478 printf(
"p.curve[%d][%i].y = %f;\n",
k,
i,
p->curve[
k][
i].y);
2492 if(
d->curve_type[
ch] !=
p->curve_type[
ch] ||
d->curve_nodes[
ch] !=
p->curve_num_nodes[
ch])
2496 d->curve_nodes[
ch] =
p->curve_num_nodes[
ch];
2497 d->curve_type[
ch] =
p->curve_type[
ch];
2505 for(
int k = 0;
k <
p->curve_num_nodes[
ch];
k++)
2521 for(
int k = 0;
k <
p->curve_num_nodes[
ch];
k++)
2537 if(
d->curve_type[
ch] !=
p->curve_type[
ch] ||
d->curve_nodes[
ch] !=
p->curve_num_nodes[
ch]
2538 ||
d->curve[
ch]->c.m_numAnchors !=
p->curve_num_nodes[
ch])
2542 d->curve_nodes[
ch] =
p->curve_num_nodes[
ch];
2543 d->curve_type[
ch] =
p->curve_type[
ch];
2545 for(
int k = 0;
k <
p->curve_num_nodes[
ch];
k++)
2550 for(
int k = 0;
k <
p->curve_num_nodes[
ch];
k++)
2581 d->mode = default_params->
mode;
2599 module->params = calloc(1, sizeof(dt_iop_colorzones_params_t));
2600 module->default_params = calloc(1, sizeof(dt_iop_colorzones_params_t));
2601 module->default_enabled = 0;
2602 module->params_size = sizeof(dt_iop_colorzones_params_t);
2603 module->request_histogram |= (DT_REQUEST_ON);
2608#undef DT_IOP_COLORZONES_INSET
2609#undef DT_IOP_COLORZONES_CURVE_INFL
2610#undef DT_IOP_COLORZONES_RES
2611#undef DT_IOP_COLORZONES_LUT_RES
2612#undef DT_IOP_COLORZONES_BANDS
2613#undef DT_IOP_COLORZONES_MAXNODES
2614#undef DT_IOP_COLORZONES_DEFAULT_STEP
2615#undef DT_IOP_COLORZONES_MIN_X_DISTANCE
Handle default and user-set shortcuts (accelerators)
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)
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
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)
void dt_colorspaces_apply_profile(const char *const op_name, const char *const instance_name, 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)
Convert a 4-channel float buffer between RGB and Lab through one profile.
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
static dt_aligned_pixel_t rgb
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)
Float for name, clamped to its declared bounds.
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
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...
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
#define dt_database_start_transaction()
#define dt_database_release_transaction()
#define dt_dev_add_history_item(dev, module, enable, redraw)
#define dt_dev_pixelpipe_update_history_main(dev)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_output_profile_info(const struct dt_dev_pixelpipe_t *pipe)
__DT_CLONE_TARGETS__ dt_iop_order_iccprofile_info_t * dt_ioppr_get_iop_work_profile_info(struct dt_iop_module_t *module, GList *iop_list)
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
GHashTable * selected
set of checked row labels, mirrored to conf on every change
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)
static guint dt_keys_mainpad_alternatives(const guint key_val)
Remap keypad keys to usual mainpad ones.
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)
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)
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
void dt_iop_request_focus(dt_iop_module_t *module)
Move darkroom focus to module, or clear it with NULL.
@ 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)
dt_iop_colorzones_channel_t
#define DT_IOP_COLORZONES_BANDS
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.
GtkWidget * dt_ui_notebook_page(GtkNotebook *notebook, const char *text, const char *tooltip)
GtkNotebook * dt_ui_notebook_new()
void dt_ui_notebook_set_picker_owner(GtkNotebook *notebook, gpointer owner)
Register an opaque owner for a GtkNotebook's page switches, and report every "switch_page" to the hos...
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)
#define __OMP_PARALLEL_FOR__(...)
static cairo_surface_t * dt_cairo_image_surface_create(cairo_format_t format, int width, int height)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
static const dt_aligned_pixel_simd_t value
const float uint32_t state[4]
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::@13 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]
dt_iop_global_data_t * data
dt_dev_request_colorpick_flags_t request_color_pick
dt_iop_params_t * default_params
struct dt_iop_module_gui_t * gui
struct dt_develop_t * dev
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
A profile reduced to the arithmetic the pixel loop can run: two matrices and six tone-curve LUTs,...
Region of interest passed through the pixelpipe.
#define __DT_CLONE_TARGETS__