90#define RETOUCH_NO_FORMS 300
91#define RETOUCH_MAX_SCALES 15
92#define RETOUCH_NO_SCALES (RETOUCH_MAX_SCALES + 2)
94#define RETOUCH_PREVIEW_LVL_MIN -3.0f
95#define RETOUCH_PREVIEW_LVL_MAX 3.0f
254 return _(
"re_touch");
259 return _(
"split-frequency|healing|cloning|stamp");
267 _(
"linear, RGB, scene-referred"),
268 _(
"geometric and frequential, RGB"),
269 _(
"linear, RGB, scene-referred"));
292 const int new_version)
294 if(old_version == 1 && new_version == 4)
296 typedef struct dt_iop_retouch_form_data_v1_t
307 float fill_brightness;
308 } dt_iop_retouch_form_data_v1_t;
309 typedef struct dt_iop_retouch_params_v1_t
317 int merge_from_scale;
319 float preview_levels[3];
329 float fill_brightness;
330 } dt_iop_retouch_params_v1_t;
332 dt_iop_retouch_params_v1_t *
o = (dt_iop_retouch_params_v1_t *)old_params;
339 dt_iop_retouch_form_data_v1_t of =
o->rt_forms[
i];
340 n->rt_forms[
i].algorithm = of.algorithm;
341 n->rt_forms[
i].blur_radius = of.blur_radius;
342 n->rt_forms[
i].blur_type = of.blur_type;
343 n->rt_forms[
i].distort_mode = 1;
344 n->rt_forms[
i].fill_brightness = of.fill_brightness;
345 n->rt_forms[
i].fill_color[0] = of.fill_color[0];
346 n->rt_forms[
i].fill_color[1] = of.fill_color[1];
347 n->rt_forms[
i].fill_color[2] = of.fill_color[2];
348 n->rt_forms[
i].fill_mode = of.fill_mode;
349 n->rt_forms[
i].formid = of.formid;
350 n->rt_forms[
i].scale = of.scale;
352 n->algorithm =
o->algorithm;
353 n->blur_radius =
o->blur_radius;
354 n->blur_type =
o->blur_type;
355 n->curr_scale =
o->curr_scale;
356 n->fill_brightness =
o->fill_brightness;
357 n->fill_color[0] =
o->fill_color[0];
358 n->fill_color[1] =
o->fill_color[1];
359 n->fill_color[2] =
o->fill_color[2];
360 n->fill_mode =
o->fill_mode;
361 n->merge_from_scale =
o->merge_from_scale;
362 n->num_scales =
o->num_scales;
363 n->preview_levels[0] =
o->preview_levels[0];
364 n->preview_levels[1] =
o->preview_levels[1];
365 n->preview_levels[2] =
o->preview_levels[2];
367 n->max_heal_iter = 1000;
372 if(old_version == 2 && new_version == 4)
374 typedef struct dt_iop_retouch_params_v2_t
382 int merge_from_scale;
384 float preview_levels[3];
391 float fill_brightness;
392 } dt_iop_retouch_params_v2_t;
394 dt_iop_retouch_params_v2_t *
o = (dt_iop_retouch_params_v2_t *)old_params;
400 memcpy(
n,
o,
sizeof(dt_iop_retouch_params_v2_t));
402 n->max_heal_iter = 1000;
407 if(old_version == 3 && new_version == 4)
415 memcpy(
n, old_params, v3_size);
432 if(
p->rt_forms[
i].formid == formid) index =
i;
449 return selected_group_entry ? selected_group_entry->
formid : 0;
462 for(
const GList *forms = grp->
points; forms; forms = g_list_next(forms))
465 if(grpt->
formid == formid)
467 form_point_group = grpt;
473 return form_point_group;
481 if(grpt) opacity = grpt->
opacity;
489 = (GdkRGBA){.red =
p->fill_color[0], .green =
p->fill_color[1], .blue =
p->fill_color[2], .alpha = 1.0 };
490 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(
g->colorpick), &c);
501 gtk_widget_hide(GTK_WIDGET(
g->vbox_blur));
502 gtk_widget_hide(GTK_WIDGET(
g->vbox_fill));
505 gtk_widget_show(GTK_WIDGET(
g->vbox_blur));
506 gtk_widget_hide(GTK_WIDGET(
g->vbox_fill));
509 gtk_widget_hide(GTK_WIDGET(
g->vbox_blur));
510 gtk_widget_show(GTK_WIDGET(
g->vbox_fill));
512 gtk_widget_show(GTK_WIDGET(
g->hbox_color_pick));
514 gtk_widget_hide(GTK_WIDGET(
g->hbox_color_pick));
518 gtk_widget_hide(GTK_WIDGET(
g->vbox_blur));
519 gtk_widget_hide(GTK_WIDGET(
g->vbox_fill));
523 if(
g->display_wavelet_scale)
524 gtk_widget_show(GTK_WIDGET(
g->vbox_preview_scale));
526 gtk_widget_hide(GTK_WIDGET(
g->vbox_preview_scale));
530 if(selected_formid > 0)
533 gtk_widget_show(GTK_WIDGET(
g->sl_mask_opacity));
535 gtk_widget_hide(GTK_WIDGET(
g->sl_mask_opacity));
545 gtk_label_set_text(
g->label_form_selected, form->
name);
547 gtk_label_set_text(
g->label_form_selected, _(
"none"));
563 gboolean selection_changed =
FALSE;
579 selection_changed =
TRUE;
593 selection_changed =
TRUE;
605 selection_changed =
TRUE;
614 gtk_widget_show(GTK_WIDGET(
g->sl_mask_opacity));
616 gtk_widget_hide(GTK_WIDGET(
g->sl_mask_opacity));
635 CLAMP(opacity, 0.05f, 1.0f), &member);
656 if(source_scale != dest_scale && source_scale >= 0 && dest_scale >= 0)
660 if(
p->rt_forms[
i].scale == source_scale)
p->rt_forms[
i].scale = dest_scale;
687 const int scale =
p->curr_scale;
693 if(
p->rt_forms[
i].formid != 0 &&
p->rt_forms[
i].scale == scale) count++;
697 gtk_widget_set_sensitive(
g->bt_copy_scale, count > 0);
705 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
719 if(
p->rt_forms[
i].scale == scale)
721 const int formid =
p->rt_forms[
i].formid;
737 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
758 int new_form_index = 0;
766 const int formid = grpt->
formid;
774 forms_d[new_form_index] =
p->rt_forms[form_index];
782 forms_d[new_form_index].
formid = formid;
783 forms_d[new_form_index].
scale =
p->curr_scale;
784 forms_d[new_form_index].
algorithm =
p->algorithm;
787 switch(forms_d[new_form_index].algorithm)
790 forms_d[new_form_index].
blur_type =
p->blur_type;
794 forms_d[new_form_index].
fill_mode =
p->fill_mode;
795 forms_d[new_form_index].
fill_color[0] =
p->fill_color[0];
796 forms_d[new_form_index].
fill_color[1] =
p->fill_color[1];
797 forms_d[new_form_index].
fill_color[2] =
p->fill_color[2];
810 p->rt_forms[
i] = forms_d[
i];
837 gchar *str = g_strdup_printf(
"%d", nb);
838 gtk_label_set_text(
g->label_form, str);
846 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
851 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
857 size_t points_count,
float *
new)
861 for(
size_t i = 0;
i < points_count * 2;
i += 2)
863 new[
i] = points[
i] * scalex;
864 new[
i + 1] = points[
i + 1] * scaley;
904 const float *target,
const float *source,
float *dx,
float *dy,
905 const int distort_mode)
910 if(distort_mode == 1)
927 if(distort_mode == 1)
929 *dx = points[0] - points[2];
930 *dy = points[1] - points[3];
934 *dx = (points[0] - points[2]) * roi->
scale;
935 *dy = (points[1] - points[3]) * roi->
scale;
944 const int distort_mode)
981static inline __attribute__((always_inline))
void rt_clamp_minmax(
float levels_old[3],
float levels_new[3])
984 if((levels_old[0] != levels_new[0] || levels_old[2] != levels_new[2]) && levels_old[1] == levels_new[1])
987 if(levels_old[2] != levels_old[0])
993 const float percentage = (levels_old[1] - levels_old[0]) / (levels_old[2] - levels_old[0]);
994 levels_new[1] = left + (right - left) * percentage;
995 levels_new[0] = left;
996 levels_new[2] = right;
1001 if(levels_new[0] == 0.f && levels_new[1] == 0.f && levels_new[2] == 0.f)
1003 levels_new[0] = -1.5f;
1004 levels_new[1] = 0.f;
1005 levels_new[2] = 1.5f;
1009 if(levels_new[2] < levels_new[0] + 0.05f * 2.f) levels_new[2] = levels_new[0] + 0.05f * 2.f;
1010 if(levels_new[1] < levels_new[0] + 0.05f) levels_new[1] = levels_new[0] + 0.05f;
1011 if(levels_new[1] > levels_new[2] - 0.05f) levels_new[1] = levels_new[2] - 0.05f;
1018 const float percentage = (levels_new[1] - levels_new[0]) / (levels_new[2] - levels_new[0]);
1019 levels_new[1] = left + (right - left) * percentage;
1020 levels_new[0] = left;
1021 levels_new[2] = right;
1027 int being_added = 0;
1055 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->
gui->
off),
TRUE);
1069 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
1070 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_showmask),
FALSE);
1071 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_suppress),
FALSE);
1072 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->colorpicker),
FALSE);
1099 = (GdkRGBA){.red =
p->fill_color[0], .green =
p->fill_color[1], .blue =
p->fill_color[2], .alpha = 1.0 };
1100 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget), &c);
1101 p->fill_color[0] = c.red;
1102 p->fill_color[1] = c.green;
1103 p->fill_color[2] = c.blue;
1110 p->rt_forms[index].fill_color[0] =
p->fill_color[0];
1111 p->rt_forms[index].fill_color[1] =
p->fill_color[1];
1112 p->rt_forms[index].fill_color[2] =
p->fill_color[2];
1120#define RT_WDBAR_INSET 0.2f
1121#define lw DT_PIXEL_APPLY_DPI(1.0f)
1127 snprintf(text,
sizeof(text),
"%i",
p->curr_scale);
1128 gtk_label_set_text(
g->lbl_curr_scale, text);
1130 snprintf(text,
sizeof(text),
"%i",
p->num_scales);
1131 gtk_label_set_text(
g->lbl_num_scales, text);
1133 snprintf(text,
sizeof(text),
"%i",
p->merge_from_scale);
1134 gtk_label_set_text(
g->lbl_merge_from_scale, text);
1145 if(
p->num_scales == num_scales)
return;
1147 p->num_scales = num_scales;
1149 if(
p->num_scales <
p->merge_from_scale)
p->merge_from_scale =
p->num_scales;
1164 if(
p->curr_scale == curr_scale)
return;
1166 p->curr_scale = curr_scale;
1176 &&
g->preview_auto_levels == 0 &&
p->curr_scale > 0 &&
p->curr_scale <=
p->num_scales)
1178 g->preview_auto_levels = 1;
1179 g->displayed_wavelet_scale = 1;
1195 const int merge_from_scale = CLAMP(_merge_from_scale, 0,
p->num_scales);
1196 if(
p->merge_from_scale == merge_from_scale)
return;
1198 p->merge_from_scale = merge_from_scale;
1209 g->wdbar_mouse_x =
g->wdbar_mouse_y = -1;
1211 g->lower_cursor =
g->upper_cursor =
FALSE;
1212 g->lower_margin =
g->upper_margin =
FALSE;
1214 gtk_widget_queue_draw(
g->wd_bar);
1225 GtkAllocation allocation;
1226 gtk_widget_get_allocation(widget, &allocation);
1228 const float box_w = (allocation.width - 2.0f * inset) / (
float)
RETOUCH_NO_SCALES;
1230 if(event->button == 1)
1239 else if(
g->upper_margin)
1246 else if (
g->curr_scale >= 0)
1250 gtk_widget_queue_draw(
g->wd_bar);
1258 if(event->button == 1)
g->is_dragging = 0;
1260 gtk_widget_queue_draw(
g->wd_bar);
1278 else if(
g->upper_margin)
1280 else if (
g->curr_scale >= 0)
1284 gtk_widget_queue_draw(
g->wd_bar);
1293 GtkAllocation allocation;
1294 gtk_widget_get_allocation(widget, &allocation);
1296 const float box_w = (allocation.width - 2.0f * inset) / (
float)
RETOUCH_NO_SCALES;
1297 const float sh = 3.0f *
lw + inset;
1301 g->wdbar_mouse_x = CLAMP(event->x - inset, 0, allocation.width - 2.0f * inset - 1.0f);
1302 g->wdbar_mouse_y =
event->y;
1304 g->curr_scale =
g->wdbar_mouse_x / box_w;
1305 g->lower_cursor =
g->upper_cursor =
FALSE;
1306 g->lower_margin =
g->upper_margin =
FALSE;
1307 if(
g->wdbar_mouse_y <= sh)
1309 g->upper_margin =
TRUE;
1310 float middle = box_w * (0.5f + (float)
p->merge_from_scale);
1311 g->upper_cursor = (
g->wdbar_mouse_x >= (middle - inset)) && (
g->wdbar_mouse_x <= (middle + inset));
1312 if (!(
g->is_dragging))
g->curr_scale = -1;
1314 else if (
g->wdbar_mouse_y >= allocation.height - sh)
1316 g->lower_margin =
TRUE;
1317 float middle = box_w * (0.5f + (float)
p->num_scales);
1318 g->lower_cursor = (
g->wdbar_mouse_x >= (middle - inset)) && (
g->wdbar_mouse_x <= (middle + inset));
1319 if (!(
g->is_dragging))
g->curr_scale = -1;
1328 gtk_widget_queue_draw(
g->wd_bar);
1337 has_shapes = (
p->rt_forms[
i].formid != 0 &&
p->rt_forms[
i].scale == scale);
1348 GdkRGBA border = {0.066, 0.066, 0.066, 1};
1349 GdkRGBA original = {.1, .1, .1, 1};
1350 GdkRGBA inactive = {.15, .15, .15, 1};
1351 GdkRGBA active = {.35, .35, .35, 1};
1352 GdkRGBA merge_from = {.5, .5, .5, 1};
1353 GdkRGBA residual = {.8, .8, .8, 1};
1354 GdkRGBA shapes = {.75, .5, .0, 1};
1358 const int first_scale_visible = (
g->first_scale_visible > 0) ?
g->first_scale_visible :
RETOUCH_MAX_SCALES;
1360 GtkAllocation allocation;
1361 gtk_widget_get_allocation(widget, &allocation);
1364 cairo_t *cr = cairo_create(cst);
1367 gdk_cairo_set_source_rgba(cr, &inactive);
1373 const int mk = 2 * inset;
1374 const float sh = 3.0f *
lw + inset;
1375 const float box_w = (allocation.width - 2.0f * inset) / (
float)
RETOUCH_NO_SCALES;
1376 const float box_h = allocation.height - 2.0f * sh;
1379 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
1385 else if(
i ==
p->num_scales + 1)
1387 else if(
i >=
p->merge_from_scale && i <= p->num_scales &&
p->merge_from_scale > 0)
1389 else if(i <= p->num_scales)
1394 gdk_cairo_set_source_rgba(cr, &
color);
1395 cairo_rectangle(cr, box_w *
i + inset, sh, box_w, box_h);
1399 if(
i >= first_scale_visible && i <= p->num_scales)
1401 gdk_cairo_set_source_rgba(cr, &merge_from);
1402 cairo_rectangle(cr, box_w *
i + inset,
lw, box_w, 2.0f *
lw);
1409 cairo_set_line_width(cr,
lw);
1410 gdk_cairo_set_source_rgba(cr, &shapes);
1411 cairo_rectangle(cr, box_w *
i + inset +
lw / 2.0f, allocation.height - sh, box_w -
lw, 2.0f *
lw);
1416 cairo_set_line_width(cr,
lw);
1417 gdk_cairo_set_source_rgba(cr, &border);
1418 cairo_rectangle(cr, box_w *
i + inset, sh, box_w, box_h);
1422 cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT);
1426 if(
p->curr_scale >=
p->merge_from_scale &&
p->curr_scale <=
p->num_scales &&
p->merge_from_scale > 0)
1433 cairo_set_line_width(cr,
lw);
1434 gdk_cairo_set_source_rgba(cr, &
color);
1435 middle = box_w * (0.5f + (float)
p->curr_scale);
1436 cairo_arc(cr, middle + inset, 0.5f * box_h + sh, 0.5f * inset, 0, 2.0f *
M_PI);
1442 if(
g->curr_scale >= 0)
1444 cairo_set_line_width(cr,
lw);
1445 if(
g->curr_scale ==
p->num_scales + 1)
color = inactive;
1446 else color = residual;
1447 gdk_cairo_set_source_rgba(cr, &
color);
1448 cairo_rectangle(cr, box_w *
g->curr_scale + inset +
lw, sh +
lw, box_w - 2.0f *
lw, box_h - 2.0f *
lw);
1455 middle = box_w * (0.5f + (float)
p->num_scales);
1458 cairo_set_source_rgb(cr, 0.67, 0.67, 0.67);
1463 cairo_set_source_rgb(cr, 0.54, 0.54, 0.54);
1468 middle = box_w * (0.5f + (float)
p->merge_from_scale);
1471 cairo_set_source_rgb(cr, 0.67, 0.67, 0.67);
1476 cairo_set_source_rgb(cr, 0.54, 0.54, 0.54);
1482 cairo_set_source_surface(crf, cst, 0, 0);
1484 cairo_surface_destroy(cst);
1517 for (
int i = 0;
i < 3;
i++)
p->preview_levels[
i] = dlevels[
i];
1546 p->rt_forms[index].fill_color[0] =
p->fill_color[0];
1547 p->rt_forms[index].fill_color[1] =
p->fill_color[1];
1548 p->rt_forms[index].fill_color[2] =
p->fill_color[2];
1563 int scale_copied = 0;
1564 const int active = !gtk_toggle_button_get_active(togglebutton);
1568 if(togglebutton == (GtkToggleButton *)
g->bt_copy_scale)
1570 g->copied_scale = (active) ?
p->curr_scale : -1;
1572 else if(togglebutton == (GtkToggleButton *)
g->bt_paste_scale)
1578 g->copied_scale = -1;
1581 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_copy_scale),
g->copied_scale >= 0);
1582 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_paste_scale),
g->copied_scale >= 0);
1583 gtk_widget_set_sensitive(
g->bt_paste_scale,
g->copied_scale >= 0);
1596 return module->request_mask_display && !g->mask_display && !g->display_wavelet_scale;
1605 return g->mask_display ||
g->display_wavelet_scale ||
g->suppress_mask;
1617 const int variant = (
g->mask_display ? 1 : 0) | (
g->display_wavelet_scale ? 2 : 0) | (
g->suppress_mask ? 4 : 0);
1639 module->request_mask_display = display_request;
1652 dt_control_log(_(
"cannot display scales when the blending mask is displayed"));
1655 gtk_toggle_button_set_active(togglebutton,
FALSE);
1660 if(self->
gui->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->
gui->
off), 1);
1663 g->display_wavelet_scale = !gtk_toggle_button_get_active(togglebutton);
1675 &&
g->preview_auto_levels == 0 &&
p->curr_scale > 0 &&
p->curr_scale <=
p->num_scales)
1677 g->preview_auto_levels = 1;
1678 g->displayed_wavelet_scale = 1;
1684 gtk_toggle_button_set_active(togglebutton,
g->display_wavelet_scale);
1697 if(
g->preview_auto_levels == 2)
1699 g->preview_auto_levels = -1;
1703 for(
int i = 0;
i < 3;
i++)
p->preview_levels[
i] =
g->preview_levels[
i];
1711 for(
int i = 0;
i < 3;
i++) dlevels[
i] =
p->preview_levels[
i];
1717 g->preview_auto_levels = 0;
1722 gtk_widget_queue_draw(GTK_WIDGET(
g->wd_bar));
1731 if(self->
gui->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->
gui->
off), 1);
1735 if(
g->preview_auto_levels == 0)
1737 g->preview_auto_levels = 1;
1801 if(event->button == 1)
1833 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
1865 if(togglebutton == (GtkToggleButton *)
g->bt_blur)
1867 else if(togglebutton == (GtkToggleButton *)
g->bt_clone)
1869 else if(togglebutton == (GtkToggleButton *)
g->bt_heal)
1871 else if(togglebutton == (GtkToggleButton *)
g->bt_fill)
1875 gboolean accept =
TRUE;
1884 if(accept)
p->algorithm = new_algo;
1901 if(
p->algorithm !=
p->rt_forms[index].algorithm)
1903 p->rt_forms[index].algorithm =
p->algorithm;
1912 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_polygon)))
1914 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_circle)))
1916 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_ellipse)))
1918 else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_brush)))
1963 dt_control_log(_(
"cannot display masks when the blending mask is displayed"));
1965 gtk_toggle_button_set_active(togglebutton,
FALSE);
1969 g->mask_display = !gtk_toggle_button_get_active(togglebutton);
1973 if(module->
gui->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->
gui->
off), 1);
1978 gtk_toggle_button_set_active(togglebutton,
g->mask_display);
1987 g->suppress_mask = !gtk_toggle_button_get_active(togglebutton);
1993 if(module->
gui->
off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->
gui->
off), 1);
1998 gtk_toggle_button_set_active(togglebutton,
g->suppress_mask);
2007 if(w ==
g->cmb_fill_mode)
2020 p->rt_forms[index].blur_type =
p->blur_type;
2021 p->rt_forms[index].blur_radius =
p->blur_radius;
2025 p->rt_forms[index].fill_mode =
p->fill_mode;
2026 p->rt_forms[index].fill_brightness =
p->fill_brightness;
2053 d->preview_levels[1] = 0.f;
2060 const int program = 21;
2114 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
2126 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
2132 if(
g->display_wavelet_scale ||
g->mask_display ||
g->suppress_mask)
2159 const float require = 2.0f;
2160 const float require_cl = 1.0f
2161 + ((
p->num_scales > 0) ? 4.0f : 2.0f);
2165 tiling->factor = 2.0f + require;
2166 tiling->factor_cl = 2.0f + require_cl;
2168 tiling->maxbuf_cl = 1.0f;
2201 gchar *str = g_strdup_printf(
"%d", nb);
2202 gtk_label_set_text(
g->label_form, str);
2227 gtk_widget_queue_draw(GTK_WIDGET(
g->wd_bar));
2237 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_display_wavelet_scale),
g->display_wavelet_scale);
2238 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_copy_scale),
g->copied_scale >= 0);
2239 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_paste_scale),
g->copied_scale >= 0);
2240 gtk_widget_set_sensitive(
g->bt_paste_scale,
g->copied_scale >= 0);
2251 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
2256 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
2261 for(
int i = 0;
i < 3;
i++) dlevels[
i] =
p->preview_levels[
i];
2270 g->copied_scale = -1;
2271 g->mask_display = 0;
2272 g->suppress_mask = 0;
2273 g->display_wavelet_scale = 0;
2274 g->displayed_wavelet_scale = 0;
2277 g->preview_auto_levels = 0;
2279 g->preview_levels[1] = 0.f;
2283 g->wdbar_mouse_x =
g->wdbar_mouse_y = -1;
2285 g->lower_cursor =
g->upper_cursor =
FALSE;
2286 g->lower_margin =
g->upper_margin =
FALSE;
2301 g->label_form = GTK_LABEL(gtk_label_new(
"-1"));
2303 gtk_widget_set_tooltip_text(hbox_shapes,
2304 _(
"To add a shape select an algorithm and a shape type and click on the image.\n"
2305 "Shapes are added to the current scale"));
2308 N_(
"show and edit shapes in restricted mode"),
2315 .owner_module = self,
2316 .creation_module = self,
2317 .buttons = shape_buttons,
2319 .action_section = N_(
"shapes"),
2330 gtk_box_pack_start(GTK_BOX(hbox_shapes), shape_buttons_box,
FALSE,
FALSE, 0);
2342 self, N_(
"tools"), N_(
"Activate blur tool"), N_(
"change algorithm for current form"),
2346 self, N_(
"tools"), N_(
"Activate fill tool"), N_(
"change algorithm for current form"),
2350 self, N_(
"tools"), N_(
"Activate cloning tool"), N_(
"change algorithm for current form"),
2354 self, N_(
"tools"), N_(
"Activate healing tool"), N_(
"change algorithm for current form"),
2358 gchar *tt2 = g_strdup_printf(
"%s\n%s", _(
"Ctrl+click to change tool for current form"),
2359 _(
"Shift+click to set the tool as default"));
2360 gchar *tt = g_strdup_printf(
"%s\n%s", _(
"Activate blur tool"), tt2);
2361 gtk_widget_set_tooltip_text(
g->bt_blur, tt);
2363 tt = g_strdup_printf(
"%s\n%s", _(
"Activate fill tool"), tt2);
2364 gtk_widget_set_tooltip_text(
g->bt_fill, tt);
2366 tt = g_strdup_printf(
"%s\n%s", _(
"Activate cloning tool"), tt2);
2367 gtk_widget_set_tooltip_text(
g->bt_clone, tt);
2369 tt = g_strdup_printf(
"%s\n%s", _(
"Activate healing tool"), tt2);
2370 gtk_widget_set_tooltip_text(
g->bt_heal, tt);
2375 GtkWidget *grid_wd_labels = gtk_grid_new();
2376 gtk_grid_set_column_homogeneous(GTK_GRID(grid_wd_labels),
FALSE);
2378 gtk_grid_attach(GTK_GRID(grid_wd_labels),
dt_ui_label_new(_(
"scales:")), 0, 0, 1, 1);
2380 gtk_label_set_width_chars(
g->lbl_num_scales, 2);
2381 gtk_grid_attach(GTK_GRID(grid_wd_labels), GTK_WIDGET(
g->lbl_num_scales), 1, 0, 1, 1);
2383 gtk_grid_attach(GTK_GRID(grid_wd_labels),
dt_ui_label_new(_(
"current:")), 0, 1, 1, 1);
2385 gtk_label_set_width_chars(
g->lbl_curr_scale, 2);
2386 gtk_grid_attach(GTK_GRID(grid_wd_labels), GTK_WIDGET(
g->lbl_curr_scale), 1, 1, 1, 1);
2388 gtk_grid_attach(GTK_GRID(grid_wd_labels),
dt_ui_label_new(_(
"merge from:")), 0, 2, 1, 1);
2390 gtk_label_set_width_chars(
g->lbl_merge_from_scale, 2);
2391 gtk_grid_attach(GTK_GRID(grid_wd_labels), GTK_WIDGET(
g->lbl_merge_from_scale), 1, 2, 1, 1);
2394 g->wd_bar = gtk_drawing_area_new();
2396 gtk_widget_set_tooltip_text(
g->wd_bar, _(
"Top slider adjusts where the merge scales start\n"
2397 "Bottom slider adjusts the number of scales\n"
2398 "Dot indicates the current scale\n"
2399 "Top line indicates that the scale is visible at current zoom level\n"
2400 "Bottom line indicates that the scale has shapes on it"));
2401 g_signal_connect(G_OBJECT(
g->wd_bar),
"draw", G_CALLBACK(
rt_wdbar_draw), self);
2406 g_signal_connect(G_OBJECT(
g->wd_bar),
"scroll-event", G_CALLBACK(
rt_wdbar_scrolled), self);
2407 gtk_widget_add_events(GTK_WIDGET(
g->wd_bar), GDK_POINTER_MOTION_MASK
2408 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
2426 gtk_box_pack_end(GTK_BOX(hbox_scale), gtk_grid_new(),
TRUE,
TRUE, 0);
2437 gtk_box_pack_end(GTK_BOX(hbox_scale), gtk_grid_new(),
TRUE,
TRUE, 0);
2449 gtk_box_pack_start(GTK_BOX(
g->vbox_preview_scale), lbl_psc,
FALSE,
TRUE, 0);
2454 #define NEUTRAL_GRAY 0.5
2459 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->preview_levels_gslider), _(
"Adjust preview levels"));
2468 (
g->preview_levels_gslider)->min_spacing = 0.05;
2469 g_signal_connect(G_OBJECT(
g->preview_levels_gslider),
"value-changed", G_CALLBACK(
rt_gslider_changed), self);
2471 gtk_box_pack_start(GTK_BOX(prev_lvl), GTK_WIDGET(
g->preview_levels_gslider),
TRUE,
TRUE, 0);
2478 gtk_box_pack_start(GTK_BOX(
g->vbox_preview_scale), prev_lvl,
TRUE,
TRUE, 0);
2482 GtkWidget *label1 = gtk_label_new(_(
"shape selected:"));
2483 gtk_label_set_ellipsize(GTK_LABEL(label1), PANGO_ELLIPSIZE_START);
2484 gtk_box_pack_start(GTK_BOX(hbox_shape_sel), label1,
FALSE,
TRUE, 0);
2485 g->label_form_selected = GTK_LABEL(gtk_label_new(
"-1"));
2486 gtk_widget_set_tooltip_text(hbox_shape_sel,
2487 _(
"Click on a shape to select it,\nto unselect click on an empty space"));
2488 gtk_box_pack_start(GTK_BOX(hbox_shape_sel), GTK_WIDGET(
g->label_form_selected),
FALSE,
TRUE, 0);
2494 gtk_widget_set_tooltip_text(
g->cmb_fill_mode, _(
"Erase the detail or fills with chosen color"));
2498 = (GdkRGBA){.red =
p->fill_color[0], .green =
p->fill_color[1], .blue =
p->fill_color[2], .alpha = 1.0 };
2502 gtk_box_pack_start(GTK_BOX(
g->hbox_color_pick), lbl_fill_color,
FALSE,
TRUE, 0);
2504 g->colorpick = gtk_color_button_new_with_rgba(&
color);
2505 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(
g->colorpick),
FALSE);
2506 gtk_color_button_set_title(GTK_COLOR_BUTTON(
g->colorpick), _(
"Select fill color"));
2507 gtk_widget_set_tooltip_text(
g->colorpick, _(
"Select fill color"));
2509 gtk_box_pack_start(GTK_BOX(
g->hbox_color_pick), GTK_WIDGET(
g->colorpick),
TRUE,
TRUE, 0);
2512 gtk_widget_set_tooltip_text(
g->colorpicker, _(
"Pick fill color from image"));
2514 gtk_box_pack_start(GTK_BOX(
g->vbox_fill),
g->hbox_color_pick,
TRUE,
TRUE, 0);
2519 gtk_widget_set_tooltip_text(
g->sl_fill_brightness,
2520 _(
"Adjusts color brightness to fine-tune it. Works with erase as well"));
2526 gtk_widget_set_tooltip_text(
g->cmb_blur_type, _(
"Type for the blur algorithm"));
2530 gtk_widget_set_tooltip_text(
g->sl_blur_radius, _(
"Radius of the selected blur type"));
2536 gtk_widget_set_tooltip_text(
g->sl_mask_opacity, _(
"Set the opacity on the selected shape"));
2551 gtk_widget_set_tooltip_text(
g->cmb_heal_algorithm,
2552 _(
"- Linear: the source keeps its own noise and texture amplitude,\n"
2553 " a source brighter than the target makes it noisier\n"
2554 "- Square root: the source noise is scaled to the brightness of the target"));
2568 gtk_box_pack_start(GTK_BOX(self->
gui->
widget),
g->vbox_preview_scale,
TRUE,
TRUE, 0);
2629 const float right,
const float bottom)
2631 bounds->
y = fminf(
top, bounds->
y);
2632 bounds->
x = fminf(left, bounds->
x);
2633 bounds->
r = fmaxf(right, bounds->
r);
2634 bounds->
b = fmaxf(bottom, bounds->
b);
2648 const GList *member,
int *formid,
int *index)
2653 if(*index < 0)
return NULL;
2667 (area->
y + area->
height) + dy);
2675 if(bounds->
y > area->
y) bounds->
y =
MAX(bounds->
y - overlap, area->
y);
2676 if(bounds->
x > area->
x) bounds->
x =
MAX(bounds->
x - overlap, area->
x);
2677 if(bounds->
r < area->
x + area->
width) bounds->
r =
MAX(bounds->
r + overlap, area->
x + area->
width);
2678 if(bounds->
b < area->
y + area->
height) bounds->
b =
MAX(bounds->
b + overlap, area->
y + area->
height);
2686 static const char cache_tag[] =
"retouch:geometry";
2696 hash =
dt_hash(
hash, (
const char *)&raster_step,
sizeof(raster_step));
2763 static const char cache_tag[] =
"boxes";
2777 if(
ctx->stats)
ctx->stats->boxes_computed++;
2782 if(
ctx->stats) {
if(
created)
ctx->stats->boxes_computed++;
else ctx->stats->boxes_hit++; }
2912 || src.
x + src.
width < bounds->
x);
2925 .r = roi_in->
width + roi_in->
x, .b = roi_in->
height + roi_in->
y };
2939 while(
memcmp(&bounds, &previous,
sizeof(bounds)))
2948 "[retouch] %-8s modify_roi_in: %d stabilisation pass(es), boxes %d (%d memo / %d rasterised),"
2969 for(
int i = 0;
i < stride;
i +=
ch)
2982 for(
int i = 0;
i < stride;
i +=
ch)
3009 work_profile->
lut_in, work_profile->unbounded_coeffs_in,
3038 const float left =
levels[0];
3040 const float right =
levels[2];
3044 const float delta = (right - left) / 2.0f;
3047 const float in_inv_gamma =
powf(10,
tmp);
3064 work_profile->
lut_in, work_profile->unbounded_coeffs_in,
3075 for(
int c = 0; c < 1; c++)
3093 work_profile->
lut_out, work_profile->unbounded_coeffs_out,
3108#undef RT_WDBAR_INSET
3110#undef RETOUCH_NO_FORMS
3111#undef RETOUCH_MAX_SCALES
3112#undef RETOUCH_NO_SCALES
3114#undef RETOUCH_PREVIEW_LVL_MIN
3115#undef RETOUCH_PREVIEW_LVL_MAX
3137 const struct dt_iop_roi_t *
const roi_out,
const int ch,
const int dx,
const int dy)
3140 const int xoffs = roi_out->
x - roi_in->
x - dx;
3141 const int yoffs = roi_out->
y - roi_in->
y - dy;
3144 for(
int y = 0; y <
y_to; y++)
3199 const int mx = ((int)(
xx / roi_in->
scale)) - roi_mask->
x;
3210 const float opacity)
3226 const float f =
m[
xx] * opacity;
3227 const float f1 = (1.0f -
f);
3239 const float opacity)
3253 const float f = (*m) * opacity;
3254 if(
f >
d[3])
d[3] =
f;
3274 const float f =
m[
xx] * opacity;
3277 d[4*
xx + c] =
d[4*
xx + c] * (1.0f -
f) + fill_color[c] *
f;
3289 fprintf(
stderr,
"retouch_clone: error allocating memory for cloning\n");
3306 const float blur_radius,
const int use_sse)
3308 if(
fabsf(blur_radius) <= 0.1f)
return 0;
3310 const float sigma = blur_radius * roi_in->
scale;
3318 fprintf(
stderr,
"retouch_blur: error allocating memory for blurring\n");
3342 const float detail = -1.0f;
3383 const gboolean
has_level = (scale == 0 || scale == scales + 1);
3400 fprintf(
stderr,
"retouch_heal: error allocating memory for healing\n");
3478 if(
ctx->stats)
ctx->stats->masks_rasterised++;
3482 fprintf(
stderr,
"rt_process_forms: error retrieving mask\n");
3494 "rt_process_forms: the rasterised area %ix%i+%i+%i disagrees with the announced %ix%i+%i+%i\n",
3502 = { .
x = area->
x, .y = area->
y, .width = area->
width, .height = area->
height, .scale = 1.f };
3513#define RT_MASK_MEMO_HEADER 64u
3526 static const char cache_tag[] =
"scaled-mask";
3609 if(
ctx->stats)
ctx->stats->masks_hit++;
3683 const int dx = (int)shape->
dx;
3684 const int dy = (int)shape->
dy;
3713 fprintf(
stderr,
"rt_shape_scaled_mask: error allocating memory\n");
3725 shape->
mask = buffer;
3761 if(index >= 0 &&
p->rt_forms[index].scale != scale)
return RT_SHAPE_SKIP;
3766 fprintf(
stderr,
"rt_process_forms: missing form=%i from %s\n", formid, index < 0 ?
"array" :
"masks");
3771 shape->
index = index;
3773 shape->
algo =
p->rt_forms[index].algorithm;
3778 p->rt_forms[index].distort_mode))
3798 if(
wt_p->merge_from_scale == 0 &&
wt_p->return_layer > 0 && scale !=
wt_p->return_layer && scale != 0)
return 0;
3800 if(scale >
wt_p->scales + 1)
return 0;
3811 const int mask_display
3812 =
usr_d->mask_display && (
wt_p->return_layer > 0 || scale ==
usr_d->display_scale);
3817 if(
wt_p->scales <
p->num_scales &&
wt_p->return_layer == 0 && scale ==
wt_p->scales + 1)
3819 scale =
p->num_scales + 1;
3822 if(
usr_d->suppress_mask)
return 0;
3835 const int index = shape.
index;
3840 const int dx = (int)shape.
dx;
3841 const int dy = (int)shape.
dy;
3865 p->rt_forms[index].blur_type,
p->rt_forms[index].blur_radius,
wt_p->use_sse) != 0)
3878 fill_color[0] = fill_color[1] = fill_color[2] =
p->rt_forms[index].fill_brightness;
3882 fill_color[0] =
p->rt_forms[index].fill_color[0] +
p->rt_forms[index].fill_brightness;
3883 fill_color[1] =
p->rt_forms[index].fill_color[1] +
p->rt_forms[index].fill_brightness;
3884 fill_color[2] =
p->rt_forms[index].fill_color[2] +
p->rt_forms[index].fill_brightness;
3886 fill_color[3] = 0.0f;
3891 fprintf(
stderr,
"rt_process_forms: unknown algorithm %i\n", algo);
3895 usr_d->stats->shapes_applied++;
3912 const rt_memo_stats_t *
const stats,
const double start,
const char *
const path)
3915 "[retouch] %-8s process %s %dx%d: %d shape(s), masks %d (%d memo / %d rasterised),"
3916 " boxes %d (%d memo / %d rasterised), algorithms %.3f s, total %.3f s\n",
3946 const int display_wavelet_scale = (
g &&
gui_active) ?
g->display_wavelet_scale : 0;
3974 roi_in->
scale, use_sse);
4025 g->preview_auto_levels = -1;
4033 for(
int i = 0;
i < 3;
i++)
g->preview_levels[
i] =
levels[
i];
4036 g->preview_auto_levels = 2;
4042 if(
dwt_p->return_layer > 0 &&
dwt_p->return_layer <
dwt_p->scales + 1)
4071 const float *
const in,
float *
const out,
const dt_iop_roi_t *
const roi_in,
4093 fprintf(
stderr,
"dt_heal_cl: error allocating memory for healing\n");
4133 fprintf(
stderr,
"dt_heal_cl: error allocating memory for healing\n");
4161 cl_mem dev_out,
const struct dt_iop_roi_t *
const roi_out,
const int dx,
4162 const int dy,
const int kernel)
4166 const int xoffs = roi_out->
x - roi_in->
x - dx;
4167 const int yoffs = roi_out->
y - roi_in->
y - dy;
4172 const size_t sizes[]
4214 fprintf(
stderr,
"rt_upload_scaled_mask_cl: error allocating the device buffer\n");
4221 fprintf(
stderr,
"rt_upload_scaled_mask_cl: error writing the mask to the device\n");
4273 const int kernel =
gd->kernel_retouch_copy_mask_to_alpha;
4321 gd->kernel_retouch_copy_buffer_to_buffer);
4330 gd->kernel_retouch_copy_buffer_to_buffer_masked);
4350 const int kernel =
gd->kernel_retouch_fill;
4387 if(
fabsf(blur_radius) <= 0.1f)
return err;
4392 const cl_mem dev_dest =
4403 const int kernel =
gd->kernel_retouch_image_rgb2lab;
4414 gd->kernel_retouch_copy_buffer_to_image);
4439 const float detail = -1.0f;
4455 gd->kernel_retouch_copy_image_to_buffer_masked);
4464 const int kernel =
gd->kernel_retouch_image_lab2rgb;
4489 cl_mem dev_dest =
NULL;
4494 fprintf(
stderr,
"retouch_heal_cl: error allocating memory for healing\n");
4503 fprintf(
stderr,
"retouch_heal_cl: error allocating memory for healing\n");
4509 gd->kernel_retouch_copy_buffer_to_buffer);
4517 gd->kernel_retouch_copy_buffer_to_buffer);
4540 gd->kernel_retouch_copy_buffer_to_buffer_masked);
4566 if(
wt_p->merge_from_scale == 0 &&
wt_p->return_layer > 0 && scale !=
wt_p->return_layer && scale != 0)
4569 if(scale >
wt_p->scales + 1)
return err;
4576 const int mask_display
4577 =
usr_d->mask_display && (
wt_p->return_layer > 0 || scale ==
usr_d->display_scale);
4582 if(
wt_p->scales <
p->num_scales &&
wt_p->return_layer == 0 && scale ==
wt_p->scales + 1)
4584 scale =
p->num_scales + 1;
4591 if(!
usr_d->suppress_mask)
4606 const int index = shape.
index;
4611 const int dx = (int)shape.
dx;
4612 const int dy = (int)shape.
dy;
4637 p->rt_forms[index].blur_type,
p->rt_forms[index].blur_radius,
gd);
4646 fill_color[0] = fill_color[1] = fill_color[2] =
p->rt_forms[index].fill_brightness;
4650 fill_color[0] =
p->rt_forms[index].fill_color[0] +
p->rt_forms[index].fill_brightness;
4651 fill_color[1] =
p->rt_forms[index].fill_color[1] +
p->rt_forms[index].fill_brightness;
4652 fill_color[2] =
p->rt_forms[index].fill_color[2] +
p->rt_forms[index].fill_brightness;
4659 fprintf(
stderr,
"rt_process_forms: unknown algorithm %i\n", algo);
4668 usr_d->stats->shapes_applied++;
4694 const int ch =
piece->dsc_in.channels;
4702 const int display_wavelet_scale = (
g &&
gui_active) ?
g->display_wavelet_scale : 0;
4709 dt_print(
DT_DEBUG_OPENCL,
"[retouch process_cl] error allocating memory for wavelet decompose on device %d\n", devid);
4716 size_t origin[] = { 0, 0, 0 };
4717 size_t region[] = {
roi_rt->width,
roi_rt->height, 1 };
4735 (!display_wavelet_scale
4756 const int kernel =
gd->kernel_retouch_clear_alpha;
4799 g->preview_auto_levels = -1;
4809 for(
int i = 0;
i < 3;
i++)
g->preview_levels[
i] =
levels[
i];
4812 g->preview_auto_levels = 2;
4818 if(
dwt_p->return_layer > 0 &&
dwt_p->return_layer <
dwt_p->scales + 1)
4827 const int kernel =
gd->kernel_retouch_copy_alpha;
4840 gd->kernel_retouch_copy_buffer_to_image);
4863 if(index < 0)
return;
4865 if(
p->rt_forms[index].algorithm == algo)
return;
4870 p->rt_forms[index].algorithm = algo;
4884 form->
type = masks_type;
4898 fprintf(
stderr,
"populate_masks_context_menu: missing form=%i from array\n", formid);
Handle default and user-set shortcuts (accelerators)
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[]
The blending panel's GUI state and API, cut out of develop/blend.h.
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
void dt_iop_color_picker_reset(dt_iop_module_t *module, gboolean keep)
GtkWidget * dt_color_picker_new(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w)
void dt_colorspaces_apply_profile(const char *const op_name, const char *const instance_name, const float *const image_in, float *const image_out, const int width, const int height, const int cst_from, const int cst_to, int *converted_cst, const dt_iop_order_iccprofile_info_t *const profile_info)
Convert a 4-channel float buffer between RGB and Lab through one profile.
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
static 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
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)
Integer for name, clamped to the bounds declared in the XML.
void dt_control_log(const char *msg,...)
void dt_control_queue_redraw_center()
Request a redraw of the centre view.
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
#define dt_dev_add_history_item(dev, module, enable, redraw)
#define dt_dev_pixelpipe_update_history_main(dev)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_work_profile_info(const struct dt_dev_pixelpipe_t *pipe)
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
static int dt_pthread_rwlock_unlock(dt_pthread_rwlock_t *rwlock) RELEASE_GENERIC(rwlock) NO_THREAD_SAFETY_ANALYSIS
static int dt_pthread_rwlock_rdlock(dt_pthread_rwlock_t *rwlock) ACQUIRE_SHARED(rwlock) NO_THREAD_SAFETY_ANALYSIS
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
static uint64_t dt_hash(uint64_t hash, const char *str, size_t size)
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 dt_heal_solver_t solver)
void dt_heal_free_cl(heal_params_cl_t *p)
heal_params_cl_t * dt_heal_init_cl(const int devid)
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 dt_heal_solver_t solver)
float dt_boundingbox_t[4]
__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)
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)
void dt_iop_gui_leave_critical_section(dt_iop_module_t *const module)
Release what dt_iop_gui_enter_critical_section() took. Also a no-op headless.
void dt_iop_request_focus(dt_iop_module_t *module)
Move darkroom focus to module, or clear it with NULL.
@ IOP_FLAGS_INTERNAL_MASKS
@ IOP_FLAGS_SUPPORTS_BLENDING
void dt_iop_gui_enter_critical_section(dt_iop_module_t *const module)
Take the module's GUI lock, serialising access to its dt_iop_gui_data_t.
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 dt_iop_gui_data_t * dt_iop_gui_data(const struct dt_iop_module_t *m)
The module's GUI data blob, NULL-safe for headless callers: IOP process() implementations read it for...
#define IOP_GUI_ALLOC(module)
static float kernel(const float *x, const float *y)
GtkWidget * dt_ui_section_label_new(const gchar *str)
GtkWidget * dt_ui_label_new(const gchar *str)
static const dt_dev_pixelpipe_t * pipe
static const dt_dev_pixelpipe_t const dt_dev_pixelpipe_iop_t * piece
static const dt_iop_drawlayer_params_t * params
_lib_location_type_t type
int32_t dt_get_debug_flags(void)
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
float *const restrict const size_t const size_t ch
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
dt_masks_result_t dt_masks_group_set_member_opacity(dt_develop_t *dev, const int group_id, const int formid, const float opacity, dt_masks_member_t *out)
Set a group member's opacity.
dt_masks_raster_result_t dt_masks_get_mask(const dt_iop_module_t *const module, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *const piece, dt_masks_form_t *const form, float **buffer, dt_masks_area_t *area)
dt_masks_form_t * dt_masks_get_from_id_in_pipe(const dt_dev_pixelpipe_t *pipe, int id)
uint64_t dt_masks_form_get_own_hash(uint64_t hash, GList *masks, const dt_masks_form_t *form)
dt_masks_raster_result_t dt_masks_get_area(const dt_iop_module_t *iop_module, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, dt_masks_area_t *area)
dt_masks_form_t * dt_masks_create_ext(dt_develop_t *dev, dt_masks_type_t type)
void dt_masks_area_scale(dt_masks_area_t *area, const double scale)
gboolean dt_masks_area_intersects(const dt_masks_area_t *area, const dt_iop_roi_t *roi)
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_raster_result_t dt_masks_get_source_area(const dt_iop_module_t *iop_module, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, dt_masks_area_t *area)
void dt_masks_set_edit_mode(struct dt_iop_module_t *module, dt_masks_edit_mode_t value)
Ask the masks module about a shape or a group, instead of reading its structs.
void dt_masks_group_ungroup(dt_develop_t *dev, dt_masks_form_t *dest_group, dt_masks_form_t *group_form)
void dt_masks_change_form_gui(dt_develop_t *dev, dt_masks_form_t *new_form)
dt_masks_form_group_t * dt_masks_form_get_selected_group_live(const dt_masks_form_t *mask_form, const dt_masks_form_gui_t *mask_gui)
Resolve a "live" selected group entry, even if GUI selection is stale.
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.
dt_masks_form_t * dt_masks_get_visible_form(const dt_develop_t *dev)
Return the currently visible form used by the masks GUI.
void dt_masks_reset_form_gui(dt_develop_t *dev)
gboolean dt_masks_creation_mode_enter(dt_develop_t *dev, dt_iop_module_t *module, const dt_masks_type_t type)
Enter mask creation mode for a given shape type.
dt_masks_form_group_t * dt_masks_group_add_form_with_state(dt_develop_t *dev, dt_masks_form_t *group_form, dt_masks_form_t *mask_form, const int parentid, const dt_masks_state_t state, const float opacity)
The interactive half of the masks subsystem: the editing state (dt_masks_form_gui_t),...
@ DT_MASKS_SHAPE_INDEX_BRUSH
@ DT_MASKS_SHAPE_INDEX_ELLIPSE
@ DT_MASKS_SHAPE_INDEX_CIRCLE
@ DT_MASKS_SHAPE_INDEX_POLYGON
@ DT_MASKS_SHAPE_BUTTONS_ALL
@ DT_MASKS_EDIT_RESTRICTED
dt_masks_result_t
What a request that may change the masks model did.
#define DEVELOP_MASKS_NB_SHAPES
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
static void * dt_calloc_align(size_t size)
dt_alloc_align() followed by a zero fill.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
dt_imageio_retval_t status
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
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
#define __OMP_PARALLEL_FOR__(...)
const char * dt_pixelpipe_name(dt_dev_pixelpipe_type_t pipe)
void dt_dev_pixelpipe_cache_wrlock_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the write lock on the entry.
void dt_dev_pixelpipe_cache_ref_count_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Take or release one reference on a cache line. A referenced line is never evicted,...
void dt_dev_pixelpipe_cache_rdlock_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the read lock on the entry.
int dt_dev_pixelpipe_cache_get(const uint64_t hash, const size_t size, const char *name, const int id, const gboolean alloc, void **data, dt_pixel_cache_entry_t **entry)
Get a cache line from the cache.
size_t dt_pixel_cache_entry_get_size(const dt_pixel_cache_entry_t *entry)
gboolean dt_dev_pixelpipe_cache_ref_entry_by_hash(const uint64_t hash, void **data, dt_pixel_cache_entry_t **entry)
Resolve and retain an existing cache entry by hash.
void dt_dev_pixelpipe_cache_flag_auto_destroy(dt_pixel_cache_entry_t *cache_entry)
Flag a cache line as disposable (auto_destroy), for short-lived lines nothing will need again: the re...
Pixelpipe cache for storing intermediate results in the pixelpipe.
#define DT_PIXELPIPE_CACHE_HASH_INVALID
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
static gboolean rt_shape_buttons_can_start(GtkWidget *button, dt_iop_module_t *self, dt_masks_type_t type, gpointer user_data)
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 rt_shape_status_t rt_rasterize_scaled_mask(const rt_masks_ctx_t *const ctx, dt_masks_form_t *form, const dt_masks_area_t *const area, const dt_iop_roi_t *const roi_layer, const dt_iop_roi_t *const roi_mask_scaled, float *const dst)
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 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 rt_memo_result_t rt_scaled_mask_take_memo(const rt_masks_ctx_t *const ctx, const uint64_t hash, const dt_iop_roi_t *const roi_layer, const int dx, const int dy, rt_prepared_shape_t *shape)
static cl_int rt_upload_scaled_mask_cl(const int devid, const rt_prepared_shape_t *const shape, cl_mem *p_dev_mask_scaled)
static rt_shape_status_t rt_shape_scaled_mask(const rt_masks_ctx_t *const ctx, dt_masks_form_t *form, const uint64_t shape_hash, const dt_iop_roi_t *const roi_layer, rt_prepared_shape_t *shape)
static void rt_report_render(const dt_dev_pixelpipe_t *pipe, const dt_iop_roi_t *const roi, const rt_memo_stats_t *const stats, const double start, const char *const path)
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)
static gboolean rt_area_is_sane(const dt_masks_area_t *const area)
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)
static const GList * rt_pipe_group_members(const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
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.
static void rt_extend_roi_in_from_source_clones(const rt_masks_ctx_t *const ctx, const dt_iop_roi_t *roi_in, const int formid_src, const dt_masks_area_t *src, rt_roi_bounds_t *const bounds)
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
dt_iop_retouch_heal_algorithm_t
@ DT_IOP_RETOUCH_HEAL_SQRT
@ DT_IOP_RETOUCH_HEAL_LINEAR
static float rt_masks_form_get_opacity(dt_iop_module_t *self, int formid)
#define RT_MASK_MEMO_HEADER
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 uint64_t rt_shape_geometry_hash(const uint64_t base, dt_masks_form_t *const form)
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)
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 dt_heal_domain_t rt_heal_domain(const dt_iop_retouch_params_t *const p, const int scale, const int scales)
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 void rt_compute_shape_geometry(const rt_masks_ctx_t *const ctx, dt_masks_form_t *form, rt_shape_geometry_t *out)
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, const dt_iop_retouch_global_data_t *const gd, const int max_iter, const dt_heal_domain_t domain)
static gboolean rt_any_preview_active(dt_iop_retouch_gui_data_t *g)
void gui_init(dt_iop_module_t *self)
static rt_shape_status_t rt_prepare_shape(const rt_masks_ctx_t *const ctx, const GList *member, const int scale, const uint64_t base_hash, const dt_iop_roi_t *roi_layer, rt_prepared_shape_t *shape)
void change_image(struct dt_iop_module_t *self)
static gboolean rt_shape_has_effect(const rt_prepared_shape_t *const shape, const int dx, const int dy)
static void image_rgb2lab(float *img_src, const int width, const int height, const int ch, const int use_sse)
static void rt_display_selected_shapes_lbl(dt_develop_t *dev, dt_iop_retouch_gui_data_t *g)
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)
static gboolean rt_perf_enabled(void)
static uint64_t rt_scaled_mask_hash(const uint64_t shape_hash, const dt_iop_roi_t *const roi_layer, const int dx, const int dy, const dt_iop_retouch_algo_type_t algo)
#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 void rt_roi_bounds_include(rt_roi_bounds_t *const bounds, const float left, const float top, const float right, const float bottom)
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)
static rt_memo_result_t rt_scaled_mask_memo_holds(const void *const data, const struct dt_pixel_cache_entry_t *const entry, const dt_iop_roi_t *const roi_layer, const int dx, const int dy, rt_prepared_shape_t *shape)
static rt_memo_result_t rt_scaled_mask_publish(const rt_masks_ctx_t *const ctx, dt_masks_form_t *form, const uint64_t hash, const dt_masks_area_t *const area, const dt_iop_roi_t *const roi_layer, rt_prepared_shape_t *shape)
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 void rt_compute_roi_in(const rt_masks_ctx_t *const ctx, const dt_iop_roi_t *roi_in, rt_roi_bounds_t *const bounds)
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)
static void rt_scaled_mask_roi(const dt_masks_area_t *const area, const dt_iop_roi_t *const roi_in, const int dx, const int dy, const int algo, dt_iop_roi_t *roi_mask_scaled)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
static int rt_get_index_from_formid(const dt_iop_retouch_params_t *p, const int formid)
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 int rt_masks_get_delta_to_destination(const rt_masks_ctx_t *const ctx, const dt_iop_roi_t *roi, dt_masks_form_t *form, float *dx, float *dy, const int distort_mode)
static int rt_get_selected_shape_index(dt_develop_t *dev, const dt_iop_retouch_params_t *p)
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 dt_masks_form_t * rt_pipe_member_form(const dt_dev_pixelpipe_t *pipe, const dt_iop_retouch_params_t *p, const GList *member, int *formid, int *index)
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)
static int rt_masks_point_calc_delta(const rt_masks_ctx_t *const ctx, const dt_iop_roi_t *roi, const float *target, const float *source, float *dx, float *dy, const int distort_mode)
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 void rt_extend_roi_in_for_clone(const rt_masks_ctx_t *const ctx, const dt_iop_roi_t *roi_in, rt_roi_bounds_t *const bounds)
static uint64_t rt_geometry_base_hash(const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
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 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, const dt_heal_domain_t domain)
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)
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 gboolean rt_algo_needs_source(const dt_iop_retouch_algo_type_t algo)
static void rt_roi_bounds_include_area(rt_roi_bounds_t *const bounds, const dt_masks_area_t *area, const float dx, const float dy)
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 gboolean rt_shape_box(const rt_masks_ctx_t *const ctx, dt_masks_form_t *form, const uint64_t shape_hash, const rt_box_t want, dt_masks_area_t *out)
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 void rt_release_shape(rt_prepared_shape_t *shape)
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 void rt_roi_bounds_grow_for_blur(rt_roi_bounds_t *const bounds, const dt_masks_area_t *area, const int overlap)
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 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 void rt_fill_scaled_mask(const float *const mask, const dt_iop_roi_t *const roi_mask, float *const mask_scaled, const dt_iop_roi_t *const roi_mask_scaled, const dt_iop_roi_t *const roi_in)
static int rt_allow_create_form(dt_iop_module_t *self)
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 void rt_intersect_2_rois(const dt_iop_roi_t *const roi_1, const dt_iop_roi_t *const roi_2, const int dx, const int dy, const int padding, dt_iop_roi_t *roi_dest)
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_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 gboolean rt_compute_shape_box(const rt_masks_ctx_t *const ctx, dt_masks_form_t *form, const rt_box_t want, dt_masks_area_t *out)
static cairo_surface_t * dt_cairo_image_surface_create(cairo_format_t format, int width, int height)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ 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)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
#define for_each_channel(_var,...)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
unsigned __int64 uint64_t
int mask_rasterization_step
Rasterisation step for drawn masks, in image pixels. Always >= 1.
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
dt_iop_params_t * default_params
struct dt_develop_blend_params_t * blend_params
struct dt_iop_module_gui_t * gui
struct dt_develop_t * dev
dt_iop_global_data_t * global_data
dt_aligned_pixel_t picked_output_color
A profile reduced to the arithmetic the pixel loop can run: two matrices and six tone-curve LUTs,...
int nonlinearlut
Non-zero when the profile has tone curves at all; tested as a boolean everywhere, but it is really th...
int lutsize
Entry count of each of the six LUTs. Always 65536 in practice: both callers of dt_ioppr_init_profile_...
dt_colormatrix_t matrix_out_transposed
float * lut_out[3]
Per-channel linear -> encoded tone curve, same convention as lut_in.
float * lut_in[3]
Per-channel encoded -> linear tone curve, lutsize entries each, sampled over [0,1]....
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
GtkWidget * cmb_heal_algorithm
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_heal_algorithm_t heal_algorithm
dt_iop_retouch_form_data_t rt_forms[300]
Region of interest passed through the pixelpipe.
One shape's membership of one group, BY VALUE.
struct rt_memo_stats_t * stats
const dt_dev_pixelpipe_t * pipe
const dt_dev_pixelpipe_iop_t * piece
const dt_dev_pixelpipe_iop_t * piece
const dt_iop_module_t * self
const dt_dev_pixelpipe_t * pipe
struct dt_pixel_cache_entry_t * mask_entry
dt_iop_retouch_algo_type_t algo
#define __DT_CLONE_TARGETS__
static double dt_get_wtime(void)