192 return _(
"_Vignetting");
199 _(
"non-linear, RGB, display-referred"),
200 _(
"non-linear, RGB"),
201 _(
"non-linear, RGB, display-referred"));
221 void *new_params,
const int new_version)
223 if(old_version == 1 && new_version == 4)
235 new->autoratio =
TRUE;
239 new->unbound =
FALSE;
242 if(old_version == 2 && new_version == 4)
254 new->shape = old->
shape;
256 new->unbound =
FALSE;
259 if(old_version == 3 && new_version == 4)
271 new->shape = old->
shape;
273 new->unbound =
FALSE;
298#define VIGNETTE_OUTLINE_SAMPLES 128
310 geo->
cx = (
p->center.x + 1.0f) * 0.5f * geo->
width;
311 geo->
cy = (
p->center.y + 1.0f) * 0.5f * geo->
height;
318 half_x = 0.5f * geo->
width;
319 half_y = 0.5f * geo->
height;
321 else if(
p->whratio <= 1.0f)
323 half_x = 0.5f * geo->
longest *
p->whratio;
329 half_y = 0.5f * geo->
longest * (2.0f -
p->whratio);
332 const float dscale =
p->scale / 100.0f;
334 const float fscale =
MAX(
p->falloff_scale, min_falloff) / 100.0f;
335 geo->
rx = dscale * half_x;
336 geo->
ry = dscale * half_y;
337 geo->
frx = (dscale + fscale) * half_x;
338 geo->
fry = (dscale + fscale) * half_y;
363 pts[0] = geo->
cx; pts[1] = geo->
cy;
364 pts[2] = geo->
cx + geo->
rx; pts[3] = geo->
cy;
365 pts[4] = geo->
cx; pts[5] = geo->
cy - geo->
ry;
366 pts[6] = geo->
cx + geo->
frx; pts[7] = geo->
cy;
367 pts[8] = geo->
cx; pts[9] = geo->
cy - geo->
fry;
379 float pointer[2] = { (float)
x, (
float)y };
384 const float radius_sq = radius * radius;
386 static const int order[5] = { 1, 2, 0, 3, 4 };
387 for(
int k = 0;
k < 5;
k++)
389 const int i = order[
k];
390 const float dx = pointer[0] - handles[2 *
i];
391 const float dy = pointer[1] - handles[2 *
i + 1];
392 if(dx * dx + dy * dy <= radius_sq)
return 1 <<
i;
404 const float c = cosf(
t);
405 const float s = sinf(
t);
406 pts[2 *
i] = geo->
cx + rx * copysignf(powf(fabsf(c), geo->
shape), c);
407 pts[2 *
i + 1] = geo->
cy + ry * copysignf(powf(fabsf(s), geo->
shape), s);
413 cairo_move_to(cr, pts[0], pts[1]);
414 for(
int i = 1;
i < count;
i++) cairo_line_to(cr, pts[2 *
i], pts[2 *
i + 1]);
415 cairo_close_path(cr);
419static void _draw_overlay(cairo_t *cr,
const float *inner,
const float *outer,
const float *handles,
420 const int grab,
const float zoom_scale)
424 cairo_move_to(cr, handles[0] - crosshair, handles[1]);
425 cairo_line_to(cr, handles[0] + crosshair, handles[1]);
426 cairo_move_to(cr, handles[0], handles[1] - crosshair);
427 cairo_line_to(cr, handles[0], handles[1] + crosshair);
435 for(
int i = 0;
i < 5;
i++)
437 cairo_new_sub_path(cr);
438 cairo_arc(cr, handles[2 *
i], handles[2 *
i + 1], (grab == (1 <<
i)) ? radius_sel : radius_reg, 0.0,
445 int32_t pointerx, int32_t pointery)
469 const int grab =
_get_grab(self, &geo, pointerx, pointery);
473 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
474 cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
492 const float longest = geo.
longest;
494 static int old_grab = -1;
510 const float mx = pointer[0];
511 const float my = pointer[1];
520 const float max = 0.5f * ((
p->whratio <= 1.0f) ? longest *
p->whratio : longest);
521 const float new_vignette_w =
MIN(longest,
MAX(0.1f, mx - geo.
cx));
522 const float ratio = new_vignette_w / geo.
ry;
523 const float new_scale = 100.0f * new_vignette_w /
max;
543 const float new_vignette_h =
MIN(longest,
MAX(0.1f, geo.
cy - my));
544 const float ratio = new_vignette_h / geo.
rx;
545 const float max = 0.5f * ((ratio <= 1.0f) ? longest * (2.0f -
p->whratio) : longest);
565 const float max = 0.5f * ((
p->whratio <= 1.0f) ? longest *
p->whratio : longest);
566 const float delta_x =
MIN(2.0f *
max,
MAX(0.0f, mx - geo.
cx - geo.
rx));
571 const float max = 0.5f * ((
p->whratio > 1.0f) ? longest * (2.0f -
p->whratio) : longest);
572 const float delta_y =
MIN(2.0f *
max,
MAX(0.0f, geo.
cy - my - geo.
ry));
582 else if(grab == 2 || grab == 8)
584 else if(grab == 4 || grab == 16)
599 if(which == 1)
return 1;
605 if(which == 1)
return 1;
617 const size_t ch =
piece->dsc_in.channels;
618 const gboolean unbound = data->
unbound;
627 = { vignette_center.
x * roi_in->
scale - roi_in->
x, vignette_center.
y * roi_in->
scale - roi_in->
y };
634 xscale = 2.0 / (buf_in->
width * roi_out->
scale);
644 xscale = yscale / data->
whratio;
651 yscale = xscale / (2.0 - data->
whratio);
654 const float dscale = data->
scale / 100.0;
656 const float min_falloff = 100.0 /
MIN(buf_in->
width, buf_in->
height);
658 const float shape =
MAX(data->
shape, 0.001);
659 const float exp1 = 2.0 / shape;
660 const float exp2 = shape / 2.0;
672 dither = 1.0f / 65536;
681 for(
int j = 0; j < roi_out->
height; j++)
683 const size_t k = (size_t)
ch * roi_out->
width * j;
684 const float *in = (
const float *)ivoid +
k;
687 tea_state[0] = j * roi_out->
height;
692 = { fabsf(
i * xscale - roi_center_scaled.
x), fabsf(j * yscale - roi_center_scaled.
y) };
695 const float cplen = powf(powf(pv.
x, exp1) + powf(pv.
y, exp1), exp2);
701 weight = ((cplen - dscale) / fscale);
706 else if(dither == 0.0f)
715 dith = dither *
tpdf(tea_state[0]);
720 float col0 = in[0], col1 = in[1], col2 = in[2], col3 = in[3];
726 col0 = data->
brightness < 0 ? col0 * falloff + dith : col0 + falloff + dith;
727 col1 = data->
brightness < 0 ? col1 * falloff + dith : col1 + falloff + dith;
728 col2 = data->
brightness < 0 ? col2 * falloff + dith : col2 + falloff + dith;
730 col0 = unbound ? col0 :
CLIP(col0);
731 col1 = unbound ? col1 :
CLIP(col1);
732 col2 = unbound ? col2 :
CLIP(col2);
735 float mv = (col0 + col1 + col2) / 3.0f;
737 col0 = col0 - ((mv - col0) * wss);
738 col1 = col1 - ((mv - col1) * wss);
739 col2 = col2 - ((mv - col2) * wss);
741 col0 = unbound ? col0 :
CLIP(col0);
742 col1 = unbound ? col1 :
CLIP(col1);
743 col2 = unbound ? col2 :
CLIP(col2);
780 = { vignette_center.
x * roi_in->
scale - roi_in->
x, vignette_center.
y * roi_in->
scale - roi_in->
y };
787 xscale = 2.0 / (buf_in->
width * roi_out->
scale);
797 xscale = yscale / data->
whratio;
804 yscale = xscale / (2.0 - data->
whratio);
807 const float dscale = data->
scale / 100.0;
809 const float min_falloff = 100.0 /
MIN(buf_in->
width, buf_in->
height);
811 const float shape =
MAX(data->
shape, 0.001);
812 const float exp1 = 2.0 / shape;
813 const float exp2 = shape / 2.0;
825 dither = 1.0f / 65536;
832 float scale[2] = { xscale, yscale };
833 float roi_center_scaled_f[2] = { roi_center_scaled.
x, roi_center_scaled.
y };
834 float expt[2] = { exp1, exp2 };
837 const int unbound = data->
unbound;
855 if(err != CL_SUCCESS)
goto error;
868 const int program = 8;
890 gtk_widget_set_sensitive(GTK_WIDGET(
g->whratio), !
p->autoratio);
899 d->falloff_scale =
p->falloff_scale;
900 d->brightness =
p->brightness;
901 d->saturation =
p->saturation;
902 d->center =
p->center;
903 d->autoratio =
p->autoratio;
904 d->whratio =
p->whratio;
906 d->dithering =
p->dithering;
907 d->unbound =
p->unbound;
915 p.falloff_scale = 100.0f;
916 p.brightness = -1.0f;
926 self->version(), &
p,
sizeof(
p), 1);
947 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->autoratio),
p->autoratio);
948 gtk_widget_set_sensitive(GTK_WIDGET(
g->whratio), !
p->autoratio);
960 gtk_box_pack_start(GTK_BOX(self->
gui->
widget),
979 gtk_widget_set_tooltip_text(
g->scale, _(
"the radii scale of vignette for start of fall-off"));
980 gtk_widget_set_tooltip_text(
g->falloff_scale, _(
"the radii scale of vignette for end of fall-off"));
981 gtk_widget_set_tooltip_text(
g->brightness, _(
"strength of effect on brightness"));
982 gtk_widget_set_tooltip_text(
g->saturation, _(
"strength of effect on saturation"));
983 gtk_widget_set_tooltip_text(
g->center_x, _(
"horizontal offset of center of the effect"));
984 gtk_widget_set_tooltip_text(
g->center_y, _(
"vertical offset of center of the effect"));
985 gtk_widget_set_tooltip_text(
g->shape, _(
"shape factor\n0 produces a rectangle\n1 produces a circle or ellipse\n"
986 "2 produces a diamond"));
987 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->autoratio), _(
"enable to have the ratio automatically follow the image size"));
988 gtk_widget_set_tooltip_text(
g->whratio, _(
"width-to-height ratio"));
989 gtk_widget_set_tooltip_text(
g->dithering, _(
"add some level of random noise to prevent banding"));
Handle default and user-set shortcuts (accelerators)
static void error(char *msg)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_control_queue_redraw_center()
Request a redraw of the centre view.
gboolean dt_control_button_down(int which)
Is mouse button which currently held down?
#define dt_control_queue_cursor(cursor)
int dt_get_num_openmp_threads(void)
Number of OpenMP threads the application decided to use.
#define dt_database_start_transaction()
#define dt_database_release_transaction()
void dt_dev_coordinates_image_abs_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
int dt_dev_distort_backtransform_gui(dt_develop_t *dev, const double iop_order, const int transf_direction, float *points, size_t points_count)
The inverse of dt_dev_distort_transform_gui(), same rules.
float dt_dev_get_overlay_scale(dt_develop_t *dev)
Get the overlay scale factor in GUI logical coordinates.
void dt_dev_coordinates_image_norm_to_preview_abs(dt_develop_t *dev, float *points, size_t num_points)
gboolean dt_dev_module_geometry_gui(dt_develop_t *dev, dt_iop_module_t *module, dt_iop_roi_t *in, dt_iop_roi_t *out)
One module's own input and output rectangles at full resolution, from the geometry service.
int dt_dev_distort_transform_gui(dt_develop_t *dev, const double iop_order, const int transf_direction, float *points, size_t points_count)
The GUI's bounded transform folds, composed by the geometry service.
gboolean dt_dev_rescale_roi(dt_develop_t *dev, cairo_t *cr, int32_t width, int32_t height)
Scale the ROI to fit within given width/height, centered.
void dt_dev_coordinates_image_norm_to_image_abs(dt_develop_t *dev, float *points, size_t num_points)
void dt_dev_coordinates_widget_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
Coordinate conversion helpers between widget, normalized image, and absolute image spaces.
@ DT_DEV_TRANSFORM_DIR_FORW_EXCL
static void dt_draw_set_color_overlay(cairo_t *cr, gboolean bright, double alpha)
static void weight(const float *c1, const float *c2, const float sharpen, dt_aligned_pixel_t weight)
void dt_gui_presets_add_generic(const char *name, dt_dev_operation_t op, const int32_t version, const void *params, const int32_t params_size, const int32_t enabled)
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)
@ IOP_FLAGS_INCLUDE_IN_STYLES
@ IOP_FLAGS_SUPPORTS_BLENDING
@ IOP_FLAGS_TILING_FULL_ROI
GtkWidget * dt_bauhaus_toggle_from_params(dt_iop_module_t *self, const char *param)
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)
GtkWidget * dt_ui_section_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
_lib_location_type_t type
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 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...
#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.
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
int dt_opencl_create_kernel(const int prog, const char *name)
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)
static int dt_get_thread_num()
Index of the calling thread within its parallel region, 0 outside one.
#define __OMP_PARALLEL_FOR__(...)
const float uint32_t state[4]
dt_iop_global_data_t * data
struct dt_iop_module_gui_t * gui
struct dt_develop_t * dev
dt_iop_global_data_t * global_data
Region of interest passed through the pixelpipe.
dt_iop_vector_2d_t center
GtkWidget * falloff_scale
dt_iop_dvector_2d_t center
gboolean invert_saturation
dt_iop_vector_2d_t center
dt_iop_vector_2d_t center
dt_iop_dither_t dithering
dt_iop_vector_2d_t center
#define __DT_CLONE_TARGETS__
static float tpdf(unsigned int urandom)
static unsigned int * get_tea_state(unsigned int *const states, int threadnum)
static void free_tea_states(unsigned int *states)
static unsigned int * alloc_tea_states(size_t numthreads)
static void encrypt_tea(unsigned int *arg)
static void _vignette_handles(const dt_iop_vignette_geometry_t *geo, float pts[10])
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
const char ** description(struct dt_iop_module_t *self)
__DT_CLONE_TARGETS__ 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 _widget_to_module(dt_iop_module_t *self, const double x, const double y, float pt[2])
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void _outline_sample(const dt_iop_vignette_geometry_t *geo, const float rx, const float ry, float *pts)
void gui_update(struct dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
static gboolean _vignette_geometry(dt_iop_module_t *self, const dt_iop_vignette_params_t *p, dt_iop_vignette_geometry_t *geo)
void gui_init(struct dt_iop_module_t *self)
int button_pressed(struct dt_iop_module_t *self, double x, double y, double pressure, int which, int type, uint32_t state)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
int button_released(struct dt_iop_module_t *self, double x, double y, int which, uint32_t state)
#define VIGNETTE_OUTLINE_SAMPLES
void cleanup_global(dt_iop_module_so_t *module)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
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 _draw_overlay(cairo_t *cr, const float *inner, const float *outer, const float *handles, const int grab, const float zoom_scale)
void init_presets(dt_iop_module_so_t *self)
struct dt_iop_fvector_2d_t dt_iop_vector_2d_t
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void init_global(dt_iop_module_so_t *module)
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)
int mouse_moved(struct dt_iop_module_t *self, double x, double y, double pressure, int which)
static gboolean _module_to_image_abs(dt_iop_module_t *self, float *pts, const size_t count)
static int _get_grab(dt_iop_module_t *self, const dt_iop_vignette_geometry_t *geo, const double x, const double y)
static void _draw_closed_path(cairo_t *cr, const float *pts, const int count)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)