71#define RETOUCH_NO_FORMS 300
72#define RETOUCH_MAX_SCALES 15
73#define RETOUCH_NO_SCALES (RETOUCH_MAX_SCALES + 2)
75#define RETOUCH_PREVIEW_LVL_MIN -3.0f
76#define RETOUCH_PREVIEW_LVL_MAX 3.0f
223 return _(
"re_touch");
228 return _(
"split-frequency|healing|cloning|stamp");
236 _(
"linear, RGB, scene-referred"),
237 _(
"geometric and frequential, RGB"),
238 _(
"linear, RGB, scene-referred"));
259 const int new_version)
261 if(old_version == 1 && new_version == 3)
263 typedef struct dt_iop_retouch_form_data_v1_t
274 float fill_brightness;
275 } dt_iop_retouch_form_data_v1_t;
276 typedef struct dt_iop_retouch_params_v1_t
284 int merge_from_scale;
286 float preview_levels[3];
296 float fill_brightness;
297 } dt_iop_retouch_params_v1_t;
299 dt_iop_retouch_params_v1_t *o = (dt_iop_retouch_params_v1_t *)old_params;
306 dt_iop_retouch_form_data_v1_t of = o->rt_forms[
i];
307 n->rt_forms[
i].algorithm = of.algorithm;
308 n->rt_forms[
i].blur_radius = of.blur_radius;
309 n->rt_forms[
i].blur_type = of.blur_type;
310 n->rt_forms[
i].distort_mode = 1;
311 n->rt_forms[
i].fill_brightness = of.fill_brightness;
312 n->rt_forms[
i].fill_color[0] = of.fill_color[0];
313 n->rt_forms[
i].fill_color[1] = of.fill_color[1];
314 n->rt_forms[
i].fill_color[2] = of.fill_color[2];
315 n->rt_forms[
i].fill_mode = of.fill_mode;
316 n->rt_forms[
i].formid = of.formid;
317 n->rt_forms[
i].scale = of.scale;
319 n->algorithm = o->algorithm;
320 n->blur_radius = o->blur_radius;
321 n->blur_type = o->blur_type;
322 n->curr_scale = o->curr_scale;
323 n->fill_brightness = o->fill_brightness;
324 n->fill_color[0] = o->fill_color[0];
325 n->fill_color[1] = o->fill_color[1];
326 n->fill_color[2] = o->fill_color[2];
327 n->fill_mode = o->fill_mode;
328 n->merge_from_scale = o->merge_from_scale;
329 n->num_scales = o->num_scales;
330 n->preview_levels[0] = o->preview_levels[0];
331 n->preview_levels[1] = o->preview_levels[1];
332 n->preview_levels[2] = o->preview_levels[2];
334 n->max_heal_iter = 1000;
338 if(old_version == 2 && new_version == 3)
340 typedef struct dt_iop_retouch_params_v2_t
348 int merge_from_scale;
350 float preview_levels[3];
357 float fill_brightness;
358 } dt_iop_retouch_params_v2_t;
360 dt_iop_retouch_params_v2_t *o = (dt_iop_retouch_params_v2_t *)old_params;
366 memcpy(
n, o,
sizeof(dt_iop_retouch_params_v2_t));
368 n->max_heal_iter = 1000;
384 if(
p->rt_forms[
i].formid == formid) index =
i;
401 return selected_group_entry ? selected_group_entry->
formid : 0;
414 for(
const GList *forms = grp->
points; forms; forms = g_list_next(forms))
417 if(grpt->
formid == formid)
419 form_point_group = grpt;
425 return form_point_group;
433 if(grpt) opacity = grpt->
opacity;
441 = (GdkRGBA){.red =
p->fill_color[0], .green =
p->fill_color[1], .blue =
p->fill_color[2], .alpha = 1.0 };
442 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(
g->colorpick), &c);
453 gtk_widget_hide(GTK_WIDGET(
g->vbox_blur));
454 gtk_widget_hide(GTK_WIDGET(
g->vbox_fill));
457 gtk_widget_show(GTK_WIDGET(
g->vbox_blur));
458 gtk_widget_hide(GTK_WIDGET(
g->vbox_fill));
461 gtk_widget_hide(GTK_WIDGET(
g->vbox_blur));
462 gtk_widget_show(GTK_WIDGET(
g->vbox_fill));
464 gtk_widget_show(GTK_WIDGET(
g->hbox_color_pick));
466 gtk_widget_hide(GTK_WIDGET(
g->hbox_color_pick));
470 gtk_widget_hide(GTK_WIDGET(
g->vbox_blur));
471 gtk_widget_hide(GTK_WIDGET(
g->vbox_fill));
475 if(
g->display_wavelet_scale)
476 gtk_widget_show(GTK_WIDGET(
g->vbox_preview_scale));
478 gtk_widget_hide(GTK_WIDGET(
g->vbox_preview_scale));
482 if(selected_formid > 0)
485 gtk_widget_show(GTK_WIDGET(
g->sl_mask_opacity));
487 gtk_widget_hide(GTK_WIDGET(
g->sl_mask_opacity));
497 gtk_label_set_text(
g->label_form_selected, form->
name);
499 gtk_label_set_text(
g->label_form_selected, _(
"none"));
515 gboolean selection_changed =
FALSE;
531 selection_changed =
TRUE;
545 selection_changed =
TRUE;
557 selection_changed =
TRUE;
566 gtk_widget_show(GTK_WIDGET(
g->sl_mask_opacity));
568 gtk_widget_hide(GTK_WIDGET(
g->sl_mask_opacity));
582 grpt->
opacity = CLAMP(opacity, 0.05f, 1.0f);
600 if(source_scale != dest_scale && source_scale >= 0 && dest_scale >= 0)
604 if(
p->rt_forms[
i].scale == source_scale)
p->rt_forms[
i].scale = dest_scale;
631 const int scale =
p->curr_scale;
637 if(
p->rt_forms[
i].formid != 0 &&
p->rt_forms[
i].scale == scale) count++;
641 gtk_widget_set_sensitive(
g->bt_copy_scale, count > 0);
649 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
663 if(
p->rt_forms[
i].scale == scale)
665 const int formid =
p->rt_forms[
i].formid;
685 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
706 int new_form_index = 0;
714 const int formid = grpt->
formid;
722 forms_d[new_form_index] =
p->rt_forms[form_index];
730 forms_d[new_form_index].
formid = formid;
731 forms_d[new_form_index].
scale =
p->curr_scale;
732 forms_d[new_form_index].
algorithm =
p->algorithm;
735 switch(forms_d[new_form_index].algorithm)
738 forms_d[new_form_index].
blur_type =
p->blur_type;
742 forms_d[new_form_index].
fill_mode =
p->fill_mode;
743 forms_d[new_form_index].
fill_color[0] =
p->fill_color[0];
744 forms_d[new_form_index].
fill_color[1] =
p->fill_color[1];
745 forms_d[new_form_index].
fill_color[2] =
p->fill_color[2];
758 p->rt_forms[
i] = forms_d[
i];
785 gchar *str = g_strdup_printf(
"%d", nb);
786 gtk_label_set_text(
g->label_form, str);
794 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
799 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
815 if(ft >= roi_out->
y + roi_out->
height || ft + fh <= roi_out->y || fl >= roi_out->
x + roi_out->
width
816 || fl + fw <= roi_out->
x)
824 size_t points_count,
float *
new)
828 for(
size_t i = 0;
i < points_count * 2;
i += 2)
830 new[
i] = points[
i] * scalex;
831 new[
i + 1] = points[
i + 1] * scaley;
837 const float *target,
const float *source,
float *dx,
float *dy,
838 const int distort_mode)
843 if(distort_mode == 1)
850 points[0] = target[0] * pipe->
iwidth;
851 points[1] = target[1] * pipe->
iheight;
852 points[2] = source[0] * pipe->
iwidth;
853 points[3] = source[1] * pipe->
iheight;
860 if(distort_mode == 1)
862 *dx = points[0] - points[2];
863 *dy = points[1] - points[3];
867 *dx = (points[0] - points[2]) * roi->
scale;
868 *dy = (points[1] - points[3]) * roi->
scale;
878 const int distort_mode)
915static inline __attribute__((always_inline))
void rt_clamp_minmax(
float levels_old[3],
float levels_new[3])
918 if((levels_old[0] != levels_new[0] || levels_old[2] != levels_new[2]) && levels_old[1] == levels_new[1])
921 if(levels_old[2] != levels_old[0])
927 const float percentage = (levels_old[1] - levels_old[0]) / (levels_old[2] - levels_old[0]);
928 levels_new[1] = left + (right - left) * percentage;
929 levels_new[0] = left;
930 levels_new[2] = right;
935 if(levels_new[0] == 0.f && levels_new[1] == 0.f && levels_new[2] == 0.f)
937 levels_new[0] = -1.5f;
939 levels_new[2] = 1.5f;
943 if(levels_new[2] < levels_new[0] + 0.05f * 2.f) levels_new[2] = levels_new[0] + 0.05f * 2.f;
944 if(levels_new[1] < levels_new[0] + 0.05f) levels_new[1] = levels_new[0] + 0.05f;
945 if(levels_new[1] > levels_new[2] - 0.05f) levels_new[1] = levels_new[2] - 0.05f;
952 const float percentage = (levels_new[1] - levels_new[0]) / (levels_new[2] - levels_new[0]);
953 levels_new[1] = left + (right - left) * percentage;
954 levels_new[0] = left;
955 levels_new[2] = right;
989 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->
off),
TRUE);
1003 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
1004 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_showmask),
FALSE);
1005 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_suppress),
FALSE);
1006 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->colorpicker),
FALSE);
1033 = (GdkRGBA){.red =
p->fill_color[0], .green =
p->fill_color[1], .blue =
p->fill_color[2], .alpha = 1.0 };
1034 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget), &c);
1035 p->fill_color[0] = c.red;
1036 p->fill_color[1] = c.green;
1037 p->fill_color[2] = c.blue;
1044 p->rt_forms[index].fill_color[0] =
p->fill_color[0];
1045 p->rt_forms[index].fill_color[1] =
p->fill_color[1];
1046 p->rt_forms[index].fill_color[2] =
p->fill_color[2];
1054#define RT_WDBAR_INSET 0.2f
1055#define lw DT_PIXEL_APPLY_DPI(1.0f)
1061 snprintf(text,
sizeof(text),
"%i",
p->curr_scale);
1062 gtk_label_set_text(
g->lbl_curr_scale, text);
1064 snprintf(text,
sizeof(text),
"%i",
p->num_scales);
1065 gtk_label_set_text(
g->lbl_num_scales, text);
1067 snprintf(text,
sizeof(text),
"%i",
p->merge_from_scale);
1068 gtk_label_set_text(
g->lbl_merge_from_scale, text);
1079 if(
p->num_scales == num_scales)
return;
1081 p->num_scales = num_scales;
1083 if(
p->num_scales <
p->merge_from_scale)
p->merge_from_scale =
p->num_scales;
1098 if(
p->curr_scale == curr_scale)
return;
1100 p->curr_scale = curr_scale;
1110 &&
g->preview_auto_levels == 0 &&
p->curr_scale > 0 &&
p->curr_scale <=
p->num_scales)
1112 g->preview_auto_levels = 1;
1113 g->displayed_wavelet_scale = 1;
1129 const int merge_from_scale = CLAMP(_merge_from_scale, 0,
p->num_scales);
1130 if(
p->merge_from_scale == merge_from_scale)
return;
1132 p->merge_from_scale = merge_from_scale;
1143 g->wdbar_mouse_x =
g->wdbar_mouse_y = -1;
1145 g->lower_cursor =
g->upper_cursor =
FALSE;
1146 g->lower_margin =
g->upper_margin =
FALSE;
1148 gtk_widget_queue_draw(
g->wd_bar);
1159 GtkAllocation allocation;
1160 gtk_widget_get_allocation(widget, &allocation);
1162 const float box_w = (allocation.width - 2.0f * inset) / (
float)
RETOUCH_NO_SCALES;
1164 if(event->button == 1)
1173 else if(
g->upper_margin)
1180 else if (
g->curr_scale >= 0)
1184 gtk_widget_queue_draw(
g->wd_bar);
1192 if(event->button == 1)
g->is_dragging = 0;
1194 gtk_widget_queue_draw(
g->wd_bar);
1212 else if(
g->upper_margin)
1214 else if (
g->curr_scale >= 0)
1218 gtk_widget_queue_draw(
g->wd_bar);
1227 GtkAllocation allocation;
1228 gtk_widget_get_allocation(widget, &allocation);
1230 const float box_w = (allocation.width - 2.0f * inset) / (
float)
RETOUCH_NO_SCALES;
1231 const float sh = 3.0f *
lw + inset;
1235 g->wdbar_mouse_x = CLAMP(event->x - inset, 0, allocation.width - 2.0f * inset - 1.0f);
1236 g->wdbar_mouse_y =
event->y;
1238 g->curr_scale =
g->wdbar_mouse_x / box_w;
1239 g->lower_cursor =
g->upper_cursor =
FALSE;
1240 g->lower_margin =
g->upper_margin =
FALSE;
1241 if(
g->wdbar_mouse_y <= sh)
1243 g->upper_margin =
TRUE;
1244 float middle = box_w * (0.5f + (float)
p->merge_from_scale);
1245 g->upper_cursor = (
g->wdbar_mouse_x >= (middle - inset)) && (
g->wdbar_mouse_x <= (middle + inset));
1246 if (!(
g->is_dragging))
g->curr_scale = -1;
1248 else if (
g->wdbar_mouse_y >= allocation.height - sh)
1250 g->lower_margin =
TRUE;
1251 float middle = box_w * (0.5f + (float)
p->num_scales);
1252 g->lower_cursor = (
g->wdbar_mouse_x >= (middle - inset)) && (
g->wdbar_mouse_x <= (middle + inset));
1253 if (!(
g->is_dragging))
g->curr_scale = -1;
1262 gtk_widget_queue_draw(
g->wd_bar);
1271 has_shapes = (
p->rt_forms[
i].formid != 0 &&
p->rt_forms[
i].scale == scale);
1282 GdkRGBA border = {0.066, 0.066, 0.066, 1};
1283 GdkRGBA original = {.1, .1, .1, 1};
1284 GdkRGBA inactive = {.15, .15, .15, 1};
1285 GdkRGBA active = {.35, .35, .35, 1};
1286 GdkRGBA merge_from = {.5, .5, .5, 1};
1287 GdkRGBA residual = {.8, .8, .8, 1};
1288 GdkRGBA shapes = {.75, .5, .0, 1};
1292 const int first_scale_visible = (
g->first_scale_visible > 0) ?
g->first_scale_visible :
RETOUCH_MAX_SCALES;
1294 GtkAllocation allocation;
1295 gtk_widget_get_allocation(widget, &allocation);
1298 cairo_t *cr = cairo_create(cst);
1301 gdk_cairo_set_source_rgba(cr, &inactive);
1307 const int mk = 2 * inset;
1308 const float sh = 3.0f *
lw + inset;
1309 const float box_w = (allocation.width - 2.0f * inset) / (
float)
RETOUCH_NO_SCALES;
1310 const float box_h = allocation.height - 2.0f * sh;
1313 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
1319 else if(
i ==
p->num_scales + 1)
1321 else if(
i >=
p->merge_from_scale && i <= p->num_scales &&
p->merge_from_scale > 0)
1323 else if(i <= p->num_scales)
1328 gdk_cairo_set_source_rgba(cr, &color);
1329 cairo_rectangle(cr, box_w *
i + inset, sh, box_w, box_h);
1333 if(
i >= first_scale_visible && i <= p->num_scales)
1335 gdk_cairo_set_source_rgba(cr, &merge_from);
1336 cairo_rectangle(cr, box_w *
i + inset,
lw, box_w, 2.0f *
lw);
1343 cairo_set_line_width(cr,
lw);
1344 gdk_cairo_set_source_rgba(cr, &shapes);
1345 cairo_rectangle(cr, box_w *
i + inset +
lw / 2.0f, allocation.height - sh, box_w -
lw, 2.0f *
lw);
1350 cairo_set_line_width(cr,
lw);
1351 gdk_cairo_set_source_rgba(cr, &border);
1352 cairo_rectangle(cr, box_w *
i + inset, sh, box_w, box_h);
1356 cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT);
1360 if(
p->curr_scale >=
p->merge_from_scale &&
p->curr_scale <=
p->num_scales &&
p->merge_from_scale > 0)
1367 cairo_set_line_width(cr,
lw);
1368 gdk_cairo_set_source_rgba(cr, &color);
1369 middle = box_w * (0.5f + (float)
p->curr_scale);
1370 cairo_arc(cr, middle + inset, 0.5f * box_h + sh, 0.5f * inset, 0, 2.0f *
M_PI);
1376 if(
g->curr_scale >= 0)
1378 cairo_set_line_width(cr,
lw);
1379 if(
g->curr_scale ==
p->num_scales + 1) color = inactive;
1380 else color = residual;
1381 gdk_cairo_set_source_rgba(cr, &color);
1382 cairo_rectangle(cr, box_w *
g->curr_scale + inset +
lw, sh +
lw, box_w - 2.0f *
lw, box_h - 2.0f *
lw);
1389 middle = box_w * (0.5f + (float)
p->num_scales);
1392 cairo_set_source_rgb(cr, 0.67, 0.67, 0.67);
1397 cairo_set_source_rgb(cr, 0.54, 0.54, 0.54);
1402 middle = box_w * (0.5f + (float)
p->merge_from_scale);
1405 cairo_set_source_rgb(cr, 0.67, 0.67, 0.67);
1410 cairo_set_source_rgb(cr, 0.54, 0.54, 0.54);
1416 cairo_set_source_surface(crf, cst, 0, 0);
1418 cairo_surface_destroy(cst);
1451 for (
int i = 0;
i < 3;
i++)
p->preview_levels[
i] = dlevels[
i];
1480 p->rt_forms[index].fill_color[0] =
p->fill_color[0];
1481 p->rt_forms[index].fill_color[1] =
p->fill_color[1];
1482 p->rt_forms[index].fill_color[2] =
p->fill_color[2];
1497 int scale_copied = 0;
1498 const int active = !gtk_toggle_button_get_active(togglebutton);
1502 if(togglebutton == (GtkToggleButton *)
g->bt_copy_scale)
1504 g->copied_scale = (active) ?
p->curr_scale : -1;
1506 else if(togglebutton == (GtkToggleButton *)
g->bt_paste_scale)
1512 g->copied_scale = -1;
1515 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_copy_scale),
g->copied_scale >= 0);
1516 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_paste_scale),
g->copied_scale >= 0);
1517 gtk_widget_set_sensitive(
g->bt_paste_scale,
g->copied_scale >= 0);
1530 return module->request_mask_display && !g->mask_display && !g->display_wavelet_scale;
1539 return g->mask_display ||
g->display_wavelet_scale ||
g->suppress_mask;
1551 const int variant = (
g->mask_display ? 1 : 0) | (
g->display_wavelet_scale ? 2 : 0) | (
g->suppress_mask ? 4 : 0);
1573 module->request_mask_display = display_request;
1586 dt_control_log(_(
"cannot display scales when the blending mask is displayed"));
1589 gtk_toggle_button_set_active(togglebutton,
FALSE);
1594 if(self->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->
off), 1);
1597 g->display_wavelet_scale = !gtk_toggle_button_get_active(togglebutton);
1609 &&
g->preview_auto_levels == 0 &&
p->curr_scale > 0 &&
p->curr_scale <=
p->num_scales)
1611 g->preview_auto_levels = 1;
1612 g->displayed_wavelet_scale = 1;
1618 gtk_toggle_button_set_active(togglebutton,
g->display_wavelet_scale);
1631 if(
g->preview_auto_levels == 2)
1633 g->preview_auto_levels = -1;
1637 for(
int i = 0;
i < 3;
i++)
p->preview_levels[
i] =
g->preview_levels[
i];
1645 for(
int i = 0;
i < 3;
i++) dlevels[
i] =
p->preview_levels[
i];
1651 g->preview_auto_levels = 0;
1656 gtk_widget_queue_draw(GTK_WIDGET(
g->wd_bar));
1665 if(self->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->
off), 1);
1669 if(
g->preview_auto_levels == 0)
1671 g->preview_auto_levels = 1;
1735 if(event->button == 1)
1744 const gboolean control_button_pressed =
dt_modifier_is(event->state, GDK_CONTROL_MASK);
1767 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
1799 if(togglebutton == (GtkToggleButton *)
g->bt_blur)
1801 else if(togglebutton == (GtkToggleButton *)
g->bt_clone)
1803 else if(togglebutton == (GtkToggleButton *)
g->bt_heal)
1805 else if(togglebutton == (GtkToggleButton *)
g->bt_fill)
1809 gboolean accept =
TRUE;
1818 if(accept)
p->algorithm = new_algo;
1835 if(
p->algorithm !=
p->rt_forms[index].algorithm)
1837 p->rt_forms[index].algorithm =
p->algorithm;
1846 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_polygon)))
1848 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_circle)))
1850 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_ellipse)))
1852 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_brush)))
1897 dt_control_log(_(
"cannot display masks when the blending mask is displayed"));
1899 gtk_toggle_button_set_active(togglebutton,
FALSE);
1903 g->mask_display = !gtk_toggle_button_get_active(togglebutton);
1907 if(module->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->
off), 1);
1912 gtk_toggle_button_set_active(togglebutton,
g->mask_display);
1921 g->suppress_mask = !gtk_toggle_button_get_active(togglebutton);
1927 if(module->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->
off), 1);
1932 gtk_toggle_button_set_active(togglebutton,
g->suppress_mask);
1941 if(w ==
g->cmb_fill_mode)
1954 p->rt_forms[index].blur_type =
p->blur_type;
1955 p->rt_forms[index].blur_radius =
p->blur_radius;
1959 p->rt_forms[index].fill_mode =
p->fill_mode;
1960 p->rt_forms[index].fill_brightness =
p->fill_brightness;
1987 d->preview_levels[1] = 0.f;
1994 const int program = 21;
2048 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
2060 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
2066 if(
g->display_wavelet_scale ||
g->mask_display ||
g->suppress_mask)
2093 const float require = 2.0f;
2094 const float require_cl = 1.0f
2095 + ((
p->num_scales > 0) ? 4.0f : 2.0f);
2099 tiling->factor = 2.0f + require;
2100 tiling->factor_cl = 2.0f + require_cl;
2102 tiling->maxbuf_cl = 1.0f;
2135 gchar *str = g_strdup_printf(
"%d", nb);
2136 gtk_label_set_text(
g->label_form, str);
2161 gtk_widget_queue_draw(GTK_WIDGET(
g->wd_bar));
2170 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_display_wavelet_scale),
g->display_wavelet_scale);
2171 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_copy_scale),
g->copied_scale >= 0);
2172 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_paste_scale),
g->copied_scale >= 0);
2173 gtk_widget_set_sensitive(
g->bt_paste_scale,
g->copied_scale >= 0);
2184 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
2189 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
2194 for(
int i = 0;
i < 3;
i++) dlevels[
i] =
p->preview_levels[
i];
2203 g->copied_scale = -1;
2204 g->mask_display = 0;
2205 g->suppress_mask = 0;
2206 g->display_wavelet_scale = 0;
2207 g->displayed_wavelet_scale = 0;
2210 g->preview_auto_levels = 0;
2212 g->preview_levels[1] = 0.f;
2216 g->wdbar_mouse_x =
g->wdbar_mouse_y = -1;
2218 g->lower_cursor =
g->upper_cursor =
FALSE;
2219 g->lower_margin =
g->upper_margin =
FALSE;
2234 g->label_form = GTK_LABEL(gtk_label_new(
"-1"));
2236 gtk_widget_set_tooltip_text(hbox_shapes,
2237 _(
"to add a shape select an algorithm and a shape type and click on the image.\n"
2238 "shapes are added to the current scale"));
2241 N_(
"show and edit shapes in restricted mode"),
2248 .creation_module = self,
2249 .buttons = shape_buttons,
2251 .action_section = N_(
"shapes"),
2262 gtk_box_pack_start(GTK_BOX(hbox_shapes), shape_buttons_box,
FALSE,
FALSE, 0);
2274 self, N_(
"tools"), N_(
"activate blur tool"), N_(
"change algorithm for current form"),
2278 self, N_(
"tools"), N_(
"activate fill tool"), N_(
"change algorithm for current form"),
2282 self, N_(
"tools"), N_(
"activate cloning tool"), N_(
"change algorithm for current form"),
2286 self, N_(
"tools"), N_(
"activate healing tool"), N_(
"change algorithm for current form"),
2290 gchar *tt2 = g_strdup_printf(
"%s\n%s", _(
"ctrl+click to change tool for current form"),
2291 _(
"shift+click to set the tool as default"));
2292 gchar *tt = g_strdup_printf(
"%s\n%s", _(
"activate blur tool"), tt2);
2293 gtk_widget_set_tooltip_text(
g->bt_blur, tt);
2295 tt = g_strdup_printf(
"%s\n%s", _(
"activate fill tool"), tt2);
2296 gtk_widget_set_tooltip_text(
g->bt_fill, tt);
2298 tt = g_strdup_printf(
"%s\n%s", _(
"activate cloning tool"), tt2);
2299 gtk_widget_set_tooltip_text(
g->bt_clone, tt);
2301 tt = g_strdup_printf(
"%s\n%s", _(
"activate healing tool"), tt2);
2302 gtk_widget_set_tooltip_text(
g->bt_heal, tt);
2307 GtkWidget *grid_wd_labels = gtk_grid_new();
2308 gtk_grid_set_column_homogeneous(GTK_GRID(grid_wd_labels),
FALSE);
2310 gtk_grid_attach(GTK_GRID(grid_wd_labels),
dt_ui_label_new(_(
"scales:")), 0, 0, 1, 1);
2312 gtk_label_set_width_chars(
g->lbl_num_scales, 2);
2313 gtk_grid_attach(GTK_GRID(grid_wd_labels), GTK_WIDGET(
g->lbl_num_scales), 1, 0, 1, 1);
2315 gtk_grid_attach(GTK_GRID(grid_wd_labels),
dt_ui_label_new(_(
"current:")), 0, 1, 1, 1);
2317 gtk_label_set_width_chars(
g->lbl_curr_scale, 2);
2318 gtk_grid_attach(GTK_GRID(grid_wd_labels), GTK_WIDGET(
g->lbl_curr_scale), 1, 1, 1, 1);
2320 gtk_grid_attach(GTK_GRID(grid_wd_labels),
dt_ui_label_new(_(
"merge from:")), 0, 2, 1, 1);
2322 gtk_label_set_width_chars(
g->lbl_merge_from_scale, 2);
2323 gtk_grid_attach(GTK_GRID(grid_wd_labels), GTK_WIDGET(
g->lbl_merge_from_scale), 1, 2, 1, 1);
2326 g->wd_bar = gtk_drawing_area_new();
2328 gtk_widget_set_tooltip_text(
g->wd_bar, _(
"top slider adjusts where the merge scales start\n"
2329 "bottom slider adjusts the number of scales\n"
2330 "dot indicates the current scale\n"
2331 "top line indicates that the scale is visible at current zoom level\n"
2332 "bottom line indicates that the scale has shapes on it"));
2333 g_signal_connect(G_OBJECT(
g->wd_bar),
"draw", G_CALLBACK(
rt_wdbar_draw), self);
2338 g_signal_connect(G_OBJECT(
g->wd_bar),
"scroll-event", G_CALLBACK(
rt_wdbar_scrolled), self);
2339 gtk_widget_add_events(GTK_WIDGET(
g->wd_bar), GDK_POINTER_MOTION_MASK
2340 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
2358 gtk_box_pack_end(GTK_BOX(hbox_scale), gtk_grid_new(),
TRUE,
TRUE, 0);
2369 gtk_box_pack_end(GTK_BOX(hbox_scale), gtk_grid_new(),
TRUE,
TRUE, 0);
2381 gtk_box_pack_start(GTK_BOX(
g->vbox_preview_scale), lbl_psc,
FALSE,
TRUE, 0);
2386 #define NEUTRAL_GRAY 0.5
2391 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->preview_levels_gslider), _(
"adjust preview levels"));
2400 (
g->preview_levels_gslider)->min_spacing = 0.05;
2401 g_signal_connect(G_OBJECT(
g->preview_levels_gslider),
"value-changed", G_CALLBACK(
rt_gslider_changed), self);
2403 gtk_box_pack_start(GTK_BOX(prev_lvl), GTK_WIDGET(
g->preview_levels_gslider),
TRUE,
TRUE, 0);
2410 gtk_box_pack_start(GTK_BOX(
g->vbox_preview_scale), prev_lvl,
TRUE,
TRUE, 0);
2414 GtkWidget *label1 = gtk_label_new(_(
"shape selected:"));
2415 gtk_label_set_ellipsize(GTK_LABEL(label1), PANGO_ELLIPSIZE_START);
2416 gtk_box_pack_start(GTK_BOX(hbox_shape_sel), label1,
FALSE,
TRUE, 0);
2417 g->label_form_selected = GTK_LABEL(gtk_label_new(
"-1"));
2418 gtk_widget_set_tooltip_text(hbox_shape_sel,
2419 _(
"click on a shape to select it,\nto unselect click on an empty space"));
2420 gtk_box_pack_start(GTK_BOX(hbox_shape_sel), GTK_WIDGET(
g->label_form_selected),
FALSE,
TRUE, 0);
2426 gtk_widget_set_tooltip_text(
g->cmb_fill_mode, _(
"erase the detail or fills with chosen color"));
2430 = (GdkRGBA){.red =
p->fill_color[0], .green =
p->fill_color[1], .blue =
p->fill_color[2], .alpha = 1.0 };
2434 gtk_box_pack_start(GTK_BOX(
g->hbox_color_pick), lbl_fill_color,
FALSE,
TRUE, 0);
2436 g->colorpick = gtk_color_button_new_with_rgba(&color);
2437 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(
g->colorpick),
FALSE);
2438 gtk_color_button_set_title(GTK_COLOR_BUTTON(
g->colorpick), _(
"select fill color"));
2439 gtk_widget_set_tooltip_text(
g->colorpick, _(
"select fill color"));
2441 gtk_box_pack_start(GTK_BOX(
g->hbox_color_pick), GTK_WIDGET(
g->colorpick),
TRUE,
TRUE, 0);
2444 gtk_widget_set_tooltip_text(
g->colorpicker, _(
"pick fill color from image"));
2446 gtk_box_pack_start(GTK_BOX(
g->vbox_fill),
g->hbox_color_pick,
TRUE,
TRUE, 0);
2451 gtk_widget_set_tooltip_text(
g->sl_fill_brightness,
2452 _(
"adjusts color brightness to fine-tune it. works with erase as well"));
2458 gtk_widget_set_tooltip_text(
g->cmb_blur_type, _(
"type for the blur algorithm"));
2462 gtk_widget_set_tooltip_text(
g->sl_blur_radius, _(
"radius of the selected blur type"));
2468 gtk_widget_set_tooltip_text(
g->sl_mask_opacity, _(
"set the opacity on the selected shape"));
2475 gtk_box_pack_start(GTK_BOX(self->
widget), lbl_rt_tools,
FALSE,
TRUE, 0);
2478 gtk_box_pack_start(GTK_BOX(self->
widget), hbox_shapes,
TRUE,
TRUE, 0);
2480 gtk_box_pack_start(GTK_BOX(self->
widget), hbox_algo,
TRUE,
TRUE, 0);
2487 gtk_box_pack_start(GTK_BOX(self->
widget), grid_wd_labels,
TRUE,
TRUE, 0);
2491 gtk_box_pack_start(GTK_BOX(self->
widget), hbox_scale,
TRUE,
TRUE, 0);
2494 gtk_box_pack_start(GTK_BOX(self->
widget),
g->vbox_preview_scale,
TRUE,
TRUE, 0);
2498 gtk_box_pack_start(GTK_BOX(self->
widget), lbl_shapes,
FALSE,
TRUE, 0);
2501 gtk_box_pack_start(GTK_BOX(self->
widget), hbox_shape_sel,
TRUE,
TRUE, 0);
2503 gtk_box_pack_start(GTK_BOX(self->
widget),
g->vbox_blur,
TRUE,
TRUE, 0);
2505 gtk_box_pack_start(GTK_BOX(self->
widget),
g->vbox_fill,
TRUE,
TRUE, 0);
2507 gtk_box_pack_start(GTK_BOX(self->
widget),
g->sl_mask_opacity,
TRUE,
TRUE, 0);
2546 dt_iop_roi_t *roi_in,
int *_roir,
int *_roib,
int *_roix,
int *_roiy)
2560 for(
const GList *forms = grp->
points; forms; forms = g_list_next(forms))
2565 const int formid = grpt->
formid;
2586 if(ft >= roi_in->
y + roi_in->
height || ft + fh <= roi_in->y || fl >= roi_in->
x + roi_in->
width
2587 || fl + fw <= roi_in->
x)
2596 roiy = fminf(ft, roiy);
2597 roix = fminf(fl, roix);
2598 roir = fmaxf(fl + fw, roir);
2599 roib = fmaxf(ft + fh, roib);
2604 const int overlap = ceilf(4 * (
p->rt_forms[index].blur_radius * roi_in->
scale));
2605 if(roiy > ft) roiy =
MAX(roiy - overlap, ft);
2606 if(roix > fl) roix =
MAX(roix - overlap, fl);
2607 if(roir < fl + fw) roir =
MAX(roir + overlap, fl + fw);
2608 if(roib < ft + fh) roib =
MAX(roib + overlap, ft + fh);
2614 float dx = 0.f, dy = 0.f;
2616 p->rt_forms[index].distort_mode))
2618 roiy = fminf(ft - dy, roiy);
2619 roix = fminf(fl - dx, roix);
2620 roir = fmaxf(fl + fw - dx, roir);
2621 roib = fmaxf(ft + fh - dy, roib);
2637 dt_iop_roi_t *roi_in,
const int formid_src,
const int fl_src,
2638 const int ft_src,
const int fw_src,
const int fh_src,
int *_roir,
2639 int *_roib,
int *_roix,
int *_roiy)
2653 for(
const GList *forms = grp->
points; forms; forms = g_list_next(forms))
2658 const int formid = grpt->
formid;
2661 if(formid == formid_src)
break;
2685 int fl_dest, ft_dest;
2686 float dx = 0.f, dy = 0.f;
2688 p->rt_forms[index].distort_mode))
2697 const int intersects = !(ft_dest + fh < ft_src || ft_src + fh_src < ft_dest || fl_dest + fw < fl_src
2698 || fl_src + fw_src < fl_dest);
2702 roiy = fminf(ft, roiy);
2703 roix = fminf(fl, roix);
2704 roir = fmaxf(fl + fw, roir);
2705 roib = fmaxf(ft + fh, roib);
2708 roiy = fminf(ft + dy, roiy);
2709 roix = fminf(fl + dx, roix);
2710 roir = fmaxf(fl + fw + dx, roir);
2711 roib = fmaxf(ft + fh + dy, roib);
2726 dt_iop_roi_t *roi_in,
int *_roir,
int *_roib,
int *_roix,
int *_roiy)
2740 for(
const GList *forms = grp->
points; forms; forms = g_list_next(forms))
2745 const int formid = grpt->
formid;
2762 int fl_src, ft_src, fw_src, fh_src;
2768 fw_src *= roi_in->
scale, fh_src *= roi_in->
scale, fl_src *= roi_in->
scale, ft_src *= roi_in->
scale;
2771 const int intersects
2772 = !(roib < ft_src || ft_src + fh_src < roiy || roir < fl_src || fl_src + fw_src < roix);
2775 &roir, &roib, &roix, &roiy);
2793 int roir = roi_in->
width + roi_in->
x;
2794 int roib = roi_in->
height + roi_in->
y;
2795 int roix = roi_in->
x;
2796 int roiy = roi_in->
y;
2798 rt_compute_roi_in(self, processing_pipe, piece, roi_in, &roir, &roib, &roix, &roiy);
2800 int roir_prev = -1, roib_prev = -1, roix_prev = -1, roiy_prev = -1;
2802 while(roir != roir_prev || roib != roib_prev || roix != roix_prev || roiy != roiy_prev)
2814 roi_in->
x = CLAMP(roix, 0, scwidth - 1);
2815 roi_in->
y = CLAMP(roiy, 0, scheight - 1);
2816 roi_in->
width = CLAMP(roir - roi_in->
x, 1, scwidth + .5f - roi_in->
x);
2817 roi_in->
height = CLAMP(roib - roi_in->
y, 1, scheight + .5f - roi_in->
y);
2828 for(
int i = 0;
i < stride;
i +=
ch)
2832 dt_linearRGB_to_XYZ(img_src +
i,
XYZ);
2841 for(
int i = 0;
i < stride;
i +=
ch)
2846 dt_XYZ_to_linearRGB(
XYZ, img_src +
i);
2855 float l_max = -INFINITY;
2856 float l_min = INFINITY;
2868 work_profile->
lut_in, work_profile->unbounded_coeffs_in,
2874 dt_linearRGB_to_XYZ(img_src +
i,
XYZ);
2878 l_max =
MAX(l_max,
Lab[0]);
2879 l_min =
MIN(l_min,
Lab[0]);
2884 levels[0] = l_min / 100.f;
2885 levels[2] = l_max / 100.f;
2886 levels[1] = (l_sum / (float)count) / 100.f;
2891 float *img_src,
const int width,
const int height,
const int ch,
2897 const float left =
levels[0];
2898 const float middle =
levels[1];
2899 const float right =
levels[2];
2903 const float delta = (right - left) / 2.0f;
2904 const float mid = left +
delta;
2905 const float tmp = (middle - mid) /
delta;
2906 const float in_inv_gamma = powf(10, tmp);
2918 const float preserved_alpha = img_src[
i + 3];
2923 work_profile->
lut_in, work_profile->unbounded_coeffs_in,
2930 dt_linearRGB_to_XYZ(img_src +
i,
XYZ);
2934 for(
int c = 0; c < 1; c++)
2936 const float L_in = img_src[
i + c] / 100.0f;
2940 img_src[
i + c] = 0.f;
2944 const float percentage = (L_in - left) / (right - left);
2945 img_src[
i + c] = 100.0f * powf(percentage, in_inv_gamma);
2952 work_profile->
lut_out, work_profile->unbounded_coeffs_out,
2960 dt_XYZ_to_linearRGB(
XYZ, img_src +
i);
2963 img_src[
i + 3] = preserved_alpha;
2967#undef RT_WDBAR_INSET
2969#undef RETOUCH_NO_FORMS
2970#undef RETOUCH_MAX_SCALES
2971#undef RETOUCH_NO_SCALES
2973#undef RETOUCH_PREVIEW_LVL_MIN
2974#undef RETOUCH_PREVIEW_LVL_MAX
2979 const int x_from =
MAX(
MAX((roi_1->
x + 1 - padding), roi_2->
x), (roi_2->
x + dx));
2983 const int y_from =
MAX(
MAX((roi_1->
y + 1 - padding), roi_2->
y), (roi_2->
y + dy));
2984 const int y_to =
MIN(
MIN((roi_1->
y + roi_1->
height + 1 + padding), (roi_2->
y + roi_2->
height)),
2985 (roi_2->
y + roi_2->
height + dy));
2987 roi_dest->
x = x_from;
2988 roi_dest->
y = y_from;
2989 roi_dest->
width = x_to - x_from;
2990 roi_dest->
height = y_to - y_from;
2995 const struct dt_iop_roi_t *
const roi_out,
const int ch,
const int dx,
const int dy)
2997 const size_t rowsize =
sizeof(float) *
ch *
MIN(roi_out->
width, roi_in->
width);
2998 const int xoffs = roi_out->
x - roi_in->
x - dx;
2999 const int yoffs = roi_out->
y - roi_in->
y - dy;
3002 for(
int y = 0; y < y_to; y++)
3004 const size_t iindex = ((size_t)(y + yoffs) * roi_in->
width + xoffs) *
ch;
3005 const size_t oindex = (size_t)y * roi_out->
width *
ch;
3006 float *in1 = (
float *)in + iindex;
3007 float *out1 = (
float *)
out + oindex;
3009 memcpy(out1, in1, rowsize);
3015 const int dy,
const int algo)
3017 float *mask_tmp = NULL;
3019 *mask_scaled = NULL;
3023 *roi_mask_scaled = *roi_mask;
3025 roi_mask_scaled->
x = roi_mask->
x * roi_in->
scale;
3026 roi_mask_scaled->
y = roi_mask->
y * roi_in->
scale;
3034 const int x_to = roi_mask_scaled->
width + roi_mask_scaled->
x;
3035 const int y_to = roi_mask_scaled->
height + roi_mask_scaled->
y;
3040 fprintf(stderr,
"rt_build_scaled_mask: error allocating memory\n");
3046 for(
int yy = roi_mask_scaled->
y; yy < y_to; yy++)
3048 const int mask_index = ((int)(yy / roi_in->
scale)) - roi_mask->
y;
3049 if(mask_index < 0 || mask_index >= roi_mask->
height)
continue;
3051 const int mask_scaled_index = (yy - roi_mask_scaled->
y) * roi_mask_scaled->
width;
3053 const float *
m = mask + mask_index * roi_mask->
width;
3054 float *ms = mask_tmp + mask_scaled_index;
3056 for(
int xx = roi_mask_scaled->
x; xx < x_to; xx++, ms++)
3058 const int mx = ((int)(xx / roi_in->
scale)) - roi_mask->
x;
3059 if(mx < 0 || mx >= roi_mask->
width)
continue;
3066 *mask_scaled = mask_tmp;
3072 float *
const mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
3073 const float opacity)
3076 for(
int yy = 0; yy < roi_mask_scaled->
height; yy++)
3078 const int mask_index = yy * roi_mask_scaled->
width;
3079 const int src_index = 4 * mask_index;
3080 const int dest_index
3081 = 4 * (((yy + roi_mask_scaled->
y - roi_dest->
y) * roi_dest->
width) + (roi_mask_scaled->
x - roi_dest->
x));
3083 const float *s = img_src + src_index;
3084 const float *
m = mask_scaled + mask_index;
3085 float *
d = img_dest + dest_index;
3087 for(
int xx = 0; xx < roi_mask_scaled->
width; xx++)
3089 const float f =
m[xx] * opacity;
3090 const float f1 = (1.0f -
f);
3094 d[4*xx + c] =
d[4*xx + c] * f1 + s[4*xx + c] *
f;
3101 float *
const mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
3102 const float opacity)
3105 for(
int yy = 0; yy < roi_mask_scaled->
height; yy++)
3107 const int mask_index = yy * roi_mask_scaled->
width;
3108 const int dest_index
3109 = (((yy + roi_mask_scaled->
y - roi_img->
y) * roi_img->
width) + (roi_mask_scaled->
x - roi_img->
x)) *
ch;
3111 float *
d = img + dest_index;
3112 const float *
m = mask_scaled + mask_index;
3114 for(
int xx = 0; xx < roi_mask_scaled->
width; xx++,
d +=
ch,
m++)
3116 const float f = (*m) * opacity;
3117 if(
f >
d[3])
d[3] =
f;
3123 dt_iop_roi_t *
const roi_mask_scaled,
const float opacity,
const float *
const fill_color)
3126 for(
int yy = 0; yy < roi_mask_scaled->
height; yy++)
3128 const int mask_index = yy * roi_mask_scaled->
width;
3129 const int dest_index
3130 = (((yy + roi_mask_scaled->
y - roi_in->
y) * roi_in->
width) + (roi_mask_scaled->
x - roi_in->
x)) * 4;
3132 float *
d = in + dest_index;
3133 const float *
m = mask_scaled + mask_index;
3135 for(
int xx = 0; xx < roi_mask_scaled->
width; xx++)
3137 const float f =
m[xx] * opacity;
3140 d[4*xx + c] =
d[4*xx + c] * (1.0f -
f) + fill_color[c] *
f;
3146 dt_iop_roi_t *
const roi_mask_scaled,
const int dx,
const int dy,
const float opacity)
3152 fprintf(stderr,
"retouch_clone: error allocating memory for cloning\n");
3168 dt_iop_roi_t *
const roi_mask_scaled,
const float opacity,
const int blur_type,
3169 const float blur_radius,
const int use_sse)
3171 if(fabsf(blur_radius) <= 0.1f)
return 0;
3173 const float sigma = blur_radius * roi_in->
scale;
3175 float *img_dest = NULL;
3181 fprintf(stderr,
"retouch_blur: error allocating memory for blurring\n");
3190 float Labmax[] = { INFINITY, INFINITY, INFINITY, INFINITY };
3191 float Labmin[] = { -INFINITY, -INFINITY, -INFINITY, -INFINITY };
3205 const float detail = -1.0f;
3242 dt_iop_roi_t *
const roi_mask_scaled,
const int dx,
const int dy,
const float opacity,
const int max_iter)
3244 float *img_src = NULL;
3245 float *img_dest = NULL;
3253 fprintf(stderr,
"retouch_heal: error allocating memory for healing\n");
3263 dt_heal(img_src, img_dest, mask_scaled, roi_mask_scaled->
width, roi_mask_scaled->
height, 4, max_iter);
3286 if(scale > wt_p->
scales + 1)
return 0;
3298 const int mask_display
3306 scale =
p->num_scales + 1;
3315 for(
const GList *forms = grp->
points; forms; forms = g_list_next(forms))
3320 fprintf(stderr,
"rt_process_forms: invalid form\n");
3323 const int formid = grpt->
formid;
3324 const float form_opacity = grpt->
opacity;
3327 fprintf(stderr,
"rt_process_forms: form is null\n");
3334 fprintf(stderr,
"rt_process_forms: missing form=%i from array\n", formid);
3339 if(
p->rt_forms[index].scale != scale)
3348 fprintf(stderr,
"rt_process_forms: missing form=%i from masks\n", formid);
3363 &roi_mask.
x, &roi_mask.
y);
3366 fprintf(stderr,
"rt_process_forms: error retrieving mask\n");
3372 float dx = 0.f, dy = 0.f;
3377 p->rt_forms[index].distort_mode))
3385 float *mask_scaled = NULL;
3387 if(
rt_build_scaled_mask(mask, &roi_mask, &mask_scaled, &roi_mask_scaled, roi_layer, dx, dy, algo) != 0)
3406 && ((roi_mask_scaled.
width > 2) && (roi_mask_scaled.
height > 2)))
3410 if(
_retouch_clone(layer, roi_layer, mask_scaled, &roi_mask_scaled, dx, dy, form_opacity) != 0)
3418 if(
_retouch_heal(layer, roi_layer, mask_scaled, &roi_mask_scaled, dx, dy, form_opacity,
p->max_heal_iter) != 0)
3426 if(
_retouch_blur(self, pipe, layer, roi_layer, mask_scaled, &roi_mask_scaled, form_opacity,
3427 p->rt_forms[index].blur_type,
p->rt_forms[index].blur_radius, wt_p->
use_sse) != 0)
3440 fill_color[0] = fill_color[1] = fill_color[2] =
p->rt_forms[index].fill_brightness;
3444 fill_color[0] =
p->rt_forms[index].fill_color[0] +
p->rt_forms[index].fill_brightness;
3445 fill_color[1] =
p->rt_forms[index].fill_color[1] +
p->rt_forms[index].fill_brightness;
3446 fill_color[2] =
p->rt_forms[index].fill_color[2] +
p->rt_forms[index].fill_brightness;
3448 fill_color[3] = 0.0f;
3450 _retouch_fill(layer, roi_layer, mask_scaled, &roi_mask_scaled, form_opacity, fill_color);
3453 fprintf(stderr,
"rt_process_forms: unknown algorithm %i\n", algo);
3475 float *in_retouch = NULL;
3485 const int display_wavelet_scale = (
g && gui_active) ?
g->display_wavelet_scale : 0;
3499 usr_data.
self = self;
3500 usr_data.
pipe = pipe;
3501 usr_data.
piece = piece;
3502 usr_data.
roi = *roi_rt;
3505 && (pipe == self->
dev->
pipe));
3511 p->merge_from_scale, &usr_data,
3512 roi_in->
scale, use_sse);
3524 for(
size_t j = 0; j < (size_t)roi_rt->
width * roi_rt->
height * 4; j += 4) in_retouch[j + 3] = 0.f;
3537 if(dwt_p->
scales > max_scales)
3539 dt_control_log(_(
"max scale is %i for this image size"), max_scales);
3561 g->preview_auto_levels = -1;
3569 for(
int i = 0;
i < 3;
i++)
g->preview_levels[
i] =
levels[
i];
3572 g->preview_auto_levels = 2;
3586 dt_iop_alpha_copy(ivoid, in_retouch, roi_rt->
width, roi_rt->
height);
3607 const float *
const in,
float *
const out,
const dt_iop_roi_t *
const roi_in,
3617 const int devid, cl_mem dev_img,
const int width,
const int height,
3620 cl_int err = CL_SUCCESS;
3624 float *src_buffer = NULL;
3629 fprintf(stderr,
"dt_heal_cl: error allocating memory for healing\n");
3636 if(err != CL_SUCCESS)
3645 if(err != CL_SUCCESS)
3657 const int devid, cl_mem dev_img,
const int width,
const int height,
3660 cl_int err = CL_SUCCESS;
3664 float *src_buffer = NULL;
3669 fprintf(stderr,
"dt_heal_cl: error allocating memory for healing\n");
3676 if(err != CL_SUCCESS)
3685 if(err != CL_SUCCESS)
3697 cl_mem dev_out,
const struct dt_iop_roi_t *
const roi_out,
const int dx,
3698 const int dy,
const int kernel)
3700 cl_int err = CL_SUCCESS;
3702 const int xoffs = roi_out->
x - roi_in->
x - dx;
3703 const int yoffs = roi_out->
y - roi_in->
y - dy;
3705 cl_mem dev_roi_in = NULL;
3706 cl_mem dev_roi_out = NULL;
3708 const size_t sizes[]
3715 fprintf(stderr,
"rt_copy_in_to_out_cl error 1\n");
3716 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3727 if(err != CL_SUCCESS)
3729 fprintf(stderr,
"rt_copy_in_to_out_cl error 2\n");
3741 float **mask_scaled, cl_mem *p_dev_mask_scaled,
3743 const int dy,
const int algo)
3745 cl_int err = CL_SUCCESS;
3753 const cl_mem dev_mask_scaled
3757 fprintf(stderr,
"rt_build_scaled_mask_cl error 2\n");
3758 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3763 sizeof(
float) * roi_mask_scaled->
width * roi_mask_scaled->
height, CL_TRUE);
3764 if(err != CL_SUCCESS)
3766 fprintf(stderr,
"rt_build_scaled_mask_cl error 4\n");
3770 *p_dev_mask_scaled = dev_mask_scaled;
3773 if(err != CL_SUCCESS) fprintf(stderr,
"rt_build_scaled_mask_cl error\n");
3782 cl_int err = CL_SUCCESS;
3786 const cl_mem dev_roi_dest =
3789 const cl_mem dev_roi_mask_scaled
3794 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3805 if(err != CL_SUCCESS)
goto cleanup;
3815 cl_mem dev_mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
3818 cl_int err = CL_SUCCESS;
3825 const cl_mem dev_roi_mask_scaled
3829 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3839 if(err != CL_SUCCESS)
goto cleanup;
3850 cl_mem dev_mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
const int dx,
3853 cl_int err = CL_SUCCESS;
3859 sizeof(
float) *
ch * roi_mask_scaled->
width * roi_mask_scaled->
height);
3862 fprintf(stderr,
"retouch_clone_cl error 2\n");
3863 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3870 if(err != CL_SUCCESS)
3872 fprintf(stderr,
"retouch_clone_cl error 4\n");
3877 err =
rt_copy_image_masked_cl(devid, dev_src, dev_layer, roi_layer, dev_mask_scaled, roi_mask_scaled, opacity,
3879 if(err != CL_SUCCESS)
3881 fprintf(stderr,
"retouch_clone_cl error 5\n");
3892 cl_mem dev_mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
const float opacity,
3895 cl_int err = CL_SUCCESS;
3902 const cl_mem dev_roi_mask_scaled
3906 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3919 if(err != CL_SUCCESS)
goto cleanup;
3930 cl_mem dev_mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
const float opacity,
3933 cl_int err = CL_SUCCESS;
3935 if(fabsf(blur_radius) <= 0.1f)
return err;
3937 const float sigma = blur_radius * roi_layer->
scale;
3940 const cl_mem dev_dest =
3944 fprintf(stderr,
"retouch_blur_cl error 2\n");
3945 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3958 if(err != CL_SUCCESS)
goto cleanup;
3963 if(err != CL_SUCCESS)
3965 fprintf(stderr,
"retouch_blur_cl error 4\n");
3971 float Labmax[] = { INFINITY, INFINITY, INFINITY, INFINITY };
3972 float Labmin[] = { -INFINITY, -INFINITY, -INFINITY, -INFINITY };
3980 if(err != CL_SUCCESS)
goto cleanup;
3987 const float detail = -1.0f;
4002 err =
rt_copy_image_masked_cl(devid, dev_dest, dev_layer, roi_layer, dev_mask_scaled, roi_mask_scaled, opacity,
4004 if(err != CL_SUCCESS)
4006 fprintf(stderr,
"retouch_blur_cl error 5\n");
4019 if(err != CL_SUCCESS)
goto cleanup;
4029 cl_mem dev_mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
const int dx,
4032 cl_int err = CL_SUCCESS;
4036 cl_mem dev_dest = NULL;
4038 sizeof(
float) *
ch * roi_mask_scaled->
width * roi_mask_scaled->
height);
4041 fprintf(stderr,
"retouch_heal_cl: error allocating memory for healing\n");
4042 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
4047 sizeof(
float) *
ch * roi_mask_scaled->
width * roi_mask_scaled->
height);
4050 fprintf(stderr,
"retouch_heal_cl: error allocating memory for healing\n");
4051 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
4057 if(err != CL_SUCCESS)
4059 fprintf(stderr,
"retouch_heal_cl error 4\n");
4065 if(err != CL_SUCCESS)
4067 fprintf(stderr,
"retouch_heal_cl error 4\n");
4075 err =
dt_heal_cl(hp, dev_src, dev_dest, mask_scaled, roi_mask_scaled->
width, roi_mask_scaled->
height, max_iter);
4081 if(err != CL_SUCCESS)
goto cleanup;
4085 err =
rt_copy_image_masked_cl(devid, dev_dest, dev_layer, roi_layer, dev_mask_scaled, roi_mask_scaled, opacity,
4087 if(err != CL_SUCCESS)
4089 fprintf(stderr,
"retouch_heal_cl error 6\n");
4102 cl_int err = CL_SUCCESS;
4115 if(scale > wt_p->
scales + 1)
return err;
4120 const int devid = pipe->
devid;
4123 const int mask_display
4131 scale =
p->num_scales + 1;
4140 for(
const GList *forms = grp->
points; forms && err == CL_SUCCESS; forms = g_list_next(forms))
4145 fprintf(stderr,
"rt_process_forms: invalid form\n");
4148 const int formid = grpt->
formid;
4149 const float form_opacity = grpt->
opacity;
4152 fprintf(stderr,
"rt_process_forms: form is null\n");
4159 fprintf(stderr,
"rt_process_forms: missing form=%i from array\n", formid);
4164 if(
p->rt_forms[index].scale != scale)
4173 fprintf(stderr,
"rt_process_forms: missing form=%i from masks\n", formid);
4188 &roi_mask.
x, &roi_mask.
y);
4191 fprintf(stderr,
"rt_process_forms: error retrieving mask\n");
4195 float dx = 0.f, dy = 0.f;
4202 p->rt_forms[index].distort_mode))
4210 cl_mem dev_mask_scaled = NULL;
4211 float *mask_scaled = NULL;
4215 roi_layer, dx, dy, algo);
4234 dev_mask_scaled = NULL;
4238 if((err == CL_SUCCESS)
4240 && ((roi_mask_scaled.
width > 2) && (roi_mask_scaled.
height > 2)))
4244 err =
_retouch_clone_cl(devid, dev_layer, roi_layer, dev_mask_scaled, &roi_mask_scaled, dx, dy,
4249 err =
_retouch_heal_cl(devid, dev_layer, roi_layer, mask_scaled, dev_mask_scaled, &roi_mask_scaled, dx,
4250 dy, form_opacity, gd,
p->max_heal_iter);
4254 err =
_retouch_blur_cl(devid, dev_layer, roi_layer, dev_mask_scaled, &roi_mask_scaled, form_opacity,
4255 p->rt_forms[index].blur_type,
p->rt_forms[index].blur_radius, gd);
4264 fill_color[0] = fill_color[1] = fill_color[2] =
p->rt_forms[index].fill_brightness;
4268 fill_color[0] =
p->rt_forms[index].fill_color[0] +
p->rt_forms[index].fill_brightness;
4269 fill_color[1] =
p->rt_forms[index].fill_color[1] +
p->rt_forms[index].fill_brightness;
4270 fill_color[2] =
p->rt_forms[index].fill_color[2] +
p->rt_forms[index].fill_brightness;
4273 err =
_retouch_fill_cl(devid, dev_layer, roi_layer, dev_mask_scaled, &roi_mask_scaled, form_opacity,
4277 fprintf(stderr,
"rt_process_forms: unknown algorithm %i\n", algo);
4301 cl_int err = CL_SUCCESS;
4302 const int devid = pipe->
devid;
4312 const int display_wavelet_scale = (
g && gui_active) ?
g->display_wavelet_scale : 0;
4319 dt_print(
DT_DEBUG_OPENCL,
"[retouch process_cl] error allocating memory for wavelet decompose on device %d\n", devid);
4320 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
4326 size_t origin[] = { 0, 0, 0 };
4327 size_t region[] = { roi_rt->
width, roi_rt->
height, 1 };
4329 if(err != CL_SUCCESS)
goto cleanup;
4333 usr_data.
self = self;
4334 usr_data.
pipe = pipe;
4335 usr_data.
piece = piece;
4336 usr_data.
roi = *roi_rt;
4339 && (pipe == self->
dev->
pipe));
4344 (!display_wavelet_scale
4346 p->merge_from_scale, &usr_data,
4351 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
4372 if(err != CL_SUCCESS)
goto cleanup;
4385 if(dwt_p->
scales > max_scales)
4387 dt_control_log(_(
"max scale is %i for this image size"), max_scales);
4396 if(err != CL_SUCCESS)
goto cleanup;
4406 g->preview_auto_levels = -1;
4412 if(err != CL_SUCCESS)
goto cleanup;
4416 for(
int i = 0;
i < 3;
i++)
g->preview_levels[
i] =
levels[
i];
4419 g->preview_auto_levels = 2;
4428 if(err != CL_SUCCESS)
goto cleanup;
4442 if(err != CL_SUCCESS)
goto cleanup;
4456 return (err == CL_SUCCESS) ?
TRUE :
FALSE;
4467 const int formid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget),
"formid"));
4468 const int algo = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget),
"algo"));
4470 if(index < 0)
return;
4472 if(
p->rt_forms[index].algorithm == algo)
return;
4477 p->rt_forms[index].algorithm = algo;
4484 masks_type &= ~DT_MASKS_NON_CLONE;
4488 masks_type &= ~DT_MASKS_CLONE;
4491 form->
type = masks_type;
4505 fprintf(stderr,
"populate_masks_context_menu: missing form=%i from array\n", formid);
4511 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), sub_menu);
4522 for(
size_t i = 0;
i < G_N_ELEMENTS(algo_entries);
i++)
4524 const gboolean is_selected = (
p->rt_forms[index].algorithm == algo_entries[
i].algo);
4525 const char *
const label = _(algo_entries[
i].
name);
4528 is_selected,
FALSE);
4530 g_object_set_data(G_OBJECT(algo_item),
"formid", GINT_TO_POINTER(formid));
4531 g_object_set_data(G_OBJECT(algo_item),
"algo", GINT_TO_POINTER(algo_entries[
i].algo));
void cleanup(dt_imageio_module_format_t *self)
int levels(struct dt_imageio_module_data_t *data)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
float dt_bauhaus_slider_get(GtkWidget *widget)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
GtkWidget * dt_bauhaus_slider_new_with_range(dt_bauhaus_t *bh, dt_gui_module_t *self, float min, float max, float step, float defval, int digits)
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
void dt_bilateral_free(dt_bilateral_t *b)
__DT_CLONE_TARGETS__ void dt_bilateral_splat(const dt_bilateral_t *b, const float *const in)
dt_bilateral_t * dt_bilateral_init(const int width, const int height, const float sigma_s, const float sigma_r)
__DT_CLONE_TARGETS__ void dt_bilateral_slice(const dt_bilateral_t *const b, const float *const in, float *out, const float detail)
void dt_bilateral_blur(const dt_bilateral_t *b)
void dt_bilateral_free_cl(dt_bilateral_cl_t *b)
cl_int dt_bilateral_slice_cl(dt_bilateral_cl_t *b, cl_mem in, cl_mem out, const float detail)
dt_bilateral_cl_t * dt_bilateral_init_cl(const int devid, const int width, const int height, const float sigma_s, const float sigma_r)
cl_int dt_bilateral_blur_cl(dt_bilateral_cl_t *b)
cl_int dt_bilateral_splat_cl(dt_bilateral_cl_t *b, cl_mem in)
const dt_iop_gui_blendif_colorstop_t _gradient_L[]
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
void dt_iop_color_picker_reset(dt_iop_module_t *module, gboolean keep)
GtkWidget * dt_color_picker_new(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w)
const dt_aligned_pixel_t f
static const float const float const float min
static dt_aligned_pixel_t XYZ
static dt_aligned_pixel_t Lab
const dt_colormatrix_t dt_aligned_pixel_t out
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
void dt_conf_set_float(const char *name, float val)
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_center()
request redraw of center window. This redraws the center view within a gdk critical section to preven...
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_free_align(ptr)
static void * dt_calloc_align(size_t size)
#define dt_gui_freeze_begin()
#define dt_gui_freeze_end()
#define for_each_channel(_var,...)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
float dt_boundingbox_t[4]
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...
void void void gboolean dt_gui_widgets_suppressed(void)
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define dt_pixelpipe_cache_free_align(mem)
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR__(...)
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_dev_add_history_item(dev, module, enable, redraw)
#define dt_dev_pixelpipe_update_history_main(dev)
int dt_dev_distort_transform_plus(const dt_dev_pixelpipe_t *pipe, const double iop_order, const int transf_direction, float *points, size_t points_count)
dt_dev_pixelpipe_display_mask_t
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
@ DT_DEV_PIXELPIPE_DISPLAY_PASSTHRU
@ DT_DEV_PIXELPIPE_DISPLAY_NONE
@ DT_DEV_TRANSFORM_DIR_BACK_INCL
void dtgtk_cairo_paint_paste_forms(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_showmask(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_cut_forms(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_triangle(cairo_t *cr, gint x, int y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_tool_heal(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_tool_blur(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_auto_levels(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_tool_clone(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_solid_triangle(cairo_t *cr, gint x, int y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_eye_toggle(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_display_wavelet_scale(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_tool_fill(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_masks_edit(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
static int dt_pthread_rwlock_unlock(dt_pthread_rwlock_t *rwlock)
static int dt_pthread_rwlock_rdlock(dt_pthread_rwlock_t *rwlock)
int dt_dwt_first_scale_visible_cl(dwt_params_cl_t *p)
int dwt_decompose(dwt_params_t *p, _dwt_layer_func layer_func)
int dwt_get_max_scale(dwt_params_t *p)
void dt_dwt_free(dwt_params_t *p)
dwt_params_cl_t * dt_dwt_init_cl(const int devid, cl_mem image, const int width, const int height, const int scales, const int return_layer, const int merge_from_scale, void *user_data, const float preview_scale)
void dt_dwt_free_cl(dwt_params_cl_t *p)
dwt_params_t * dt_dwt_init(float *image, const int width, const int height, const int ch, const int scales, const int return_layer, const int merge_from_scale, void *user_data, const float preview_scale, const int use_sse)
cl_int dwt_decompose_cl(dwt_params_cl_t *p, _dwt_layer_func_cl layer_func)
int dwt_get_max_scale_cl(dwt_params_cl_t *p)
int dt_dwt_first_scale_visible(dwt_params_t *p)
void dt_gaussian_free(dt_gaussian_t *g)
void dt_gaussian_free_cl(dt_gaussian_cl_t *g)
cl_int dt_gaussian_blur_cl(dt_gaussian_cl_t *g, cl_mem dev_in, cl_mem dev_out)
void dt_gaussian_blur_4c(dt_gaussian_t *g, const float *const in, float *const out)
dt_gaussian_cl_t * dt_gaussian_init_cl(const int devid, const int width, const int height, const int channels, const float *max, const float *min, const float sigma, const int order)
dt_gaussian_t * dt_gaussian_init(const int width, const int height, const int channels, const float *max, const float *min, const float sigma, const int order)
void dtgtk_gradient_slider_multivalue_set_values(GtkDarktableGradientSlider *gslider, gdouble *values)
void dtgtk_gradient_slider_multivalue_get_values(GtkDarktableGradientSlider *gslider, gdouble *values)
GtkWidget * dtgtk_gradient_slider_multivalue_new_with_color_and_name(GdkRGBA start, GdkRGBA end, gint positions, gchar *name)
void dtgtk_gradient_slider_multivalue_set_marker(GtkDarktableGradientSlider *gslider, gint mark, gint pos)
void dtgtk_gradient_slider_multivalue_set_resetvalues(GtkDarktableGradientSlider *gslider, gdouble *values)
#define DTGTK_GRADIENT_SLIDER_MULTIVALUE(obj)
@ GRADIENT_SLIDER_MARKER_LOWER_OPEN_BIG
@ GRADIENT_SLIDER_MARKER_LOWER_FILLED_BIG
gboolean dt_gui_get_scroll_unit_deltas(const GdkEventScroll *event, int *delta_x, int *delta_y)
static cairo_surface_t * dt_cairo_image_surface_create(cairo_format_t format, int width, int height)
static GtkWidget * dt_ui_section_label_new(const gchar *str)
#define DT_GUI_BOX_SPACING
#define DT_PIXEL_APPLY_DPI(value)
static GtkWidget * dt_ui_label_new(const gchar *str)
void dt_heal_free_cl(heal_params_cl_t *p)
void dt_heal(const float *const src_buffer, float *dest_buffer, const float *const mask_buffer, const int width, const int height, const int ch, const int max_iter)
cl_int dt_heal_cl(heal_params_cl_t *p, cl_mem dev_src, cl_mem dev_dest, const float *const mask_buffer, const int width, const int height, const int max_iter)
heal_params_cl_t * dt_heal_init_cl(const int devid)
__DT_CLONE_TARGETS__ void dt_iop_image_fill(float *const buf, const float fill_value, const size_t width, const size_t height, const size_t ch)
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_set_cache_bypass_variant(dt_iop_module_t *module, int variant)
void dt_iop_default_init(dt_iop_module_t *module)
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)
void dt_iop_set_cache_bypass(dt_iop_module_t *module, gboolean state)
static void dt_iop_gui_enter_critical_section(dt_iop_module_t *const module) ACQUIRE(&module -> gui_lock)
@ IOP_FLAGS_INTERNAL_MASKS
@ IOP_FLAGS_SUPPORTS_BLENDING
static void dt_iop_gui_leave_critical_section(dt_iop_module_t *const module) RELEASE(&module -> gui_lock)
#define IOP_GUI_ALLOC(module)
GtkWidget * dt_iop_togglebutton_new(dt_iop_module_t *self, const char *section, const gchar *label, const gchar *ctrl_label, GCallback callback, gboolean local, guint accel_key, GdkModifierType mods, DTGTKCairoPaintIconFunc paint, GtkWidget *box)
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
GtkWidget * dt_bauhaus_combobox_from_params(dt_iop_module_t *self, const char *param)
static float kernel(const float *x, const float *y)
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)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_work_profile_info(const struct dt_dev_pixelpipe_t *pipe)
float *const restrict const size_t const size_t ch
@ DT_MASKS_SHAPE_INDEX_BRUSH
@ DT_MASKS_SHAPE_INDEX_ELLIPSE
@ DT_MASKS_SHAPE_INDEX_CIRCLE
@ DT_MASKS_SHAPE_INDEX_POLYGON
void dt_masks_change_form_gui(dt_masks_form_t *newform)
@ DT_MASKS_EDIT_RESTRICTED
void dt_masks_reset_form_gui(void)
void dt_masks_shape_buttons_deactivate_all(GtkWidget *active_button)
GtkWidget * dt_masks_shape_buttons_create(const dt_masks_shape_buttons_config_t *config)
Build a synchronized toolbar for creating masks shapes.
void dt_masks_group_ungroup(dt_masks_form_t *dest_grp, dt_masks_form_t *grp)
@ DT_MASKS_SHAPE_BUTTONS_ALL
gboolean dt_masks_creation_mode_enter(dt_iop_module_t *module, const dt_masks_type_t type)
Enter mask creation mode for a given shape type.
dt_masks_form_t * dt_masks_get_from_id_ext(GList *forms, int id)
dt_masks_form_t * dt_masks_get_from_id(dt_develop_t *dev, int id)
dt_masks_form_group_t * dt_masks_form_get_selected_group_live(const struct dt_masks_form_t *form, const struct dt_masks_form_gui_t *gui)
Return the currently selected group entry, resolving to the live form group when the GUI is operating...
static int dt_masks_get_mask(const dt_iop_module_t *const module, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *const piece, dt_masks_form_t *const form, float **buffer, int *width, int *height, int *posx, int *posy)
#define DEVELOP_MASKS_NB_SHAPES
int dt_masks_get_source_area(dt_iop_module_t *module, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, int *width, int *height, int *posx, int *posy)
dt_masks_form_t * dt_masks_get_visible_form(const struct dt_develop_t *dev)
void dt_masks_set_edit_mode(struct dt_iop_module_t *module, dt_masks_edit_mode_t value)
int dt_masks_get_area(dt_iop_module_t *module, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, int *width, int *height, int *posx, int *posy)
dt_masks_form_t * dt_masks_create_ext(dt_masks_type_t type)
float dt_aligned_pixel_t[4]
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
void * dt_opencl_alloc_device_buffer(const int devid, const size_t size)
void * dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
int dt_opencl_create_kernel(const int prog, const char *name)
void * dt_opencl_copy_host_to_device_constant(const int devid, const size_t size, void *host)
int dt_opencl_write_buffer_to_device(const int devid, void *host, void *device, const size_t offset, const size_t size, const int blocking)
int dt_opencl_read_buffer_from_device(const int devid, void *host, void *device, const size_t offset, const size_t size, const int blocking)
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)
int dt_opencl_enqueue_copy_image_to_buffer(const int devid, cl_mem src_image, cl_mem dst_buffer, size_t *origin, size_t *region, size_t offset)
void dt_opencl_release_mem_object(cl_mem mem)
#define DT_OPENCL_SYSMEM_ALLOCATION
static cl_int _retouch_heal_cl(const int devid, cl_mem dev_layer, dt_iop_roi_t *const roi_layer, float *mask_scaled, cl_mem dev_mask_scaled, dt_iop_roi_t *const roi_mask_scaled, const int dx, const int dy, const float opacity, dt_iop_retouch_global_data_t *gd, const int max_iter)
static gboolean rt_shape_buttons_can_start(GtkWidget *button, dt_iop_module_t *self, dt_masks_type_t type, gpointer user_data)
static cl_int rt_build_scaled_mask_cl(const int devid, float *const mask, dt_iop_roi_t *const roi_mask, float **mask_scaled, cl_mem *p_dev_mask_scaled, dt_iop_roi_t *roi_mask_scaled, dt_iop_roi_t *const roi_in, const int dx, const int dy, const int algo)
static int rt_masks_get_delta_to_destination(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi, dt_masks_form_t *form, float *dx, float *dy, const int distort_mode)
static dt_masks_type_t rt_shape_buttons_form_type(dt_iop_module_t *self, dt_masks_type_t type, gpointer user_data)
dt_iop_retouch_fill_modes_t
@ DT_IOP_RETOUCH_FILL_COLOR
@ DT_IOP_RETOUCH_FILL_ERASE
static float rt_gslider_scale_callback(GtkWidget *self, float inval, int dir)
static void rt_copy_mask_to_alpha(float *const img, dt_iop_roi_t *const roi_img, const int ch, float *const mask_scaled, dt_iop_roi_t *const roi_mask_scaled, const float opacity)
void init(dt_iop_module_t *module)
static void rt_num_scales_update(const int _num_scales, dt_iop_module_t *self)
void distort_mask(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, const float *const in, float *const out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
static void rt_resynch_params(struct dt_iop_module_t *self, dt_iop_retouch_params_t *p, GList *forms_list)
const char ** description(struct dt_iop_module_t *self)
static cl_int rt_copy_mask_to_alpha_cl(const int devid, cl_mem dev_layer, dt_iop_roi_t *const roi_layer, cl_mem dev_mask_scaled, dt_iop_roi_t *const roi_mask_scaled, const float opacity, dt_iop_retouch_global_data_t *gd)
static void rt_extend_roi_in_for_clone(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *const pipe, struct dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t *roi_in, int *_roir, int *_roib, int *_roix, int *_roiy)
static float rt_get_shape_opacity(dt_iop_module_t *self, const int formid)
static int _retouch_clone(float *const in, dt_iop_roi_t *const roi_in, float *const mask_scaled, dt_iop_roi_t *const roi_mask_scaled, const int dx, const int dy, const float opacity)
static void rt_menu_select_algorithm_callback(GtkWidget *widget, gpointer user_data)
static gboolean rt_select_algorithm_callback(GtkToggleButton *togglebutton, GdkEventButton *e, dt_iop_module_t *self)
dt_iop_retouch_algo_type_t
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *params, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static cl_int _retouch_blur_cl(const int devid, cl_mem dev_layer, dt_iop_roi_t *const roi_layer, cl_mem dev_mask_scaled, dt_iop_roi_t *const roi_mask_scaled, const float opacity, const int blur_type, const float blur_radius, dt_iop_retouch_global_data_t *gd)
void masks_selection_changed(struct dt_iop_module_t *self, const int form_selected_id)
void gui_update(dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
cl_int rt_process_stats_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const int devid, cl_mem dev_img, const int width, const int height, float levels[3])
dt_iop_retouch_drag_types_t
@ DT_IOP_RETOUCH_WDBAR_DRAG_BOTTOM
@ DT_IOP_RETOUCH_WDBAR_DRAG_TOP
static float rt_masks_form_get_opacity(dt_iop_module_t *self, int formid)
static void image_lab2rgb(float *img_src, const int width, const int height, const int ch, const int use_sse)
struct dt_iop_retouch_params_t dt_iop_retouch_data_t
static void rt_merge_from_scale_update(const int _merge_from_scale, dt_iop_module_t *self)
static void rt_sync_mask_display_request(dt_iop_module_t *module, dt_iop_retouch_gui_data_t *g)
static cl_int rt_copy_image_masked_cl(const int devid, cl_mem dev_src, cl_mem dev_dest, dt_iop_roi_t *const roi_dest, cl_mem dev_mask_scaled, dt_iop_roi_t *const roi_mask_scaled, const float opacity, const int kernel)
void gui_focus(struct dt_iop_module_t *self, gboolean in)
#define RETOUCH_MAX_SCALES
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static gboolean rt_edit_masks_callback(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self)
static int rt_get_selected_shape_id(const dt_iop_module_t *self)
static dt_masks_form_group_t * rt_get_mask_point_group(dt_iop_module_t *self, int formid)
static gboolean rt_wdbar_motion_notify(GtkWidget *widget, GdkEventMotion *event, dt_iop_module_t *self)
static void rt_display_selected_shapes_lbl(dt_iop_retouch_gui_data_t *g)
void gui_reset(struct dt_iop_module_t *self)
static cl_int _retouch_clone_cl(const int devid, cl_mem dev_layer, dt_iop_roi_t *const roi_layer, cl_mem dev_mask_scaled, dt_iop_roi_t *const roi_mask_scaled, const int dx, const int dy, const float opacity, dt_iop_retouch_global_data_t *gd)
static cl_int rt_copy_in_to_out_cl(const int devid, cl_mem dev_in, const struct dt_iop_roi_t *const roi_in, cl_mem dev_out, const struct dt_iop_roi_t *const roi_out, const int dx, const int dy, const int kernel)
static void rt_develop_ui_pipe_finished_callback(gpointer instance, gpointer user_data)
static gboolean rt_any_preview_active(dt_iop_retouch_gui_data_t *g)
void gui_init(dt_iop_module_t *self)
void change_image(struct dt_iop_module_t *self)
static void image_rgb2lab(float *img_src, const int width, const int height, const int ch, const int use_sse)
static __DT_CLONE_TARGETS__ int process_internal(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, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out, const int use_sse)
static __DT_CLONE_TARGETS__ void rt_adjust_levels(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, float *img_src, const int width, const int height, const int ch, const float levels[3])
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
#define RETOUCH_NO_SCALES
void tiling_callback(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, struct dt_develop_tiling_t *tiling)
static gboolean rt_masks_form_is_in_roi(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out)
static int rt_shape_is_being_added(dt_iop_module_t *self, const int shape_type)
static gboolean rt_wdbar_draw(GtkWidget *widget, cairo_t *crf, dt_iop_module_t *self)
void gui_cleanup(dt_iop_module_t *self)
static cl_int rt_process_forms_cl(cl_mem dev_layer, dwt_params_cl_t *const wt_p, const int scale1)
dt_iop_retouch_blur_types_t
@ DT_IOP_RETOUCH_BLUR_GAUSSIAN
@ DT_IOP_RETOUCH_BLUR_BILATERAL
static __DT_CLONE_TARGETS__ void rt_copy_in_to_out(const float *const in, const struct dt_iop_roi_t *const roi_in, float *const out, const struct dt_iop_roi_t *const roi_out, const int ch, const int dx, const int dy)
void cleanup_global(dt_iop_module_so_t *module)
void reload_defaults(dt_iop_module_t *self)
static gboolean rt_wdbar_scrolled(GtkWidget *widget, GdkEventScroll *event, dt_iop_module_t *self)
void post_history_commit(dt_iop_module_t *self)
static gboolean rt_algo_pair_compatible(const dt_iop_retouch_algo_type_t from, const dt_iop_retouch_algo_type_t to)
static gboolean rt_suppress_callback(GtkToggleButton *togglebutton, GdkEventButton *event, dt_iop_module_t *module)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
static void rt_gslider_changed(GtkDarktableGradientSlider *gslider, dt_iop_module_t *self)
#define RETOUCH_PREVIEW_LVL_MIN
void gui_post_expose(struct dt_iop_module_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery)
static void rt_show_forms_for_current_scale(dt_iop_module_t *self)
static void rt_show_hide_controls(const dt_iop_module_t *self)
static void rt_colorpick_color_set_callback(GtkColorButton *widget, dt_iop_module_t *self)
static void _retouch_fill(float *const in, dt_iop_roi_t *const roi_in, float *const mask_scaled, dt_iop_roi_t *const roi_mask_scaled, const float opacity, const float *const fill_color)
static void rt_copy_image_masked(float *const img_src, float *img_dest, dt_iop_roi_t *const roi_dest, float *const mask_scaled, dt_iop_roi_t *const roi_mask_scaled, const float opacity)
static cl_int _retouch_fill_cl(const int devid, cl_mem dev_layer, dt_iop_roi_t *const roi_layer, cl_mem dev_mask_scaled, dt_iop_roi_t *const roi_mask_scaled, const float opacity, float *color, dt_iop_retouch_global_data_t *gd)
static void rt_masks_point_denormalize(const dt_dev_pixelpipe_t *pipe, const dt_iop_roi_t *roi, const float *points, size_t points_count, float *new)
static gboolean rt_wdbar_button_release(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self)
static void rt_sync_bypass_cache(dt_iop_module_t *module, dt_iop_retouch_gui_data_t *g)
static int rt_scale_has_shapes(dt_iop_retouch_params_t *p, const int scale)
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 gboolean rt_wdbar_leave_notify(GtkWidget *widget, GdkEventCrossing *event, dt_iop_module_t *self)
static gboolean rt_blend_mask_conflicts(dt_iop_module_t *module, dt_iop_retouch_gui_data_t *g)
static int rt_process_forms(float *layer, dwt_params_t *const wt_p, const int scale1)
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void rt_compute_roi_in(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *const pipe, struct dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t *roi_in, int *_roir, int *_roib, int *_roix, int *_roiy)
static gboolean rt_showmask_callback(GtkToggleButton *togglebutton, GdkEventButton *event, dt_iop_module_t *module)
static void rt_load_shape_algo_in_gui(dt_iop_module_t *self, const int form_selected_id)
static int rt_get_index_from_formid(dt_iop_retouch_params_t *p, const int formid)
cl_int rt_adjust_levels_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const int devid, cl_mem dev_img, const int width, const int height, const float levels[3])
static void rt_curr_scale_update(const int _curr_scale, dt_iop_module_t *self)
static __DT_CLONE_TARGETS__ void rt_process_stats(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, float *const img_src, const int width, const int height, const int ch, float levels[3])
static void rt_update_wd_bar_labels(dt_iop_retouch_params_t *p, dt_iop_retouch_gui_data_t *g)
void init_global(dt_iop_module_so_t *module)
static int _retouch_blur(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, float *const in, dt_iop_roi_t *const roi_in, float *const mask_scaled, dt_iop_roi_t *const roi_mask_scaled, const float opacity, const int blur_type, const float blur_radius, const int use_sse)
static gboolean rt_auto_levels_callback(GtkToggleButton *togglebutton, GdkEventButton *event, dt_iop_module_t *self)
static void rt_mask_opacity_callback(GtkWidget *slider, dt_iop_module_t *self)
static void rt_display_selected_fill_color(dt_iop_retouch_gui_data_t *g, dt_iop_retouch_params_t *p)
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 rt_intersect_2_rois(dt_iop_roi_t *const roi_1, dt_iop_roi_t *const roi_2, const int dx, const int dy, const int padding, dt_iop_roi_t *roi_dest)
static gboolean rt_copypaste_scale_callback(GtkToggleButton *togglebutton, GdkEventButton *event, dt_iop_module_t *self)
static gboolean rt_wdbar_button_press(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self)
static int _retouch_heal(float *const in, dt_iop_roi_t *const roi_in, float *const mask_scaled, dt_iop_roi_t *const roi_mask_scaled, const int dx, const int dy, const float opacity, const int max_iter)
static int rt_allow_create_form(dt_iop_module_t *self)
static int rt_get_selected_shape_index(dt_iop_retouch_params_t *p)
int populate_masks_context_menu(struct dt_iop_module_t *self, GtkWidget *menu, const int formid, const float pzx, const float pzy)
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static int rt_build_scaled_mask(float *const mask, dt_iop_roi_t *const roi_mask, float **mask_scaled, dt_iop_roi_t *roi_mask_scaled, dt_iop_roi_t *const roi_in, const int dx, const int dy, const int algo)
void modify_roi_in(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi_out, dt_iop_roi_t *roi_in)
static gboolean rt_display_wavelet_scale_callback(GtkToggleButton *togglebutton, GdkEventButton *event, dt_iop_module_t *self)
#define RETOUCH_PREVIEW_LVL_MAX
void modify_roi_out(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t *roi_out, const dt_iop_roi_t *roi_in)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
static void rt_extend_roi_in_from_source_clones(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *const pipe, struct dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t *roi_in, const int formid_src, const int fl_src, const int ft_src, const int fw_src, const int fh_src, int *_roir, int *_roib, int *_roix, int *_roiy)
static void rt_masks_form_change_opacity(dt_iop_module_t *self, int formid, float opacity)
static void rt_paste_forms_from_scale(dt_iop_retouch_params_t *p, const int source_scale, const int dest_scale)
static int rt_masks_point_calc_delta(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi, const float *target, const float *source, float *dx, float *dy, const int distort_mode)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
@ DT_SIGNAL_DEVELOP_UI_PIPE_FINISHED
This signal is raised when pipe is finished and the gui is attached no param, no returned value.
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
struct _GtkWidget GtkWidget
struct dt_gui_gtk_t * gui
struct dt_control_signal_t * signals
struct dt_bauhaus_t * bauhaus
struct dt_develop_t * develop
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_dev_pixelpipe_type_t type
struct dt_iop_module_t * gui_module
struct dt_masks_form_gui_t * form_gui
dt_pthread_rwlock_t masks_mutex
struct dt_dev_pixelpipe_t * pipe
dt_iop_global_data_t * data
GtkDarktableToggleButton * off
dt_iop_params_t * default_params
struct dt_develop_blend_params_t * blend_params
struct dt_develop_t * dev
dt_iop_gui_data_t * gui_data
dt_iop_global_data_t * global_data
dt_aligned_pixel_t picked_output_color
dt_colormatrix_t matrix_out_transposed
dt_colormatrix_t matrix_in_transposed
int kernel_retouch_copy_alpha
int kernel_retouch_clear_alpha
int kernel_retouch_copy_buffer_to_buffer_masked
int kernel_retouch_copy_image_to_buffer_masked
int kernel_retouch_image_rgb2lab
int kernel_retouch_image_lab2rgb
int kernel_retouch_copy_mask_to_alpha
int kernel_retouch_copy_buffer_to_image
int kernel_retouch_copy_buffer_to_buffer
GtkDarktableGradientSlider * preview_levels_gslider
int display_wavelet_scale
GtkWidget * cmb_blur_type
GtkWidget * bt_paste_scale
GtkWidget * sl_fill_brightness
GtkWidget * hbox_color_pick
GtkWidget * cmb_fill_mode
GtkWidget * sl_blur_radius
GtkWidget * vbox_preview_scale
GtkWidget * sl_mask_opacity
GtkWidget * bt_edit_masks
GtkLabel * label_form_selected
GtkWidget * bt_display_wavelet_scale
GtkWidget * bt_auto_levels
GtkLabel * lbl_num_scales
int displayed_wavelet_scale
GtkLabel * lbl_curr_scale
GtkWidget * bt_copy_scale
GtkLabel * lbl_merge_from_scale
dt_iop_retouch_blur_types_t blur_type
dt_iop_retouch_fill_modes_t fill_mode
dt_iop_retouch_algo_type_t algorithm
dt_iop_retouch_form_data_t rt_forms[300]
Region of interest passed through the pixelpipe.
const dt_dev_pixelpipe_t * pipe
const dt_dev_pixelpipe_iop_t * piece