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);
1536 dt_control_log(_(
"cannot display scales when the blending mask is displayed"));
1539 gtk_toggle_button_set_active(togglebutton,
FALSE);
1544 if(self->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->
off), 1);
1547 g->display_wavelet_scale = !gtk_toggle_button_get_active(togglebutton);
1557 &&
g->preview_auto_levels == 0 &&
p->curr_scale > 0 &&
p->curr_scale <=
p->num_scales)
1559 g->preview_auto_levels = 1;
1560 g->displayed_wavelet_scale = 1;
1566 gtk_toggle_button_set_active(togglebutton,
g->display_wavelet_scale);
1579 if(
g->preview_auto_levels == 2)
1581 g->preview_auto_levels = -1;
1585 for(
int i = 0;
i < 3;
i++)
p->preview_levels[
i] =
g->preview_levels[
i];
1593 for(
int i = 0;
i < 3;
i++) dlevels[
i] =
p->preview_levels[
i];
1599 g->preview_auto_levels = 0;
1604 gtk_widget_queue_draw(GTK_WIDGET(
g->wd_bar));
1613 if(self->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->
off), 1);
1617 if(
g->preview_auto_levels == 0)
1619 g->preview_auto_levels = 1;
1683 if(event->button == 1)
1692 const gboolean control_button_pressed =
dt_modifier_is(event->state, GDK_CONTROL_MASK);
1715 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
1747 if(togglebutton == (GtkToggleButton *)
g->bt_blur)
1749 else if(togglebutton == (GtkToggleButton *)
g->bt_clone)
1751 else if(togglebutton == (GtkToggleButton *)
g->bt_heal)
1753 else if(togglebutton == (GtkToggleButton *)
g->bt_fill)
1757 gboolean accept =
TRUE;
1766 if(accept)
p->algorithm = new_algo;
1783 if(
p->algorithm !=
p->rt_forms[index].algorithm)
1785 p->rt_forms[index].algorithm =
p->algorithm;
1794 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_polygon)))
1796 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_circle)))
1798 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_ellipse)))
1800 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_brush)))
1845 dt_control_log(_(
"cannot display masks when the blending mask is displayed"));
1847 gtk_toggle_button_set_active(togglebutton,
FALSE);
1851 g->mask_display = !gtk_toggle_button_get_active(togglebutton);
1853 if(module->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->
off), 1);
1858 gtk_toggle_button_set_active(togglebutton,
g->mask_display);
1867 g->suppress_mask = !gtk_toggle_button_get_active(togglebutton);
1869 if(module->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->
off), 1);
1874 gtk_toggle_button_set_active(togglebutton,
g->suppress_mask);
1883 if(w ==
g->cmb_fill_mode)
1896 p->rt_forms[index].blur_type =
p->blur_type;
1897 p->rt_forms[index].blur_radius =
p->blur_radius;
1901 p->rt_forms[index].fill_mode =
p->fill_mode;
1902 p->rt_forms[index].fill_brightness =
p->fill_brightness;
1929 d->preview_levels[1] = 0.f;
1936 const int program = 21;
1990 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
2002 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
2008 if(
g->display_wavelet_scale ||
g->mask_display ||
g->suppress_mask)
2035 const float require = 2.0f;
2036 const float require_cl = 1.0f
2037 + ((
p->num_scales > 0) ? 4.0f : 2.0f);
2041 tiling->factor = 2.0f + require;
2042 tiling->factor_cl = 2.0f + require_cl;
2044 tiling->maxbuf_cl = 1.0f;
2077 gchar *str = g_strdup_printf(
"%d", nb);
2078 gtk_label_set_text(
g->label_form, str);
2103 gtk_widget_queue_draw(GTK_WIDGET(
g->wd_bar));
2112 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_display_wavelet_scale),
g->display_wavelet_scale);
2113 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_copy_scale),
g->copied_scale >= 0);
2114 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_paste_scale),
g->copied_scale >= 0);
2115 gtk_widget_set_sensitive(
g->bt_paste_scale,
g->copied_scale >= 0);
2126 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
2131 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
2136 for(
int i = 0;
i < 3;
i++) dlevels[
i] =
p->preview_levels[
i];
2145 g->copied_scale = -1;
2146 g->mask_display = 0;
2147 g->suppress_mask = 0;
2148 g->display_wavelet_scale = 0;
2149 g->displayed_wavelet_scale = 0;
2152 g->preview_auto_levels = 0;
2154 g->preview_levels[1] = 0.f;
2158 g->wdbar_mouse_x =
g->wdbar_mouse_y = -1;
2160 g->lower_cursor =
g->upper_cursor =
FALSE;
2161 g->lower_margin =
g->upper_margin =
FALSE;
2176 g->label_form = GTK_LABEL(gtk_label_new(
"-1"));
2178 gtk_widget_set_tooltip_text(hbox_shapes,
2179 _(
"to add a shape select an algorithm and a shape type and click on the image.\n"
2180 "shapes are added to the current scale"));
2183 N_(
"show and edit shapes in restricted mode"),
2190 .creation_module = self,
2191 .buttons = shape_buttons,
2193 .action_section = N_(
"shapes"),
2204 gtk_box_pack_start(GTK_BOX(hbox_shapes), shape_buttons_box,
FALSE,
FALSE, 0);
2216 self, N_(
"tools"), N_(
"activate blur tool"), N_(
"change algorithm for current form"),
2220 self, N_(
"tools"), N_(
"activate fill tool"), N_(
"change algorithm for current form"),
2224 self, N_(
"tools"), N_(
"activate cloning tool"), N_(
"change algorithm for current form"),
2228 self, N_(
"tools"), N_(
"activate healing tool"), N_(
"change algorithm for current form"),
2232 gchar *tt2 = g_strdup_printf(
"%s\n%s", _(
"ctrl+click to change tool for current form"),
2233 _(
"shift+click to set the tool as default"));
2234 gchar *tt = g_strdup_printf(
"%s\n%s", _(
"activate blur tool"), tt2);
2235 gtk_widget_set_tooltip_text(
g->bt_blur, tt);
2237 tt = g_strdup_printf(
"%s\n%s", _(
"activate fill tool"), tt2);
2238 gtk_widget_set_tooltip_text(
g->bt_fill, tt);
2240 tt = g_strdup_printf(
"%s\n%s", _(
"activate cloning tool"), tt2);
2241 gtk_widget_set_tooltip_text(
g->bt_clone, tt);
2243 tt = g_strdup_printf(
"%s\n%s", _(
"activate healing tool"), tt2);
2244 gtk_widget_set_tooltip_text(
g->bt_heal, tt);
2249 GtkWidget *grid_wd_labels = gtk_grid_new();
2250 gtk_grid_set_column_homogeneous(GTK_GRID(grid_wd_labels),
FALSE);
2252 gtk_grid_attach(GTK_GRID(grid_wd_labels),
dt_ui_label_new(_(
"scales:")), 0, 0, 1, 1);
2254 gtk_label_set_width_chars(
g->lbl_num_scales, 2);
2255 gtk_grid_attach(GTK_GRID(grid_wd_labels), GTK_WIDGET(
g->lbl_num_scales), 1, 0, 1, 1);
2257 gtk_grid_attach(GTK_GRID(grid_wd_labels),
dt_ui_label_new(_(
"current:")), 0, 1, 1, 1);
2259 gtk_label_set_width_chars(
g->lbl_curr_scale, 2);
2260 gtk_grid_attach(GTK_GRID(grid_wd_labels), GTK_WIDGET(
g->lbl_curr_scale), 1, 1, 1, 1);
2262 gtk_grid_attach(GTK_GRID(grid_wd_labels),
dt_ui_label_new(_(
"merge from:")), 0, 2, 1, 1);
2264 gtk_label_set_width_chars(
g->lbl_merge_from_scale, 2);
2265 gtk_grid_attach(GTK_GRID(grid_wd_labels), GTK_WIDGET(
g->lbl_merge_from_scale), 1, 2, 1, 1);
2268 g->wd_bar = gtk_drawing_area_new();
2270 gtk_widget_set_tooltip_text(
g->wd_bar, _(
"top slider adjusts where the merge scales start\n"
2271 "bottom slider adjusts the number of scales\n"
2272 "dot indicates the current scale\n"
2273 "top line indicates that the scale is visible at current zoom level\n"
2274 "bottom line indicates that the scale has shapes on it"));
2275 g_signal_connect(G_OBJECT(
g->wd_bar),
"draw", G_CALLBACK(
rt_wdbar_draw), self);
2280 g_signal_connect(G_OBJECT(
g->wd_bar),
"scroll-event", G_CALLBACK(
rt_wdbar_scrolled), self);
2281 gtk_widget_add_events(GTK_WIDGET(
g->wd_bar), GDK_POINTER_MOTION_MASK
2282 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
2300 gtk_box_pack_end(GTK_BOX(hbox_scale), gtk_grid_new(),
TRUE,
TRUE, 0);
2311 gtk_box_pack_end(GTK_BOX(hbox_scale), gtk_grid_new(),
TRUE,
TRUE, 0);
2323 gtk_box_pack_start(GTK_BOX(
g->vbox_preview_scale), lbl_psc,
FALSE,
TRUE, 0);
2328 #define NEUTRAL_GRAY 0.5
2333 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->preview_levels_gslider), _(
"adjust preview levels"));
2342 (
g->preview_levels_gslider)->min_spacing = 0.05;
2343 g_signal_connect(G_OBJECT(
g->preview_levels_gslider),
"value-changed", G_CALLBACK(
rt_gslider_changed), self);
2345 gtk_box_pack_start(GTK_BOX(prev_lvl), GTK_WIDGET(
g->preview_levels_gslider),
TRUE,
TRUE, 0);
2352 gtk_box_pack_start(GTK_BOX(
g->vbox_preview_scale), prev_lvl,
TRUE,
TRUE, 0);
2356 GtkWidget *label1 = gtk_label_new(_(
"shape selected:"));
2357 gtk_label_set_ellipsize(GTK_LABEL(label1), PANGO_ELLIPSIZE_START);
2358 gtk_box_pack_start(GTK_BOX(hbox_shape_sel), label1,
FALSE,
TRUE, 0);
2359 g->label_form_selected = GTK_LABEL(gtk_label_new(
"-1"));
2360 gtk_widget_set_tooltip_text(hbox_shape_sel,
2361 _(
"click on a shape to select it,\nto unselect click on an empty space"));
2362 gtk_box_pack_start(GTK_BOX(hbox_shape_sel), GTK_WIDGET(
g->label_form_selected),
FALSE,
TRUE, 0);
2368 gtk_widget_set_tooltip_text(
g->cmb_fill_mode, _(
"erase the detail or fills with chosen color"));
2372 = (GdkRGBA){.red =
p->fill_color[0], .green =
p->fill_color[1], .blue =
p->fill_color[2], .alpha = 1.0 };
2376 gtk_box_pack_start(GTK_BOX(
g->hbox_color_pick), lbl_fill_color,
FALSE,
TRUE, 0);
2378 g->colorpick = gtk_color_button_new_with_rgba(&color);
2379 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(
g->colorpick),
FALSE);
2380 gtk_color_button_set_title(GTK_COLOR_BUTTON(
g->colorpick), _(
"select fill color"));
2381 gtk_widget_set_tooltip_text(
g->colorpick, _(
"select fill color"));
2383 gtk_box_pack_start(GTK_BOX(
g->hbox_color_pick), GTK_WIDGET(
g->colorpick),
TRUE,
TRUE, 0);
2386 gtk_widget_set_tooltip_text(
g->colorpicker, _(
"pick fill color from image"));
2388 gtk_box_pack_start(GTK_BOX(
g->vbox_fill),
g->hbox_color_pick,
TRUE,
TRUE, 0);
2393 gtk_widget_set_tooltip_text(
g->sl_fill_brightness,
2394 _(
"adjusts color brightness to fine-tune it. works with erase as well"));
2400 gtk_widget_set_tooltip_text(
g->cmb_blur_type, _(
"type for the blur algorithm"));
2404 gtk_widget_set_tooltip_text(
g->sl_blur_radius, _(
"radius of the selected blur type"));
2410 gtk_widget_set_tooltip_text(
g->sl_mask_opacity, _(
"set the opacity on the selected shape"));
2417 gtk_box_pack_start(GTK_BOX(self->
widget), lbl_rt_tools,
FALSE,
TRUE, 0);
2420 gtk_box_pack_start(GTK_BOX(self->
widget), hbox_shapes,
TRUE,
TRUE, 0);
2422 gtk_box_pack_start(GTK_BOX(self->
widget), hbox_algo,
TRUE,
TRUE, 0);
2429 gtk_box_pack_start(GTK_BOX(self->
widget), grid_wd_labels,
TRUE,
TRUE, 0);
2433 gtk_box_pack_start(GTK_BOX(self->
widget), hbox_scale,
TRUE,
TRUE, 0);
2436 gtk_box_pack_start(GTK_BOX(self->
widget),
g->vbox_preview_scale,
TRUE,
TRUE, 0);
2440 gtk_box_pack_start(GTK_BOX(self->
widget), lbl_shapes,
FALSE,
TRUE, 0);
2443 gtk_box_pack_start(GTK_BOX(self->
widget), hbox_shape_sel,
TRUE,
TRUE, 0);
2445 gtk_box_pack_start(GTK_BOX(self->
widget),
g->vbox_blur,
TRUE,
TRUE, 0);
2447 gtk_box_pack_start(GTK_BOX(self->
widget),
g->vbox_fill,
TRUE,
TRUE, 0);
2449 gtk_box_pack_start(GTK_BOX(self->
widget),
g->sl_mask_opacity,
TRUE,
TRUE, 0);
2488 dt_iop_roi_t *roi_in,
int *_roir,
int *_roib,
int *_roix,
int *_roiy)
2502 for(
const GList *forms = grp->
points; forms; forms = g_list_next(forms))
2507 const int formid = grpt->
formid;
2528 if(ft >= roi_in->
y + roi_in->
height || ft + fh <= roi_in->y || fl >= roi_in->
x + roi_in->
width
2529 || fl + fw <= roi_in->
x)
2538 roiy = fminf(ft, roiy);
2539 roix = fminf(fl, roix);
2540 roir = fmaxf(fl + fw, roir);
2541 roib = fmaxf(ft + fh, roib);
2546 const int overlap = ceilf(4 * (
p->rt_forms[index].blur_radius * roi_in->
scale));
2547 if(roiy > ft) roiy =
MAX(roiy - overlap, ft);
2548 if(roix > fl) roix =
MAX(roix - overlap, fl);
2549 if(roir < fl + fw) roir =
MAX(roir + overlap, fl + fw);
2550 if(roib < ft + fh) roib =
MAX(roib + overlap, ft + fh);
2556 float dx = 0.f, dy = 0.f;
2558 p->rt_forms[index].distort_mode))
2560 roiy = fminf(ft - dy, roiy);
2561 roix = fminf(fl - dx, roix);
2562 roir = fmaxf(fl + fw - dx, roir);
2563 roib = fmaxf(ft + fh - dy, roib);
2579 dt_iop_roi_t *roi_in,
const int formid_src,
const int fl_src,
2580 const int ft_src,
const int fw_src,
const int fh_src,
int *_roir,
2581 int *_roib,
int *_roix,
int *_roiy)
2595 for(
const GList *forms = grp->
points; forms; forms = g_list_next(forms))
2600 const int formid = grpt->
formid;
2603 if(formid == formid_src)
break;
2627 int fl_dest, ft_dest;
2628 float dx = 0.f, dy = 0.f;
2630 p->rt_forms[index].distort_mode))
2639 const int intersects = !(ft_dest + fh < ft_src || ft_src + fh_src < ft_dest || fl_dest + fw < fl_src
2640 || fl_src + fw_src < fl_dest);
2644 roiy = fminf(ft, roiy);
2645 roix = fminf(fl, roix);
2646 roir = fmaxf(fl + fw, roir);
2647 roib = fmaxf(ft + fh, roib);
2650 roiy = fminf(ft + dy, roiy);
2651 roix = fminf(fl + dx, roix);
2652 roir = fmaxf(fl + fw + dx, roir);
2653 roib = fmaxf(ft + fh + dy, roib);
2668 dt_iop_roi_t *roi_in,
int *_roir,
int *_roib,
int *_roix,
int *_roiy)
2682 for(
const GList *forms = grp->
points; forms; forms = g_list_next(forms))
2687 const int formid = grpt->
formid;
2704 int fl_src, ft_src, fw_src, fh_src;
2710 fw_src *= roi_in->
scale, fh_src *= roi_in->
scale, fl_src *= roi_in->
scale, ft_src *= roi_in->
scale;
2713 const int intersects
2714 = !(roib < ft_src || ft_src + fh_src < roiy || roir < fl_src || fl_src + fw_src < roix);
2717 &roir, &roib, &roix, &roiy);
2735 int roir = roi_in->
width + roi_in->
x;
2736 int roib = roi_in->
height + roi_in->
y;
2737 int roix = roi_in->
x;
2738 int roiy = roi_in->
y;
2740 rt_compute_roi_in(self, processing_pipe, piece, roi_in, &roir, &roib, &roix, &roiy);
2742 int roir_prev = -1, roib_prev = -1, roix_prev = -1, roiy_prev = -1;
2744 while(roir != roir_prev || roib != roib_prev || roix != roix_prev || roiy != roiy_prev)
2756 roi_in->
x = CLAMP(roix, 0, scwidth - 1);
2757 roi_in->
y = CLAMP(roiy, 0, scheight - 1);
2758 roi_in->
width = CLAMP(roir - roi_in->
x, 1, scwidth + .5f - roi_in->
x);
2759 roi_in->
height = CLAMP(roib - roi_in->
y, 1, scheight + .5f - roi_in->
y);
2770 for(
int i = 0;
i < stride;
i +=
ch)
2774 dt_linearRGB_to_XYZ(img_src +
i,
XYZ);
2783 for(
int i = 0;
i < stride;
i +=
ch)
2788 dt_XYZ_to_linearRGB(
XYZ, img_src +
i);
2797 float l_max = -INFINITY;
2798 float l_min = INFINITY;
2810 work_profile->
lut_in, work_profile->unbounded_coeffs_in,
2816 dt_linearRGB_to_XYZ(img_src +
i,
XYZ);
2820 l_max =
MAX(l_max,
Lab[0]);
2821 l_min =
MIN(l_min,
Lab[0]);
2826 levels[0] = l_min / 100.f;
2827 levels[2] = l_max / 100.f;
2828 levels[1] = (l_sum / (float)count) / 100.f;
2833 float *img_src,
const int width,
const int height,
const int ch,
2839 const float left =
levels[0];
2840 const float middle =
levels[1];
2841 const float right =
levels[2];
2845 const float delta = (right - left) / 2.0f;
2846 const float mid = left +
delta;
2847 const float tmp = (middle - mid) /
delta;
2848 const float in_inv_gamma = powf(10, tmp);
2855 work_profile->
lut_in, work_profile->unbounded_coeffs_in,
2862 dt_linearRGB_to_XYZ(img_src +
i,
XYZ);
2866 for(
int c = 0; c < 1; c++)
2868 const float L_in = img_src[
i + c] / 100.0f;
2872 img_src[
i + c] = 0.f;
2876 const float percentage = (L_in - left) / (right - left);
2877 img_src[
i + c] = 100.0f * powf(percentage, in_inv_gamma);
2884 work_profile->
lut_out, work_profile->unbounded_coeffs_out,
2892 dt_XYZ_to_linearRGB(
XYZ, img_src +
i);
2897#undef RT_WDBAR_INSET
2899#undef RETOUCH_NO_FORMS
2900#undef RETOUCH_MAX_SCALES
2901#undef RETOUCH_NO_SCALES
2903#undef RETOUCH_PREVIEW_LVL_MIN
2904#undef RETOUCH_PREVIEW_LVL_MAX
2909 const int x_from =
MAX(
MAX((roi_1->
x + 1 - padding), roi_2->
x), (roi_2->
x + dx));
2913 const int y_from =
MAX(
MAX((roi_1->
y + 1 - padding), roi_2->
y), (roi_2->
y + dy));
2914 const int y_to =
MIN(
MIN((roi_1->
y + roi_1->
height + 1 + padding), (roi_2->
y + roi_2->
height)),
2915 (roi_2->
y + roi_2->
height + dy));
2917 roi_dest->
x = x_from;
2918 roi_dest->
y = y_from;
2919 roi_dest->
width = x_to - x_from;
2920 roi_dest->
height = y_to - y_from;
2925 const struct dt_iop_roi_t *
const roi_out,
const int ch,
const int dx,
const int dy)
2927 const size_t rowsize =
sizeof(float) *
ch *
MIN(roi_out->
width, roi_in->
width);
2928 const int xoffs = roi_out->
x - roi_in->
x - dx;
2929 const int yoffs = roi_out->
y - roi_in->
y - dy;
2932 for(
int y = 0; y < y_to; y++)
2934 const size_t iindex = ((size_t)(y + yoffs) * roi_in->
width + xoffs) *
ch;
2935 const size_t oindex = (size_t)y * roi_out->
width *
ch;
2936 float *in1 = (
float *)in + iindex;
2937 float *out1 = (
float *)
out + oindex;
2939 memcpy(out1, in1, rowsize);
2945 const int dy,
const int algo)
2947 float *mask_tmp = NULL;
2949 *mask_scaled = NULL;
2953 *roi_mask_scaled = *roi_mask;
2955 roi_mask_scaled->
x = roi_mask->
x * roi_in->
scale;
2956 roi_mask_scaled->
y = roi_mask->
y * roi_in->
scale;
2964 const int x_to = roi_mask_scaled->
width + roi_mask_scaled->
x;
2965 const int y_to = roi_mask_scaled->
height + roi_mask_scaled->
y;
2970 fprintf(stderr,
"rt_build_scaled_mask: error allocating memory\n");
2976 for(
int yy = roi_mask_scaled->
y; yy < y_to; yy++)
2978 const int mask_index = ((int)(yy / roi_in->
scale)) - roi_mask->
y;
2979 if(mask_index < 0 || mask_index >= roi_mask->
height)
continue;
2981 const int mask_scaled_index = (yy - roi_mask_scaled->
y) * roi_mask_scaled->
width;
2983 const float *
m = mask + mask_index * roi_mask->
width;
2984 float *ms = mask_tmp + mask_scaled_index;
2986 for(
int xx = roi_mask_scaled->
x; xx < x_to; xx++, ms++)
2988 const int mx = ((int)(xx / roi_in->
scale)) - roi_mask->
x;
2989 if(mx < 0 || mx >= roi_mask->
width)
continue;
2996 *mask_scaled = mask_tmp;
3002 float *
const mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
3003 const float opacity)
3006 for(
int yy = 0; yy < roi_mask_scaled->
height; yy++)
3008 const int mask_index = yy * roi_mask_scaled->
width;
3009 const int src_index = 4 * mask_index;
3010 const int dest_index
3011 = 4 * (((yy + roi_mask_scaled->
y - roi_dest->
y) * roi_dest->
width) + (roi_mask_scaled->
x - roi_dest->
x));
3013 const float *s = img_src + src_index;
3014 const float *
m = mask_scaled + mask_index;
3015 float *
d = img_dest + dest_index;
3017 for(
int xx = 0; xx < roi_mask_scaled->
width; xx++)
3019 const float f =
m[xx] * opacity;
3020 const float f1 = (1.0f -
f);
3024 d[4*xx + c] =
d[4*xx + c] * f1 + s[4*xx + c] *
f;
3031 float *
const mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
3032 const float opacity)
3035 for(
int yy = 0; yy < roi_mask_scaled->
height; yy++)
3037 const int mask_index = yy * roi_mask_scaled->
width;
3038 const int dest_index
3039 = (((yy + roi_mask_scaled->
y - roi_img->
y) * roi_img->
width) + (roi_mask_scaled->
x - roi_img->
x)) *
ch;
3041 float *
d = img + dest_index;
3042 const float *
m = mask_scaled + mask_index;
3044 for(
int xx = 0; xx < roi_mask_scaled->
width; xx++,
d +=
ch,
m++)
3046 const float f = (*m) * opacity;
3047 if(
f >
d[3])
d[3] =
f;
3053 dt_iop_roi_t *
const roi_mask_scaled,
const float opacity,
const float *
const fill_color)
3056 for(
int yy = 0; yy < roi_mask_scaled->
height; yy++)
3058 const int mask_index = yy * roi_mask_scaled->
width;
3059 const int dest_index
3060 = (((yy + roi_mask_scaled->
y - roi_in->
y) * roi_in->
width) + (roi_mask_scaled->
x - roi_in->
x)) * 4;
3062 float *
d = in + dest_index;
3063 const float *
m = mask_scaled + mask_index;
3065 for(
int xx = 0; xx < roi_mask_scaled->
width; xx++)
3067 const float f =
m[xx] * opacity;
3070 d[4*xx + c] =
d[4*xx + c] * (1.0f -
f) + fill_color[c] *
f;
3076 dt_iop_roi_t *
const roi_mask_scaled,
const int dx,
const int dy,
const float opacity)
3082 fprintf(stderr,
"retouch_clone: error allocating memory for cloning\n");
3098 dt_iop_roi_t *
const roi_mask_scaled,
const float opacity,
const int blur_type,
3099 const float blur_radius,
const int use_sse)
3101 if(fabsf(blur_radius) <= 0.1f)
return 0;
3103 const float sigma = blur_radius * roi_in->
scale;
3105 float *img_dest = NULL;
3111 fprintf(stderr,
"retouch_blur: error allocating memory for blurring\n");
3120 float Labmax[] = { INFINITY, INFINITY, INFINITY, INFINITY };
3121 float Labmin[] = { -INFINITY, -INFINITY, -INFINITY, -INFINITY };
3135 const float detail = -1.0f;
3172 dt_iop_roi_t *
const roi_mask_scaled,
const int dx,
const int dy,
const float opacity,
const int max_iter)
3174 float *img_src = NULL;
3175 float *img_dest = NULL;
3183 fprintf(stderr,
"retouch_heal: error allocating memory for healing\n");
3193 dt_heal(img_src, img_dest, mask_scaled, roi_mask_scaled->
width, roi_mask_scaled->
height, 4, max_iter);
3216 if(scale > wt_p->
scales + 1)
return 0;
3228 scale =
p->num_scales + 1;
3237 for(
const GList *forms = grp->
points; forms; forms = g_list_next(forms))
3242 fprintf(stderr,
"rt_process_forms: invalid form\n");
3245 const int formid = grpt->
formid;
3246 const float form_opacity = grpt->
opacity;
3249 fprintf(stderr,
"rt_process_forms: form is null\n");
3256 fprintf(stderr,
"rt_process_forms: missing form=%i from array\n", formid);
3261 if(
p->rt_forms[index].scale != scale)
3270 fprintf(stderr,
"rt_process_forms: missing form=%i from masks\n", formid);
3285 &roi_mask.
x, &roi_mask.
y);
3288 fprintf(stderr,
"rt_process_forms: error retrieving mask\n");
3294 float dx = 0.f, dy = 0.f;
3299 p->rt_forms[index].distort_mode))
3307 float *mask_scaled = NULL;
3309 if(
rt_build_scaled_mask(mask, &roi_mask, &mask_scaled, &roi_mask_scaled, roi_layer, dx, dy, algo) != 0)
3328 && ((roi_mask_scaled.
width > 2) && (roi_mask_scaled.
height > 2)))
3332 if(
_retouch_clone(layer, roi_layer, mask_scaled, &roi_mask_scaled, dx, dy, form_opacity) != 0)
3340 if(
_retouch_heal(layer, roi_layer, mask_scaled, &roi_mask_scaled, dx, dy, form_opacity,
p->max_heal_iter) != 0)
3348 if(
_retouch_blur(self, pipe, layer, roi_layer, mask_scaled, &roi_mask_scaled, form_opacity,
3349 p->rt_forms[index].blur_type,
p->rt_forms[index].blur_radius, wt_p->
use_sse) != 0)
3362 fill_color[0] = fill_color[1] = fill_color[2] =
p->rt_forms[index].fill_brightness;
3366 fill_color[0] =
p->rt_forms[index].fill_color[0] +
p->rt_forms[index].fill_brightness;
3367 fill_color[1] =
p->rt_forms[index].fill_color[1] +
p->rt_forms[index].fill_brightness;
3368 fill_color[2] =
p->rt_forms[index].fill_color[2] +
p->rt_forms[index].fill_brightness;
3370 fill_color[3] = 0.0f;
3372 _retouch_fill(layer, roi_layer, mask_scaled, &roi_mask_scaled, form_opacity, fill_color);
3375 fprintf(stderr,
"rt_process_forms: unknown algorithm %i\n", algo);
3397 float *in_retouch = NULL;
3407 const int display_wavelet_scale = (
g && gui_active) ?
g->display_wavelet_scale : 0;
3421 usr_data.
self = self;
3422 usr_data.
pipe = pipe;
3423 usr_data.
piece = piece;
3424 usr_data.
roi = *roi_rt;
3427 && (pipe == self->
dev->
pipe));
3433 p->merge_from_scale, &usr_data,
3434 roi_in->
scale, use_sse);
3446 for(
size_t j = 0; j < (size_t)roi_rt->
width * roi_rt->
height * 4; j += 4) in_retouch[j + 3] = 0.f;
3459 if(dwt_p->
scales > max_scales)
3461 dt_control_log(_(
"max scale is %i for this image size"), max_scales);
3483 g->preview_auto_levels = -1;
3491 for(
int i = 0;
i < 3;
i++)
g->preview_levels[
i] =
levels[
i];
3494 g->preview_auto_levels = 2;
3508 dt_iop_alpha_copy(ivoid, in_retouch, roi_rt->
width, roi_rt->
height);
3529 const float *
const in,
float *
const out,
const dt_iop_roi_t *
const roi_in,
3539 const int devid, cl_mem dev_img,
const int width,
const int height,
3542 cl_int err = CL_SUCCESS;
3546 float *src_buffer = NULL;
3551 fprintf(stderr,
"dt_heal_cl: error allocating memory for healing\n");
3558 if(err != CL_SUCCESS)
3567 if(err != CL_SUCCESS)
3579 const int devid, cl_mem dev_img,
const int width,
const int height,
3582 cl_int err = CL_SUCCESS;
3586 float *src_buffer = NULL;
3591 fprintf(stderr,
"dt_heal_cl: error allocating memory for healing\n");
3598 if(err != CL_SUCCESS)
3607 if(err != CL_SUCCESS)
3619 cl_mem dev_out,
const struct dt_iop_roi_t *
const roi_out,
const int dx,
3620 const int dy,
const int kernel)
3622 cl_int err = CL_SUCCESS;
3624 const int xoffs = roi_out->
x - roi_in->
x - dx;
3625 const int yoffs = roi_out->
y - roi_in->
y - dy;
3627 cl_mem dev_roi_in = NULL;
3628 cl_mem dev_roi_out = NULL;
3630 const size_t sizes[]
3637 fprintf(stderr,
"rt_copy_in_to_out_cl error 1\n");
3638 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3649 if(err != CL_SUCCESS)
3651 fprintf(stderr,
"rt_copy_in_to_out_cl error 2\n");
3663 float **mask_scaled, cl_mem *p_dev_mask_scaled,
3665 const int dy,
const int algo)
3667 cl_int err = CL_SUCCESS;
3675 const cl_mem dev_mask_scaled
3679 fprintf(stderr,
"rt_build_scaled_mask_cl error 2\n");
3680 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3685 sizeof(
float) * roi_mask_scaled->
width * roi_mask_scaled->
height, CL_TRUE);
3686 if(err != CL_SUCCESS)
3688 fprintf(stderr,
"rt_build_scaled_mask_cl error 4\n");
3692 *p_dev_mask_scaled = dev_mask_scaled;
3695 if(err != CL_SUCCESS) fprintf(stderr,
"rt_build_scaled_mask_cl error\n");
3704 cl_int err = CL_SUCCESS;
3708 const cl_mem dev_roi_dest =
3711 const cl_mem dev_roi_mask_scaled
3716 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3727 if(err != CL_SUCCESS)
goto cleanup;
3737 cl_mem dev_mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
3740 cl_int err = CL_SUCCESS;
3747 const cl_mem dev_roi_mask_scaled
3751 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3761 if(err != CL_SUCCESS)
goto cleanup;
3772 cl_mem dev_mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
const int dx,
3775 cl_int err = CL_SUCCESS;
3781 sizeof(
float) *
ch * roi_mask_scaled->
width * roi_mask_scaled->
height);
3784 fprintf(stderr,
"retouch_clone_cl error 2\n");
3785 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3792 if(err != CL_SUCCESS)
3794 fprintf(stderr,
"retouch_clone_cl error 4\n");
3799 err =
rt_copy_image_masked_cl(devid, dev_src, dev_layer, roi_layer, dev_mask_scaled, roi_mask_scaled, opacity,
3801 if(err != CL_SUCCESS)
3803 fprintf(stderr,
"retouch_clone_cl error 5\n");
3814 cl_mem dev_mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
const float opacity,
3817 cl_int err = CL_SUCCESS;
3824 const cl_mem dev_roi_mask_scaled
3828 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3841 if(err != CL_SUCCESS)
goto cleanup;
3852 cl_mem dev_mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
const float opacity,
3855 cl_int err = CL_SUCCESS;
3857 if(fabsf(blur_radius) <= 0.1f)
return err;
3859 const float sigma = blur_radius * roi_layer->
scale;
3862 const cl_mem dev_dest =
3866 fprintf(stderr,
"retouch_blur_cl error 2\n");
3867 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3880 if(err != CL_SUCCESS)
goto cleanup;
3885 if(err != CL_SUCCESS)
3887 fprintf(stderr,
"retouch_blur_cl error 4\n");
3893 float Labmax[] = { INFINITY, INFINITY, INFINITY, INFINITY };
3894 float Labmin[] = { -INFINITY, -INFINITY, -INFINITY, -INFINITY };
3902 if(err != CL_SUCCESS)
goto cleanup;
3909 const float detail = -1.0f;
3924 err =
rt_copy_image_masked_cl(devid, dev_dest, dev_layer, roi_layer, dev_mask_scaled, roi_mask_scaled, opacity,
3926 if(err != CL_SUCCESS)
3928 fprintf(stderr,
"retouch_blur_cl error 5\n");
3941 if(err != CL_SUCCESS)
goto cleanup;
3951 cl_mem dev_mask_scaled,
dt_iop_roi_t *
const roi_mask_scaled,
const int dx,
3954 cl_int err = CL_SUCCESS;
3958 cl_mem dev_dest = NULL;
3960 sizeof(
float) *
ch * roi_mask_scaled->
width * roi_mask_scaled->
height);
3963 fprintf(stderr,
"retouch_heal_cl: error allocating memory for healing\n");
3964 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3969 sizeof(
float) *
ch * roi_mask_scaled->
width * roi_mask_scaled->
height);
3972 fprintf(stderr,
"retouch_heal_cl: error allocating memory for healing\n");
3973 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
3979 if(err != CL_SUCCESS)
3981 fprintf(stderr,
"retouch_heal_cl error 4\n");
3987 if(err != CL_SUCCESS)
3989 fprintf(stderr,
"retouch_heal_cl error 4\n");
3997 err =
dt_heal_cl(hp, dev_src, dev_dest, mask_scaled, roi_mask_scaled->
width, roi_mask_scaled->
height, max_iter);
4003 if(err != CL_SUCCESS)
goto cleanup;
4007 err =
rt_copy_image_masked_cl(devid, dev_dest, dev_layer, roi_layer, dev_mask_scaled, roi_mask_scaled, opacity,
4009 if(err != CL_SUCCESS)
4011 fprintf(stderr,
"retouch_heal_cl error 6\n");
4024 cl_int err = CL_SUCCESS;
4037 if(scale > wt_p->
scales + 1)
return err;
4042 const int devid = pipe->
devid;
4051 scale =
p->num_scales + 1;
4060 for(
const GList *forms = grp->
points; forms && err == CL_SUCCESS; forms = g_list_next(forms))
4065 fprintf(stderr,
"rt_process_forms: invalid form\n");
4068 const int formid = grpt->
formid;
4069 const float form_opacity = grpt->
opacity;
4072 fprintf(stderr,
"rt_process_forms: form is null\n");
4079 fprintf(stderr,
"rt_process_forms: missing form=%i from array\n", formid);
4084 if(
p->rt_forms[index].scale != scale)
4093 fprintf(stderr,
"rt_process_forms: missing form=%i from masks\n", formid);
4108 &roi_mask.
x, &roi_mask.
y);
4111 fprintf(stderr,
"rt_process_forms: error retrieving mask\n");
4115 float dx = 0.f, dy = 0.f;
4122 p->rt_forms[index].distort_mode))
4130 cl_mem dev_mask_scaled = NULL;
4131 float *mask_scaled = NULL;
4135 roi_layer, dx, dy, algo);
4154 dev_mask_scaled = NULL;
4158 if((err == CL_SUCCESS)
4160 && ((roi_mask_scaled.
width > 2) && (roi_mask_scaled.
height > 2)))
4164 err =
_retouch_clone_cl(devid, dev_layer, roi_layer, dev_mask_scaled, &roi_mask_scaled, dx, dy,
4169 err =
_retouch_heal_cl(devid, dev_layer, roi_layer, mask_scaled, dev_mask_scaled, &roi_mask_scaled, dx,
4170 dy, form_opacity, gd,
p->max_heal_iter);
4174 err =
_retouch_blur_cl(devid, dev_layer, roi_layer, dev_mask_scaled, &roi_mask_scaled, form_opacity,
4175 p->rt_forms[index].blur_type,
p->rt_forms[index].blur_radius, gd);
4184 fill_color[0] = fill_color[1] = fill_color[2] =
p->rt_forms[index].fill_brightness;
4188 fill_color[0] =
p->rt_forms[index].fill_color[0] +
p->rt_forms[index].fill_brightness;
4189 fill_color[1] =
p->rt_forms[index].fill_color[1] +
p->rt_forms[index].fill_brightness;
4190 fill_color[2] =
p->rt_forms[index].fill_color[2] +
p->rt_forms[index].fill_brightness;
4193 err =
_retouch_fill_cl(devid, dev_layer, roi_layer, dev_mask_scaled, &roi_mask_scaled, form_opacity,
4197 fprintf(stderr,
"rt_process_forms: unknown algorithm %i\n", algo);
4221 cl_int err = CL_SUCCESS;
4222 const int devid = pipe->
devid;
4232 const int display_wavelet_scale = (
g && gui_active) ?
g->display_wavelet_scale : 0;
4239 dt_print(
DT_DEBUG_OPENCL,
"[retouch process_cl] error allocating memory for wavelet decompose on device %d\n", devid);
4240 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
4246 size_t origin[] = { 0, 0, 0 };
4247 size_t region[] = { roi_rt->
width, roi_rt->
height, 1 };
4249 if(err != CL_SUCCESS)
goto cleanup;
4253 usr_data.
self = self;
4254 usr_data.
pipe = pipe;
4255 usr_data.
piece = piece;
4256 usr_data.
roi = *roi_rt;
4259 && (pipe == self->
dev->
pipe));
4264 (!display_wavelet_scale
4266 p->merge_from_scale, &usr_data,
4271 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
4286 if(err != CL_SUCCESS)
goto cleanup;
4299 if(dwt_p->
scales > max_scales)
4301 dt_control_log(_(
"max scale is %i for this image size"), max_scales);
4310 if(err != CL_SUCCESS)
goto cleanup;
4320 g->preview_auto_levels = -1;
4326 if(err != CL_SUCCESS)
goto cleanup;
4330 for(
int i = 0;
i < 3;
i++)
g->preview_levels[
i] =
levels[
i];
4333 g->preview_auto_levels = 2;
4342 if(err != CL_SUCCESS)
goto cleanup;
4356 if(err != CL_SUCCESS)
goto cleanup;
4370 return (err == CL_SUCCESS) ?
TRUE :
FALSE;
4381 const int formid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget),
"formid"));
4382 const int algo = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget),
"algo"));
4384 if(index < 0)
return;
4386 if(
p->rt_forms[index].algorithm == algo)
return;
4391 p->rt_forms[index].algorithm = algo;
4398 masks_type &= ~DT_MASKS_NON_CLONE;
4402 masks_type &= ~DT_MASKS_CLONE;
4405 form->
type = masks_type;
4419 fprintf(stderr,
"populate_masks_context_menu: missing form=%i from array\n", formid);
4425 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), sub_menu);
4436 for(
size_t i = 0;
i < G_N_ELEMENTS(algo_entries);
i++)
4438 const gboolean is_selected = (
p->rt_forms[index].algorithm == algo_entries[
i].algo);
4439 const char *
const label = _(algo_entries[
i].
name);
4442 is_selected,
FALSE);
4444 g_object_set_data(G_OBJECT(algo_item),
"formid", GINT_TO_POINTER(formid));
4445 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 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...
#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
@ DT_DEV_PIXELPIPE_DISPLAY_PASSTHRU
@ 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)
#define dt_pthread_rwlock_unlock
#define dt_pthread_rwlock_rdlock
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_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)
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 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)
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 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 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