89 return _(
"spot removal");
94 return _(
"this module is deprecated. please use the retouch module instead.");
101 _(
"linear, RGB, scene-referred"),
103 _(
"linear, RGB, scene-referred"));
122 void *new_params,
const int new_version)
124 if(old_version == 1 && new_version == 2)
126 typedef struct dt_iop_spots_v1_t
132 typedef struct dt_iop_spots_params_v1_t
135 dt_iop_spots_v1_t spot[32];
136 } dt_iop_spots_params_v1_t;
138 dt_iop_spots_params_v1_t *
o = (dt_iop_spots_params_v1_t *)old_params;
143 for(
int i = 0;
i <
o->num_spots;
i++)
167 n->clone_algo[
i] = 2;
172 int last_spot_num = 0;
174 for(GList *l = self->
dev->
history; l; l = g_list_next(l))
178 if(!strcmp(item->
op_name,
"spots")) last_spot_num = item->
num;
181 if(last_spot_num == 0) last_spot_num = count;
188 for(GList *l = self->
dev->
forms; l; l = g_list_next(l))
210 int nalgo[64] = { 2 };
217 for(GList *forms = grp->
points; (
i < 64) && forms; forms = g_list_next(forms))
221 for(
int j = 0; j < 64; j++)
223 if(
p->clone_id[j] == nid[
i])
225 nalgo[
i] =
p->clone_algo[j];
234 for(
int i = 0;
i < 64;
i++)
236 p->clone_algo[
i] = nalgo[
i];
237 p->clone_id[
i] = nid[
i];
253 dt_control_log(_(
"spot module is limited to 64 shapes. please add a new instance !"));
257 && (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_path))
258 || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_circle))
259 || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g->bt_ellipse))))
264 if(widget !=
g->bt_path || nb >= 64) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_path),
FALSE);
265 if(widget !=
g->bt_circle || nb >= 64) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_circle),
FALSE);
266 if(widget !=
g->bt_ellipse || nb >= 64) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_ellipse),
FALSE);
268 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
302 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->
gui->
off),
TRUE);
309 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
return FALSE;
316 if(widget ==
g->bt_path)
318 else if(widget ==
g->bt_circle)
320 else if(widget ==
g->bt_ellipse)
365 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_path),
FALSE);
366 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_circle),
FALSE);
367 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_ellipse),
FALSE);
381 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
386 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
410 int roir = roi_in->
width + roi_in->
x;
411 int roib = roi_in->
height + roi_in->
y;
412 int roix = roi_in->
x;
413 int roiy = roi_in->
y;
423 for(
const GList *forms = grp->
points; forms; forms = g_list_next(forms))
436 roiy = fminf(area.
y, roiy);
437 roix = fminf(area.
x, roix);
438 roir = fmaxf(area.
x + area.
width, roir);
439 roib = fmaxf(area.
y + area.
height, roib);
444 const float scwidth =
piece->buf_in.width * roi_in->
scale, scheight =
piece->buf_in.height * roi_in->
scale;
445 roi_in->
x = CLAMP(roix, 0, scwidth - 1);
446 roi_in->
y = CLAMP(roiy, 0, scheight - 1);
447 roi_in->
width = CLAMP(roir - roi_in->
x, 1, scwidth + .5f - roi_in->
x);
448 roi_in->
height = CLAMP(roib - roi_in->
y, 1, scheight + .5f - roi_in->
y);
453 const float *points,
size_t points_count,
float *
new)
457 for(
size_t i = 0;
i < points_count * 2;
i += 2)
459 new[
i] = points[
i] * scalex;
460 new[
i + 1] = points[
i + 1] * scaley;
465 const dt_iop_roi_t *roi,
const float *target,
const float *source,
int *dx,
475 *dx = points[0] - points[2];
476 *dy = points[1] - points[3];
491 res = masks_point_calc_delta(self,
pipe, roi, pt->node, form->
source, dx, dy);
497 res = masks_point_calc_delta(self,
pipe, roi, pt->center, form->
source, dx, dy);
503 res = masks_point_calc_delta(self,
pipe, roi, pt->center, form->
source, dx, dy);
526 const int posx,
const int posy,
const int dx,
const int dy)
528 const float *in = buffers->
in;
529 float *
out = buffers->
out;
532 const int ch = buffers->
ch;
533 const int fw = 2 * rad;
534 const int fh = 2 * rad;
536 for(
int yy = posy; yy < posy + fh; yy++)
539 if(yy < roi_out->y || yy >= roi_out->
y + roi_out->
height)
continue;
541 if(yy - dy < roi_in->y || yy - dy >= roi_in->
y + roi_in->
height)
continue;
542 for(
int xx = posx; xx < posx + fw; xx++)
545 if(xx < roi_out->
x || xx >= roi_out->
x + roi_out->
width)
continue;
547 if(xx - dx < roi_in->
x || xx - dx >= roi_in->
x + roi_in->
width)
continue;
549 const float f = filter[xx - posx + 1] * filter[yy - posy + 1];
550 for(
int c = 0; c <
ch; c++)
551 out[
ch * ((
size_t)roi_out->
width * (yy - roi_out->
y) + xx - roi_out->
x) + c]
552 =
out[
ch * ((size_t)roi_out->
width * (yy - roi_out->
y) + xx - roi_out->
x) + c] * (1.0f -
f)
553 + in[
ch * ((size_t)roi_in->
width * (yy - dy - roi_in->
y) + xx - dx - roi_in->
x) + c] *
f;
579 const int rad =
MIN(radf[0], radf[1]);
580 const int posx = points[0] - rad;
581 const int posy = points[1] - rad;
582 const int posx_source = points[2] - rad;
583 const int posy_source = points[3] - rad;
584 const int dx = posx - posx_source;
585 const int dy = posy - posy_source;
587 float *filter = malloc(
sizeof(
float) * (2 * rad + 1));
592 for(
int k = -rad;
k <= rad;
k++)
594 const float kk = 1.0f - fabsf(
k / (
float)rad);
595 filter[rad +
k] = kk * kk * (3.0f - 2.0f * kk);
614 const float *in = buffers->
in;
615 float *
out = buffers->
out;
618 const int ch = buffers->
ch;
632 if(area.
width < 1 || area.
height < 1 || !masks_get_delta(self,
pipe, roi_in, form, &dx, &dy)
633 || (dx == 0 && dy == 0))
639 const int fts = area.
y * roi_in->
scale;
641 const int fls = area.
x * roi_in->
scale;
645 for(
int yy = fts + 1; yy < fts + fhs - 1; yy++)
648 if(yy < roi_out->y || yy >= roi_out->
y + roi_out->
height)
continue;
650 if(yy - dy < roi_in->y || yy - dy >= roi_in->
y + roi_in->
height)
continue;
651 for(
int xx = fls + 1; xx < fls + fws - 1; xx++)
654 if(xx < roi_out->
x || xx >= roi_out->
x + roi_out->
width)
continue;
656 if(xx - dx < roi_in->
x || xx - dx >= roi_in->
x + roi_in->
width)
continue;
658 const float f = mask[((int)((yy - fts) / roi_in->
scale)) * area.
width
659 + (int)((xx - fls) / roi_in->
scale)] * opacity;
661 for(
int c = 0; c <
ch; c++)
662 out[
ch * ((
size_t)roi_out->
width * (yy - roi_out->
y) + xx - roi_out->
x) + c]
663 =
out[
ch * ((size_t)roi_out->
width * (yy - roi_out->
y) + xx - roi_out->
x) + c] * (1.0f -
f)
664 + in[
ch * ((size_t)roi_in->
width * (yy - dy - roi_in->
y) + xx - dx - roi_in->
x) + c] *
f;
672 const float *
const in,
683 float *outb =
out + (size_t)
ch *
k * roi_out->
width;
684 const float *inb = in + (size_t)
ch * roi_in->
width * (
k + roi_out->
y - roi_in->
y)
685 +
ch * (roi_out->
x - roi_in->
x);
686 memcpy(outb, inb,
sizeof(
float) * roi_out->
width *
ch);
696 for(
const GList *forms = grp->
points; (pos < 64) && forms; pos++, forms = g_list_next(forms))
725 const float *in = (
float *)
i;
726 float *
out = (
float *)
o;
731 const float *
const in,
float *
const out,
const dt_iop_roi_t *
const roi_in,
742 module->global_data = NULL;
743 module->params = calloc(1, sizeof(dt_iop_spots_params_t));
744 module->default_params = calloc(1, sizeof(dt_iop_spots_params_t));
747 module->default_enabled = 0;
748 module->params_size = sizeof(dt_iop_spots_params_t);
773 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
779 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
787 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_path),
FALSE);
788 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_circle),
FALSE);
789 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_ellipse),
FALSE);
790 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
824 gchar *str = g_strdup_printf(
"%d", nb);
825 gtk_label_set_text(
g->label, str);
839 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
844 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_edit_masks),
FALSE);
858 gtk_widget_set_tooltip_text(hbox, _(
"click on a shape and drag on canvas.\nuse the mouse wheel "
859 "to adjust size.\nright click to remove a shape."));
877 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(
g->label),
FALSE,
TRUE, 0);
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)
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_control_log(const char *msg,...)
void dt_control_queue_redraw_center()
Request a redraw of the centre view.
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_TRANSFORM_DIR_BACK_INCL
float dt_boundingbox_t[4]
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_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
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)
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)
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
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
int dt_masks_legacy_params(dt_develop_t *dev, void *params, const int old_version, const int new_version)
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)
void dt_masks_write_masks_history_item(const int32_t imgid, const int num, dt_masks_form_t *form)
int dt_masks_version(void)
dt_masks_form_t * dt_masks_create(dt_masks_type_t type)
void dt_masks_area_scale(dt_masks_area_t *area, const double scale)
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)
gboolean dt_masks_form_is_in_roi(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, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out)
void dt_masks_change_form_gui(dt_develop_t *dev, dt_masks_form_t *new_form)
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.
void dt_masks_gui_form_save_creation(dt_develop_t *develop, dt_iop_module_t *module, dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui)
Save the form creation right after a shape has been finished drawing.
The interactive half of the masks subsystem: the editing state (dt_masks_form_gui_t),...
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
static void * dt_calloc_align(size_t size)
dt_alloc_align() followed by a zero fill.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
#define __OMP_PARALLEL_FOR__(...)
#define dt_pixelpipe_cache_free_align(mem)
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...
void init(dt_iop_module_t *module)
const char ** description(struct dt_iop_module_t *self)
static int _process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const 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, const int ch)
int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const i, void *const o)
static gboolean _add_shape(GtkWidget *widget, dt_iop_module_t *self)
static void _resynch_params(struct dt_iop_module_t *self)
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)
void gui_update(dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
void distort_mask(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, 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 int _spots_clone_circle(const struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_masks_form_t *form, const _spots_buffers_t *buffers)
void gui_focus(struct dt_iop_module_t *self, gboolean in)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void gui_reset(struct dt_iop_module_t *self)
static gboolean _add_shape_callback(GtkWidget *widget, GdkEventButton *e, dt_iop_module_t *self)
void gui_init(dt_iop_module_t *self)
static int _spots_clone_mask(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, const float opacity, const _spots_buffers_t *buffers)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
static int _shape_is_being_added(dt_iop_module_t *self, const int shape_type)
static gboolean _reset_form_creation(GtkWidget *widget, dt_iop_module_t *self)
static __DT_CLONE_TARGETS__ void 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 _edit_masks(GtkWidget *widget, GdkEventButton *e, dt_iop_module_t *self)
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
struct dt_iop_spots_params_t dt_iop_spots_data_t
const char * deprecated_msg()
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)
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 _spots_blend_disc(const _spots_buffers_t *buffers, const float *const filter, const int rad, const int posx, const int posy, const int dx, const int dy)
const dt_iop_roi_t * roi_in
const dt_iop_roi_t * roi_out
struct dt_iop_module_t * gui_module
struct dt_masks_form_gui_t * form_gui
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
Region of interest passed through the pixelpipe.
GtkWidget * bt_edit_masks
#define __DT_CLONE_TARGETS__