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;
287 const float radius_sq = radius[0] * radius[0];
289 if((pointerx - startx) * (pointerx - startx) + pointery * pointery <= radius_sq)
return 2;
290 if(pointerx * pointerx + (pointery - starty) * (pointery - starty) <= radius_sq)
return 4;
291 if(pointerx * pointerx + pointery * pointery <= radius_sq)
return 1;
292 if((pointerx - endx) * (pointerx - endx) + pointery * pointery <= radius_sq)
return 8;
293 if(pointerx * pointerx + (pointery - endy) * (pointery - endy) <= radius_sq)
return 16;
298static void draw_overlay(cairo_t *cr,
float x,
float y,
float fx,
float fy,
int grab,
float zoom_scale)
305 cairo_move_to(cr, -crosshair_w, 0.0);
306 cairo_line_to(cr, crosshair_w, 0.0);
307 cairo_move_to(cr, 0.0, -crosshair_h);
308 cairo_line_to(cr, 0.0, crosshair_h);
315 cairo_scale(cr,
x / y, 1.0);
316 cairo_arc(cr, 0.0, 0.0, y, 0.0,
M_PI * 2.0);
320 cairo_scale(cr, 1.0, y /
x);
321 cairo_arc(cr, 0.0, 0.0,
x, 0.0,
M_PI * 2.0);
330 cairo_scale(cr,
fx / fy, 1.0);
331 cairo_arc(cr, 0.0, 0.0, fy, 0.0,
M_PI * 2.0);
335 cairo_scale(cr, 1.0, fy /
fx);
336 cairo_arc(cr, 0.0, 0.0,
fx, 0.0,
M_PI * 2.0);
345 cairo_arc(cr, 0.0, 0.0, radius_sel, 0.0,
M_PI * 2.0);
347 cairo_arc(cr, 0.0, 0.0, radius_reg, 0.0,
M_PI * 2.0);
350 cairo_arc(cr,
x, 0.0, radius_sel, 0.0,
M_PI * 2.0);
352 cairo_arc(cr,
x, 0.0, radius_reg, 0.0,
M_PI * 2.0);
355 cairo_arc(cr, 0.0, -y, radius_sel, 0.0,
M_PI * 2.0);
357 cairo_arc(cr, 0.0, -y, radius_reg, 0.0,
M_PI * 2.0);
360 cairo_arc(cr,
fx, 0.0, radius_sel, 0.0,
M_PI * 2.0);
362 cairo_arc(cr,
fx, 0.0, radius_reg, 0.0,
M_PI * 2.0);
365 cairo_arc(cr, 0.0, -fy, radius_sel, 0.0,
M_PI * 2.0);
367 cairo_arc(cr, 0.0, -fy, radius_reg, 0.0,
M_PI * 2.0);
374 int32_t pointerx, int32_t pointery)
383 float bigger_side, smaller_side;
395 float pzxpy[2] = { (float)pointerx, (
float)pointery };
397 const float pzx = pzxpy[0];
398 const float pzy = pzxpy[1];
401 float vignette_x = (
p->center.x + 1.0) * 0.5 * wd;
402 float vignette_y = (
p->center.y + 1.0) * 0.5 * ht;
404 cairo_translate(cr, vignette_x, vignette_y);
406 float vignette_w =
p->scale * 0.01 * 0.5 * wd;
407 float vignette_h =
p->scale * 0.01 * 0.5 * ht;
408 float vignette_fx = vignette_w +
p->falloff_scale * 0.01 * 0.5 * wd;
409 float vignette_fy = vignette_h +
p->falloff_scale * 0.01 * 0.5 * ht;
413 float factor1 = bigger_side / smaller_side;
416 float factor2 = (2.0 -
p->whratio) * factor1;
420 vignette_h *= factor1;
421 vignette_w *=
p->whratio;
422 vignette_fx *=
p->whratio;
423 vignette_fy *= factor1;
427 vignette_h *= factor2;
428 vignette_fy *= factor2;
433 float factor2 = (
p->whratio) * factor1;
437 vignette_w *= factor2;
438 vignette_fx *= factor2;
442 vignette_w *= factor1;
443 vignette_h *= (2.0 -
p->whratio);
444 vignette_fx *= factor1;
445 vignette_fy *= (2.0 -
p->whratio);
450 int grab =
get_grab(self, pzx * wd - vignette_x, pzy * ht - vignette_y, vignette_w, -vignette_h, vignette_fx,
451 -vignette_fy, zoom_scale);
452 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
455 draw_overlay(cr, vignette_w, vignette_h, vignette_fx, vignette_fy, grab, zoom_scale);
458 draw_overlay(cr, vignette_w, vignette_h, vignette_fx, vignette_fy, grab, zoom_scale);
470 float bigger_side, smaller_side;
483 float pzxpy[2] = { (float)
x, (
float)y };
485 const float pzx = pzxpy[0];
486 const float pzy = pzxpy[1];
487 static int old_grab = -1;
490 float vignette_x = (
p->center.x + 1.0) * 0.5 * wd;
491 float vignette_y = (
p->center.y + 1.0) * 0.5 * ht;
493 float vignette_w =
p->scale * 0.01 * 0.5 * wd;
494 float vignette_h =
p->scale * 0.01 * 0.5 * ht;
495 float vignette_fx = vignette_w +
p->falloff_scale * 0.01 * 0.5 * wd;
496 float vignette_fy = vignette_h +
p->falloff_scale * 0.01 * 0.5 * ht;
500 float factor1 = bigger_side / smaller_side;
503 float factor2 = (2.0 -
p->whratio) * factor1;
507 vignette_h *= factor1;
508 vignette_w *=
p->whratio;
509 vignette_fx *=
p->whratio;
510 vignette_fy *= factor1;
514 vignette_h *= factor2;
515 vignette_fy *= factor2;
520 float factor2 = (
p->whratio) * factor1;
524 vignette_w *= factor2;
525 vignette_fx *= factor2;
529 vignette_w *= factor1;
530 vignette_h *= (2.0 -
p->whratio);
531 vignette_fx *= factor1;
532 vignette_fy *= (2.0 -
p->whratio);
539 grab =
get_grab(self, pzx * wd - vignette_x, pzy * ht - vignette_y, vignette_w, -vignette_h, vignette_fx,
540 -vignette_fy, zoom_scale);
557 const float max = 0.5 * ((
p->whratio <= 1.0) ? bigger_side *
p->whratio : bigger_side);
558 const float new_vignette_w =
MIN(bigger_side,
MAX(0.1, pzx * wd - vignette_x));
559 const float ratio = new_vignette_w / vignette_h;
560 const float new_scale = 100.0 * new_vignette_w /
max;
581 float new_whratio = 2.0 - 1.0 / ratio;
588 const float new_vignette_h =
MIN(bigger_side,
MAX(0.1, vignette_y - pzy * ht));
589 const float ratio = new_vignette_h / vignette_w;
590 const float max = 0.5 * ((ratio <= 1.0) ? bigger_side * (2.0 -
p->whratio) : bigger_side);
598 const float new_scale = 100.0 * new_vignette_h /
max;
608 const float new_scale = 100.0 * new_vignette_h /
max;
613 const float new_whratio = 1.0 / ratio;
620 const float new_vignette_fx = pzx * wd - vignette_x;
621 const float max = 0.5 * ((
p->whratio <= 1.0) ? bigger_side *
p->whratio : bigger_side);
622 const float delta_x =
MIN(2.0f *
max,
MAX(0.0, new_vignette_fx - vignette_w));
623 const float new_falloff = 100.0 * delta_x /
max;
628 const float new_vignette_fy = vignette_y - pzy * ht;
629 const float max = 0.5 * ((
p->whratio > 1.0) ? bigger_side * (2.0 -
p->whratio) : bigger_side);
630 const float delta_y =
MIN(2.0f *
max,
MAX(0.0, new_vignette_fy - vignette_h));
631 const float new_falloff = 100.0 * delta_y /
max;
662 if(which == 1)
return 1;
668 if(which == 1)
return 1;
681 const gboolean unbound = data->
unbound;
690 = { vignette_center.
x * roi_in->
scale - roi_in->
x, vignette_center.
y * roi_in->
scale - roi_in->
y };
697 xscale = 2.0 / (buf_in->
width * roi_out->
scale);
707 xscale = yscale / data->
whratio;
714 yscale = xscale / (2.0 - data->
whratio);
717 const float dscale = data->
scale / 100.0;
719 const float min_falloff = 100.0 /
MIN(buf_in->
width, buf_in->
height);
721 const float shape =
MAX(data->
shape, 0.001);
722 const float exp1 = 2.0 / shape;
723 const float exp2 = shape / 2.0;
735 dither = 1.0f / 65536;
744 for(
int j = 0; j < roi_out->
height; j++)
746 const size_t k = (size_t)
ch * roi_out->
width * j;
747 const float *in = (
const float *)ivoid +
k;
750 tea_state[0] = j * roi_out->
height;
755 = { fabsf(
i * xscale - roi_center_scaled.
x), fabsf(j * yscale - roi_center_scaled.
y) };
758 const float cplen = powf(powf(pv.
x, exp1) + powf(pv.
y, exp1), exp2);
764 weight = ((cplen - dscale) / fscale);
769 else if(dither == 0.0f)
778 dith = dither *
tpdf(tea_state[0]);
783 float col0 = in[0], col1 = in[1], col2 = in[2], col3 = in[3];
789 col0 = data->
brightness < 0 ? col0 * falloff + dith : col0 + falloff + dith;
790 col1 = data->
brightness < 0 ? col1 * falloff + dith : col1 + falloff + dith;
791 col2 = data->
brightness < 0 ? col2 * falloff + dith : col2 + falloff + dith;
793 col0 = unbound ? col0 :
CLIP(col0);
794 col1 = unbound ? col1 :
CLIP(col1);
795 col2 = unbound ? col2 :
CLIP(col2);
798 float mv = (col0 + col1 + col2) / 3.0f;
800 col0 = col0 - ((mv - col0) * wss);
801 col1 = col1 - ((mv - col1) * wss);
802 col2 = col2 - ((mv - col2) * wss);
804 col0 = unbound ? col0 :
CLIP(col0);
805 col1 = unbound ? col1 :
CLIP(col1);
806 col2 = unbound ? col2 :
CLIP(col2);
830 const int devid = pipe->
devid;
843 = { vignette_center.
x * roi_in->
scale - roi_in->
x, vignette_center.
y * roi_in->
scale - roi_in->
y };
850 xscale = 2.0 / (buf_in->
width * roi_out->
scale);
860 xscale = yscale / data->
whratio;
867 yscale = xscale / (2.0 - data->
whratio);
870 const float dscale = data->
scale / 100.0;
872 const float min_falloff = 100.0 /
MIN(buf_in->
width, buf_in->
height);
874 const float shape =
MAX(data->
shape, 0.001);
875 const float exp1 = 2.0 / shape;
876 const float exp2 = shape / 2.0;
888 dither = 1.0f / 65536;
895 float scale[2] = { xscale, yscale };
896 float roi_center_scaled_f[2] = { roi_center_scaled.
x, roi_center_scaled.
y };
897 float expt[2] = { exp1, exp2 };
900 const int unbound = data->
unbound;
918 if(err != CL_SUCCESS)
goto error;
931 const int program = 8;
953 gtk_widget_set_sensitive(GTK_WIDGET(
g->whratio), !
p->autoratio);
962 d->falloff_scale =
p->falloff_scale;
963 d->brightness =
p->brightness;
964 d->saturation =
p->saturation;
965 d->center =
p->center;
966 d->autoratio =
p->autoratio;
967 d->whratio =
p->whratio;
969 d->dithering =
p->dithering;
970 d->unbound =
p->unbound;
978 p.falloff_scale = 100.0f;
979 p.brightness = -1.0f;
989 self->version(), &
p,
sizeof(
p), 1);
1010 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->autoratio),
p->autoratio);
1011 gtk_widget_set_sensitive(GTK_WIDGET(
g->whratio), !
p->autoratio);
1023 gtk_box_pack_start(GTK_BOX(self->
gui->
widget),
1042 gtk_widget_set_tooltip_text(
g->scale, _(
"the radii scale of vignette for start of fall-off"));
1043 gtk_widget_set_tooltip_text(
g->falloff_scale, _(
"the radii scale of vignette for end of fall-off"));
1044 gtk_widget_set_tooltip_text(
g->brightness, _(
"strength of effect on brightness"));
1045 gtk_widget_set_tooltip_text(
g->saturation, _(
"strength of effect on saturation"));
1046 gtk_widget_set_tooltip_text(
g->center_x, _(
"horizontal offset of center of the effect"));
1047 gtk_widget_set_tooltip_text(
g->center_y, _(
"vertical offset of center of the effect"));
1048 gtk_widget_set_tooltip_text(
g->shape, _(
"shape factor\n0 produces a rectangle\n1 produces a circle or ellipse\n"
1049 "2 produces a diamond"));
1050 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->autoratio), _(
"enable to have the ratio automatically follow the image size"));
1051 gtk_widget_set_tooltip_text(
g->whratio, _(
"width-to-height ratio"));
1052 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()
int32_t dt_dev_roi_request_preview_height(const dt_develop_t *dev)
int32_t dt_dev_roi_request_preview_width(const dt_develop_t *dev)
float dt_dev_viewport_scaling(const dt_develop_t *dev)
void dt_dev_coordinates_image_abs_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
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_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_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.
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)
_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_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
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 int get_grab(dt_iop_module_t *self, float pointerx, float pointery, float startx, float starty, float endx, float endy, float zoom_scale)
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)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void gui_update(struct dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
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)
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)
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 void draw_overlay(cairo_t *cr, float x, float y, float fx, float fy, int grab, float zoom_scale)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)