58 if(group_entry) *group_entry = entry;
77 double pressure,
int which,
int type, uint32_t
state,
94 gboolean return_value =
FALSE;
156 dt_show_times_f(&start,
"[masks]",
"shape %d (%s) drawn: %d outline points, %d border points, %d nodes",
159 g_list_length(selected_form->
points));
168 for(GList *fpts = form->
points; fpts; fpts = g_list_next(fpts), pos++)
175 if(pos < 0 || pos >= (
int)g_list_length(form->
points))
return;
185 for(GList *fpts = form->
points; fpts; fpts = g_list_next(fpts))
200 float **buffer,
int *
width,
int *
height,
int *posx,
int *posy)
203 const int wt = piece->
iwidth;
209 const int posx_ = *posx;
210 const int posy_ = *posy;
211 const int width_ = *
width;
212 const int height_ = *
height;
213 const float *
const src = *buffer;
215 for(
int yy = 0; yy <
MIN(posy_, ht); yy++)
217 float *
const row = buf + (size_t)yy * wt;
218 for(
int xx = 0; xx < wt; xx++)
row[xx] = 1.0f;
221 for(
int yy =
MAX(posy_, 0); yy <
MIN(ht, posy_ + height_); yy++)
223 float *
const row = buf + (size_t)yy * wt;
224 for(
int xx = 0; xx <
MIN(posx_, wt); xx++)
row[xx] = 1.0f;
225 const int xstart =
MAX(posx_, 0);
226 const int xend =
MIN(wt, posx_ + width_);
227 const float *
const src_row = src + (size_t)(yy - posy_) * width_;
228 for(
int xx = xstart; xx < xend; xx++)
229 row[xx] = 1.0f - src_row[xx - posx_];
230 for(
int xx =
MAX(posx_ + width_, 0); xx < wt; xx++)
row[xx] = 1.0f;
233 for(
int yy =
MAX(posy_ + height_, 0); yy < ht; yy++)
235 float *
const row = buf + (size_t)yy * wt;
236 for(
int xx = 0; xx < wt; xx++)
row[xx] = 1.0f;
253 float **buffer,
int *
width,
int *
height,
int *posx,
int *posy)
262 const guint nb = g_list_length(form->
points);
291 for(GList *fpts = form->
points; fpts; fpts = g_list_next(fpts))
298 =
dt_masks_get_mask(module, pipe, piece, sel, &bufs[nb_ok], &w[nb_ok], &h[nb_ok],
299 &px[nb_ok], &py[nb_ok]);
312 if(
_inverse_mask(module, piece, sel, &bufs[nb_ok], &w[nb_ok], &h[nb_ok], &px[nb_ok], &py[nb_ok]) != 0)
321 states[nb_ok] = fpt->
state;
337 int l = INT_MAX,
r = INT_MIN,
t = INT_MAX, b = INT_MIN;
338 for(
int i = 0;
i < nb_ok;
i++)
343 b =
MAX(b, py[
i] + h[
i]);
359 const int dst_w =
r - l;
360 const int dst_h = b -
t;
361 float *
const dst = *buffer;
362 for(
int i = 0;
i < nb_ok;
i++)
367 const int ox = px[
i] - l;
368 const int oy = py[
i] -
t;
370 const float *
const src = bufs[
i];
374 for(
int y = 0; y < hi; y++)
376 float *
const dst_row = dst + (size_t)(oy + y) * dst_w + ox;
377 const float *
const src_row = src + (size_t)y * wi;
378 for(
int x = 0;
x < wi;
x++)
381 if(
v > dst_row[
x]) dst_row[
x] =
v;
387 const int x0 =
MAX(px[
i], l);
388 const int y0 =
MAX(py[
i],
t);
389 const int x1 =
MIN(px[
i] + wi,
r);
390 const int y1 =
MIN(py[
i] + hi, b);
391 if(x0 >= x1 || y0 >= y1)
393 memset(dst, 0, (
size_t)dst_w * dst_h *
sizeof(
float));
397 const int row_start = y0 -
t;
398 const int row_end = y1 -
t;
399 const int col_start = x0 - l;
400 const int col_end = x1 - l;
401 const int src_x_offset = x0 - px[
i];
402 const int src_y_offset =
t - py[
i];
404 for(
int y = 0; y < dst_h; y++)
406 float *
const dst_row = dst + (size_t)y * dst_w;
407 if(y < row_start || y >= row_end)
409 memset(dst_row, 0, (
size_t)dst_w *
sizeof(
float));
413 const int src_y = y + src_y_offset;
414 const float *
const src_row = src + (size_t)src_y * wi + src_x_offset;
415 float *
const dst_mid = dst_row + col_start;
416 const int mid_w = col_end - col_start;
417 for(
int x = 0;
x < mid_w;
x++)
419 const float b1 = dst_mid[
x];
420 const float b2 = src_row[
x];
421 if(b1 > 0.0f && b2 > 0.0f)
422 dst_mid[
x] = fminf(b1, b2 *
opacity);
427 if(col_start > 0) memset(dst_row, 0, (
size_t)col_start *
sizeof(
float));
428 if(col_end < dst_w) memset(dst_row + col_end, 0, (
size_t)(dst_w - col_end) *
sizeof(
float));
435 for(
int y = 0; y < hi; y++)
437 float *
const dst_row = dst + (size_t)(oy + y) * dst_w + ox;
438 const float *
const src_row = src + (size_t)y * wi;
439 for(
int x = 0;
x < wi;
x++)
441 const float b1 = dst_row[
x];
442 const float b2 = src_row[
x] *
opacity;
443 if(b1 > 0.0f && b2 > 0.0f) dst_row[
x] = b1 * (1.0f - b2);
450 for(
int y = 0; y < hi; y++)
452 float *
const dst_row = dst + (size_t)(oy + y) * dst_w + ox;
453 const float *
const src_row = src + (size_t)y * wi;
454 for(
int x = 0;
x < wi;
x++)
456 const float b1 = dst_row[
x];
457 const float b2 = src_row[
x] *
opacity;
458 if(b1 > 0.0f && b2 > 0.0f)
459 dst_row[
x] = fmaxf((1.0f - b1) * b2, b1 * (1.0f - b2));
461 dst_row[
x] = fmaxf(dst_row[
x], b2);
467 const int x0 =
MAX(px[
i], l);
468 const int y0 =
MAX(py[
i],
t);
469 const int x1 =
MIN(px[
i] + wi,
r);
470 const int y1 =
MIN(py[
i] + hi, b);
471 if(x0 >= x1 || y0 >= y1)
473 memset(dst, 0, (
size_t)dst_w * dst_h *
sizeof(
float));
477 const int row_start = y0 -
t;
478 const int row_end = y1 -
t;
479 const int col_start = x0 - l;
480 const int col_end = x1 - l;
481 const int src_x_offset = x0 - px[
i];
482 const int src_y_offset =
t - py[
i];
484 for(
int y = 0; y < dst_h; y++)
486 float *
const dst_row = dst + (size_t)y * dst_w;
487 if(y < row_start || y >= row_end)
489 memset(dst_row, 0, (
size_t)dst_w *
sizeof(
float));
493 const int src_y = y + src_y_offset;
494 const float *
const src_row = src + (size_t)src_y * wi + src_x_offset;
495 float *
const dst_mid = dst_row + col_start;
496 const int mid_w = col_end - col_start;
497 for(
int x = 0;
x < mid_w;
x++)
502 if(col_start > 0) memset(dst_row, 0, (
size_t)col_start *
sizeof(
float));
503 if(col_end < dst_w) memset(dst_row + col_end, 0, (
size_t)(dst_w - col_end) *
sizeof(
float));
524static void _combine_masks_union(
float *
const restrict dest,
float *
const restrict newmask,
const size_t npixels,
525 const float opacity,
const int inverted)
530 for(
int index = 0; index < npixels; index++)
532 const float mask =
opacity * (1.0f - newmask[index]);
533 dest[index] =
MAX(dest[index], mask);
539 for(
int index = 0; index < npixels; index++)
541 const float mask =
opacity * newmask[index];
542 dest[index] =
MAX(dest[index], mask);
551 for(
int y = box->
y; y < box->
y + box->
height; y++)
553 float *
const restrict dest_row = dest + (size_t)y *
width + box->
x;
554 const float *
const restrict src_row = newmask + (size_t)y *
width + box->
x;
557 const float mask =
opacity * src_row[
x];
558 dest_row[
x] =
MAX(dest_row[
x], mask);
564 const float opacity,
const int inverted)
569 for(
int index = 0; index < npixels; index++)
571 const float mask =
opacity * (1.0f - newmask[index]);
572 dest[index] =
MIN(
MAX(dest[index], 0.0f),
MAX(mask, 0.0f));
578 for(
int index = 0; index < npixels; index++)
580 const float mask =
opacity * newmask[index];
581 dest[index] =
MIN(
MAX(dest[index], 0.0f),
MAX(mask, 0.0f));
590 return (val1 > 0.0f) && (val2 > 0.0f);
594 const float opacity,
const int inverted)
599 for(
int index = 0; index < npixels; index++)
601 const float mask =
opacity * (1.0f - newmask[index]);
602 dest[index] *= (1.0f - mask *
both_positive(dest[index],mask));
609 for(
int index = 0; index < npixels; index++)
611 const float mask =
opacity * newmask[index];
612 dest[index] *= (1.0f - mask *
both_positive(dest[index],mask));
618 const float opacity,
const int inverted)
624 for(
int index = 0; index < npixels; index++)
626 const float mask =
opacity * (1.0f - newmask[index]);
628 const float neg = (1.0f - pos);
629 const float b1 = dest[index];
630 dest[index] = pos *
MAX((1.0f - b1) * mask, b1 * (1.0f - mask)) + neg *
MAX(b1, mask);
636 for(
int index = 0; index < npixels; index++)
638 const float mask =
opacity * newmask[index];
640 const float neg = (1.0f - pos);
641 const float b1 = dest[index];
642 dest[index] = pos *
MAX((1.0f - b1) * mask, b1 * (1.0f - mask)) + neg *
MAX(b1, mask);
680 for(
const GList *fpts = form->
points; fpts &&
i < count; fpts = g_list_next(fpts),
i++)
686 hash =
dt_hash(hash, (
const char *)&fpt->
state,
sizeof(
int));
690 return hash ? hash : 1;
720 const int shape_count = g_list_length(form->
points);
723 for(
int count = shape_count - 1; count > 0; count--)
726 if(prefix == 0)
break;
733 memcpy(buffer, cached, npixels *
sizeof(
float));
752 float *publishable = NULL;
753 if(shape_count > 1 && resume_from < shape_count - 1)
756 if(resume_from == 0) memset(buffer, 0, npixels *
sizeof(
float));
757 gboolean bufs_zeroed =
FALSE;
766 for(GList *fpts = form->
points; fpts; fpts = g_list_next(fpts))
771 if(sel &&
i < resume_from)
783 memcpy(publishable, buffer, npixels *
sizeof(
float));
789 memset(bufs, 0, npixels *
sizeof(
float));
799 const int state = (
i == 0) ? no_op_state : fpt->
state;
853 if(
i != 0) memset(buffer, 0, npixels *
sizeof(
float));
854 for(
int y = child_touched.
y; y < child_touched.
y + child_touched.
height; y++)
856 float *
const restrict dest_row = buffer + (size_t)y *
width + child_touched.
x;
857 const float *
const restrict src_row = bufs + (size_t)y *
width + child_touched.
x;
858 for(
int x = 0;
x < child_touched.
width;
x++) dest_row[
x] = op * src_row[
x];
864 for(
int index = 0; index < npixels; index++)
866 buffer[index] = op * (inverted ? (1.0f - bufs[index]) : bufs[index]);
873 group_touched = child_touched;
891 memset(buffer, 0, npixels *
sizeof(
float));
893 *touched = group_touched;
911 if(err ==
DT_MASKS_RASTER_OK && shape_count > 1 && nb_ok == shape_count && resume_from < shape_count - 1
925 memcpy(slot, publishable, npixels *
sizeof(
float));
955 for(GList *pts = base->
points; pts; pts = g_list_next(pts))
977 for(
const GList *l = form->
points; l; l = g_list_next(l))
984 float child_center[2] = { 0.0f, 0.0f };
985 float child_area = 0.0f;
988 const float w = (child_area > 0.0f) ? child_area : 1.0f;
989 sum_x += child_center[0] * w;
990 sum_y += child_center[1] * w;
1005 center[0] = sum_x / (float)count;
1006 center[1] = sum_y / (float)count;
1011 center[0] = sum_x / sum_w;
1012 center[1] = sum_y / sum_w;
1022 .sanitize_config = NULL,
1023 .set_form_name = NULL,
1024 .set_hint_message = NULL,
1026 .initial_source_pos = NULL,
1027 .get_distance = NULL,
1029 .get_points_border = NULL,
1033 .get_source_area = NULL,
1035 .get_interaction_value = NULL,
1036 .set_interaction_value = NULL,
1037 .update_hover = NULL,
void cleanup(dt_imageio_module_format_t *self)
void * dt_alloc_align(size_t size)
Allocate cacheline-aligned memory.
static guint dt_keys_mainpad_alternatives(const guint key_val)
Remap keypad keys to usual mainpad ones.
static int _group_events_mouse_moved(struct dt_iop_module_t *module, double x, double y, double pressure, int which, dt_masks_form_t *form, int unused1, dt_masks_form_gui_t *gui, int unused2)
static uint64_t _group_prefix_hash(const dt_masks_form_t *const form, GList *masks, const dt_dev_pixelpipe_iop_t *const piece, const dt_iop_roi_t *const roi, const int count)
Identity of the group mask after folding the first count shapes, at this ROI.
static dt_masks_raster_result_t _group_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)
static int _group_events_key_pressed(struct dt_iop_module_t *module, GdkEventKey *event, dt_masks_form_t *form, int parentid, dt_masks_form_gui_t *gui, int index)
static int _group_events_button_released(struct dt_iop_module_t *module, double x, double y, int which, uint32_t state, dt_masks_form_t *form, int unused1, dt_masks_form_gui_t *gui, int unused2)
static void _group_duplicate_points(dt_develop_t *const dev, dt_masks_form_t *const base, dt_masks_form_t *const dest)
static void _combine_masks_union_box(float *const restrict dest, const float *const restrict newmask, const int width, const dt_iop_roi_t *const box, const float opacity)
const dt_masks_functions_t dt_masks_functions_group
void dt_group_events_post_expose_except(cairo_t *cr, float zoom_scale, dt_masks_form_t *form, dt_masks_form_gui_t *gui, const int except_pos)
static void _group_events_post_expose_draw(cairo_t *cr, float zoom_scale, dt_masks_form_t *form, dt_masks_form_gui_t *gui, int pos)
dt_masks_raster_result_t dt_masks_group_render_roi(dt_iop_module_t *module, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, const dt_iop_roi_t *roi, float *buffer)
static void _combine_masks_union(float *const restrict dest, float *const restrict newmask, const size_t npixels, const float opacity, const int inverted)
static void _combine_masks_exclusion(float *const restrict dest, float *const restrict newmask, const size_t npixels, const float opacity, const int inverted)
static gboolean _group_events_button_pressed(struct dt_iop_module_t *module, double x, double y, double pressure, int which, int type, uint32_t state, dt_masks_form_t *form, int unused1, dt_masks_form_gui_t *gui, int unused2)
void dt_group_events_post_expose_only(cairo_t *cr, float zoom_scale, dt_masks_form_t *form, dt_masks_form_gui_t *gui, const int pos)
static gboolean _group_get_gravity_center(dt_develop_t *dev, const dt_masks_form_t *form, float center[2], float *area)
static void _combine_masks_difference(float *const restrict dest, float *const restrict newmask, const size_t npixels, const float opacity, const int inverted)
static int _inverse_mask(const dt_iop_module_t *const module, const dt_dev_pixelpipe_iop_t *const piece, dt_masks_form_t *const form, float **buffer, int *width, int *height, int *posx, int *posy)
static int both_positive(const float val1, const float val2)
static dt_masks_raster_result_t _group_get_mask_roi(const dt_iop_module_t *const restrict module, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *const restrict piece, dt_masks_form_t *const form, const dt_iop_roi_t *const roi, float *const restrict buffer, dt_iop_roi_t *touched)
static dt_masks_form_t * _group_get_selected_child(dt_masks_form_t *form, dt_masks_form_gui_t *gui, dt_masks_form_group_t **group_entry)
static dt_masks_form_t * _group_get_child_at(dt_develop_t *dev, dt_masks_form_t *form, const int group_index, dt_masks_form_group_t **group_entry)
void dt_group_events_post_expose(cairo_t *cr, float zoom_scale, dt_masks_form_t *form, dt_masks_form_gui_t *gui)
static void _combine_masks_intersect(float *const restrict dest, float *const restrict newmask, const size_t npixels, const float opacity, const int inverted)
static int _group_events_mouse_scrolled(struct dt_iop_module_t *module, double x, double y, int up, const int flow, uint32_t state, dt_masks_form_t *form, int unused1, dt_masks_form_gui_t *gui, int unused, dt_masks_interaction_t interaction)
static uint64_t dt_hash(uint64_t hash, const char *str, size_t size)
_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.
#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_raster_result_t dt_masks_get_mask_roi(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, const dt_iop_roi_t *roi, float *buffer, dt_iop_roi_t *touched)
dt_masks_raster_result_t 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)
dt_masks_raster_result_t
What a rasterisation attempt produced.
uint64_t dt_masks_form_get_own_hash(uint64_t hash, GList *masks, const dt_masks_form_t *form)
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)
int dt_masks_form_duplicate(dt_develop_t *dev, int formid)
The per-shape function table, private to the masks implementation.
gboolean dt_masks_form_get_gravity_center(dt_develop_t *dev, const dt_masks_form_t *mask_form, float center[2], float *area)
gboolean dt_masks_gui_remove(struct dt_iop_module_t *module, dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, const int parent_id)
remove a mask shape or node form from the GUI. This function is used with a popupmenu "Delete" action...
gboolean dt_masks_form_exit_creation(dt_iop_module_t *module, dt_masks_form_gui_t *mask_gui)
The interactive half of the masks subsystem: the editing state (dt_masks_form_gui_t),...
static int dt_masks_touched_is_empty(const dt_iop_roi_t *touched)
static void dt_masks_touched_full(dt_iop_roi_t *touched, const int width, const int height)
static void dt_masks_touched_clear(float *const buffer, const int width, const dt_iop_roi_t *touched)
static void dt_masks_touched_none(dt_iop_roi_t *touched)
static void dt_masks_touched_union(dt_iop_roi_t *into, const dt_iop_roi_t *other)
@ DT_MASKS_STATE_DIFFERENCE
@ DT_MASKS_STATE_INTERSECTION
@ DT_MASKS_STATE_IS_COMBINE_OP
@ DT_MASKS_STATE_EXCLUSION
#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.
static float * dt_alloc_align_float(size_t pixels)
Allocate pixels floats, cacheline-aligned and marked as such.
#define __OMP_DECLARE_SIMD__(...)
#define __OMP_PARALLEL_FOR__(...)
#define __OMP_FOR_SIMD__(...)
#define __OMP_PARALLEL_FOR_SIMD__(...)
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)
Increase/Decrease the reference count on the cache line as to prevent LRU item removal....
gboolean dt_dev_pixelpipe_cache_peek(const uint64_t hash, void **data, dt_pixel_cache_entry_t **entry, const int preferred_devid, void **cl_mem_output)
Non-owning lookup of an existing cache line.
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.
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
const float uint32_t state[4]
unsigned __int64 uint64_t
dt_dev_pixelpipe_type_t type
struct dt_develop_t * dev
Region of interest passed through the pixelpipe.
void(* post_expose)(cairo_t *cr, float zoom_scale, struct dt_masks_form_gui_t *gui, int index, int num_points)
static void dt_get_times(dt_times_t *t)
static double dt_get_wtime(void)
void dt_show_times_f(const dt_times_t *start, const char *prefix, const char *suffix,...) __attribute__((format(printf