Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
vignette.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010 Alexandre Prokoudine.
4 Copyright (C) 2010-2011 Bruce Guenter.
5 Copyright (C) 2010-2011 Henrik Andersson.
6 Copyright (C) 2010-2013, 2016, 2018 johannes hanika.
7 Copyright (C) 2010 Stuart Henderson.
8 Copyright (C) 2011 Antony Dovgal.
9 Copyright (C) 2011 Jérémy Rosen.
10 Copyright (C) 2011 Olivier Tribout.
11 Copyright (C) 2011 Robert Bieber.
12 Copyright (C) 2011-2014, 2016, 2019 Tobias Ellinghaus.
13 Copyright (C) 2012 José Carlos García Sogo.
14 Copyright (C) 2012 Richard Wonka.
15 Copyright (C) 2012, 2014 Ulrich Pegelow.
16 Copyright (C) 2013, 2018, 2020-2022 Pascal Obry.
17 Copyright (C) 2013 Simon Spannagel.
18 Copyright (C) 2014 Pascal de Bruijn.
19 Copyright (C) 2014-2016, 2019 Roman Lebedev.
20 Copyright (C) 2015 Pedro Côrte-Real.
21 Copyright (C) 2017, 2019 Heiko Bauke.
22 Copyright (C) 2018, 2020, 2022-2023, 2025-2026 Aurélien PIERRE.
23 Copyright (C) 2018 Edgardo Hoszowski.
24 Copyright (C) 2018 Maurizio Paglia.
25 Copyright (C) 2018 rawfiner.
26 Copyright (C) 2019-2020 Aldric Renaudin.
27 Copyright (C) 2019 Andreas Schneider.
28 Copyright (C) 2020, 2022 Chris Elston.
29 Copyright (C) 2020, 2022 Diederik Ter Rahe.
30 Copyright (C) 2020, 2022 Hanno Schwalm.
31 Copyright (C) 2020-2021 Ralf Brown.
32 Copyright (C) 2021 Hubert Kowalski.
33 Copyright (C) 2022 Martin Bařinka.
34 Copyright (C) 2022 Philipp Lutz.
35 Copyright (C) 2025-2026 Guillaume Stutin.
36
37 darktable is free software: you can redistribute it and/or modify
38 it under the terms of the GNU General Public License as published by
39 the Free Software Foundation, either version 3 of the License, or
40 (at your option) any later version.
41
42 darktable is distributed in the hope that it will be useful,
43 but WITHOUT ANY WARRANTY; without even the implied warranty of
44 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 GNU General Public License for more details.
46
47 You should have received a copy of the GNU General Public License
48 along with darktable. If not, see <http://www.gnu.org/licenses/>.
49*/
50#ifdef HAVE_CONFIG_H
51#include "common/darktable.h"
52#include "config.h"
53#endif
54#include <assert.h>
55#include <stdlib.h>
56#include <string.h>
57
58#include "bauhaus/bauhaus.h"
59#include "common/math.h"
60#include "common/opencl.h"
61#include "common/tea.h"
62#include "control/control.h"
63#include "develop/blend.h"
64#include "develop/develop.h"
65#include "develop/imageop.h"
66#include "develop/imageop_gui.h"
67#include "dtgtk/resetlabel.h"
68
69#include "gui/gtk.h"
70#include "gui/presets.h"
71#include "gui/draw.h"
72#include "iop/iop_api.h"
73#include <gtk/gtk.h>
74#include <inttypes.h>
75
77
78typedef enum dt_iop_dither_t
79{
80 DITHER_OFF = 0, // $DESCRIPTION: "off"
81 DITHER_8BIT = 1, // $DESCRIPTION: "8-bit output"
82 DITHER_16BIT = 2 // $DESCRIPTION: "16-bit output"
84
85typedef struct dt_iop_dvector_2d_t
86{
87 double x;
88 double y;
90
91typedef struct dt_iop_fvector_2d_t
92{
93 float x; // $MIN: -1.0 $MAX: 1.0 $DESCRIPTION: "horizontal center"
94 float y; // $MIN: -1.0 $MAX: 1.0 $DESCRIPTION: "vertical center"
96
98{
99 double scale; // 0 - 100 Radie
100 double falloff_scale; // 0 - 100 Radie for falloff inner radie of falloff=scale and
101 // outer=scale+falloff_scale
102 double strength; // 0 - 1 strength of effect
103 double uniformity; // 0 - 1 uniformity of center
104 double bsratio; // -1 - +1 ratio of brightness/saturation effect
107 dt_iop_dvector_2d_t center; // Center of vignette
109
111{
112 float scale; // 0 - 100 Inner radius, percent of largest image dimension
113 float falloff_scale; // 0 - 100 Radius for falloff -- outer radius = inner radius + falloff_scale
114 float brightness; // -1 - 1 Strength of brightness reduction
115 float saturation; // -1 - 1 Strength of saturation reduction
116 dt_iop_vector_2d_t center; // Center of vignette
117 gboolean autoratio; //
118 float whratio; // 0-1 = width/height ratio, 1-2 = height/width ratio + 1
119 float shape;
121
123{
124 float scale; // 0 - 100 Inner radius, percent of largest image dimension
125 float falloff_scale; // 0 - 100 Radius for falloff -- outer radius = inner radius + falloff_scale
126 float brightness; // -1 - 1 Strength of brightness reduction
127 float saturation; // -1 - 1 Strength of saturation reduction
128 dt_iop_vector_2d_t center; // Center of vignette
129 gboolean autoratio; //
130 float whratio; // 0-1 = width/height ratio, 1-2 = height/width ratio + 1
131 float shape;
132 int dithering; // if and how to perform dithering
134
135typedef struct dt_iop_vignette_params_t
136{
137 float scale; // $MIN: 0.0 $MAX: 200.0 $DEFAULT: 80.0 Inner radius, percent of largest image dimension
138 float falloff_scale; // $MIN: 0.0 $MAX: 200.0 $DEFAULT: 50.0 $DESCRIPTION: "fall-off strength" 0 - 100 Radius for falloff -- outer radius = inner radius + falloff_scale
139 float brightness; // $MIN: -1.0 $MAX: 1.0 $DEFAULT: -0.5 -1 - 1 Strength of brightness reduction
140 float saturation; // $MIN: -1.0 $MAX: 1.0 $DEFAULT: -0.5 -1 - 1 Strength of saturation reduction
141 dt_iop_vector_2d_t center; // Center of vignette
142 gboolean autoratio; // $DEFAULT: FALSE $DESCRIPTION: "automatic ratio"
143 float whratio; // $MIN: 0.0 $MAX: 2.0 $DEFAULT: 1.0 $DESCRIPTION: "width vs. height ratio" 0-1 = width/height ratio, 1-2 = height/width ratio + 1
144 float shape; // $MIN: 0.0 $MAX: 5.0 $DEFAULT: 1.0 $DESCRIPTION: "shape"
145 dt_iop_dither_t dithering; // $DEFAULT: DITHER_OFF if and how to perform dithering
146 gboolean unbound; // $DEFAULT: TRUE whether the values should be clipped
148
149
163
177
182
183
184const char *name()
185{
186 return _("_Vignetting");
187}
188
189const char **description(struct dt_iop_module_t *self)
190{
191 return dt_iop_set_description(self, _("simulate a lens fall-off close to edges"),
192 _("creative"),
193 _("non-linear, RGB, display-referred"),
194 _("non-linear, RGB"),
195 _("non-linear, RGB, display-referred"));
196}
197
203
205{
206 return IOP_GROUP_EFFECTS;
207}
208
210{
211 return IOP_CS_RGB;
212}
213
214int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version,
215 void *new_params, const int new_version)
216{
217 if(old_version == 1 && new_version == 4)
218 {
219 const dt_iop_vignette_params1_t *old = old_params;
220 dt_iop_vignette_params_t *new = new_params;
221 new->scale = old->scale;
222 new->falloff_scale = old->falloff_scale;
223 new->brightness = -(1.0 - MAX(old->bsratio, 0.0)) * old->strength / 100.0;
224 new->saturation = -(1.0 + MIN(old->bsratio, 0.0)) * old->strength / 100.0;
225 if(old->invert_saturation) new->saturation *= -2.0; // Double effect for increasing saturation
226 if(old->invert_falloff) new->brightness = -new->brightness;
227 new->center.x = old->center.x;
228 new->center.y = old->center.y;
229 new->autoratio = TRUE;
230 new->whratio = 1.0;
231 new->shape = 1.0;
232 new->dithering = DITHER_OFF;
233 new->unbound = FALSE;
234 return 0;
235 }
236 if(old_version == 2 && new_version == 4)
237 {
238 const dt_iop_vignette_params2_t *old = old_params;
239 dt_iop_vignette_params_t *new = new_params;
240 new->scale = old->scale;
241 new->falloff_scale = old->falloff_scale;
242 new->brightness = old->brightness;
243 new->saturation = old->saturation;
244 new->center.x = old->center.x;
245 new->center.y = old->center.y;
246 new->autoratio = old->autoratio;
247 new->whratio = old->whratio;
248 new->shape = old->shape;
249 new->dithering = DITHER_OFF;
250 new->unbound = FALSE;
251 return 0;
252 }
253 if(old_version == 3 && new_version == 4)
254 {
255 const dt_iop_vignette_params3_t *old = old_params;
256 dt_iop_vignette_params_t *new = new_params;
257 new->scale = old->scale;
258 new->falloff_scale = old->falloff_scale;
259 new->brightness = old->brightness;
260 new->saturation = old->saturation;
261 new->center.x = old->center.x;
262 new->center.y = old->center.y;
263 new->autoratio = old->autoratio;
264 new->whratio = old->whratio;
265 new->shape = old->shape;
266 new->dithering = old->dithering;
267 new->unbound = FALSE;
268 return 0;
269 }
270
271 return 1;
272}
273
274static int get_grab(dt_iop_module_t *self, float pointerx, float pointery, float startx, float starty, float endx, float endy,
275 float zoom_scale)
276{
277 // trick to convert the radius from image norm to preview abs
278 float radius[2] = { DT_GUI_MOUSE_EFFECT_RADIUS, 0 };
281 const float radius_sq = radius[0] * radius[0];
282
283 if((pointerx - startx) * (pointerx - startx) + pointery * pointery <= radius_sq) return 2; // x size
284 if(pointerx * pointerx + (pointery - starty) * (pointery - starty) <= radius_sq) return 4; // y size
285 if(pointerx * pointerx + pointery * pointery <= radius_sq) return 1; // center
286 if((pointerx - endx) * (pointerx - endx) + pointery * pointery <= radius_sq) return 8; // x falloff
287 if(pointerx * pointerx + (pointery - endy) * (pointery - endy) <= radius_sq) return 16; // y falloff
288
289 return 0;
290}
291
292static void draw_overlay(cairo_t *cr, float x, float y, float fx, float fy, int grab, float zoom_scale)
293{
294 // half width/height of the crosshair
295 const float crosshair_w = DT_PIXEL_APPLY_DPI(10.0) / zoom_scale;
296 const float crosshair_h = DT_PIXEL_APPLY_DPI(10.0) / zoom_scale;
297
298 // center crosshair
299 cairo_move_to(cr, -crosshair_w, 0.0);
300 cairo_line_to(cr, crosshair_w, 0.0);
301 cairo_move_to(cr, 0.0, -crosshair_h);
302 cairo_line_to(cr, 0.0, crosshair_h);
303 cairo_stroke(cr);
304
305 // inner border of the vignette
306 cairo_save(cr);
307 if(x <= y)
308 {
309 cairo_scale(cr, x / y, 1.0);
310 cairo_arc(cr, 0.0, 0.0, y, 0.0, M_PI * 2.0);
311 }
312 else
313 {
314 cairo_scale(cr, 1.0, y / x);
315 cairo_arc(cr, 0.0, 0.0, x, 0.0, M_PI * 2.0);
316 }
317 cairo_restore(cr);
318 cairo_stroke(cr);
319
320 // outer border of the vignette
321 cairo_save(cr);
322 if(fx <= fy)
323 {
324 cairo_scale(cr, fx / fy, 1.0);
325 cairo_arc(cr, 0.0, 0.0, fy, 0.0, M_PI * 2.0);
326 }
327 else
328 {
329 cairo_scale(cr, 1.0, fy / fx);
330 cairo_arc(cr, 0.0, 0.0, fx, 0.0, M_PI * 2.0);
331 }
332 cairo_restore(cr);
333 cairo_stroke(cr);
334
335 // the handles
336 const float radius_sel = DT_PIXEL_APPLY_DPI(6.0) / zoom_scale;
337 const float radius_reg = DT_PIXEL_APPLY_DPI(4.0) / zoom_scale;
338 if(grab == 1)
339 cairo_arc(cr, 0.0, 0.0, radius_sel, 0.0, M_PI * 2.0);
340 else
341 cairo_arc(cr, 0.0, 0.0, radius_reg, 0.0, M_PI * 2.0);
342 cairo_stroke(cr);
343 if(grab == 2)
344 cairo_arc(cr, x, 0.0, radius_sel, 0.0, M_PI * 2.0);
345 else
346 cairo_arc(cr, x, 0.0, radius_reg, 0.0, M_PI * 2.0);
347 cairo_stroke(cr);
348 if(grab == 4)
349 cairo_arc(cr, 0.0, -y, radius_sel, 0.0, M_PI * 2.0);
350 else
351 cairo_arc(cr, 0.0, -y, radius_reg, 0.0, M_PI * 2.0);
352 cairo_stroke(cr);
353 if(grab == 8)
354 cairo_arc(cr, fx, 0.0, radius_sel, 0.0, M_PI * 2.0);
355 else
356 cairo_arc(cr, fx, 0.0, radius_reg, 0.0, M_PI * 2.0);
357 cairo_stroke(cr);
358 if(grab == 16)
359 cairo_arc(cr, 0.0, -fy, radius_sel, 0.0, M_PI * 2.0);
360 else
361 cairo_arc(cr, 0.0, -fy, radius_reg, 0.0, M_PI * 2.0);
362 cairo_stroke(cr);
363}
364
365// FIXME: For portrait images the overlay is a bit off. The coordinates in mouse_moved seem to be ok though.
366// WTF?
367void gui_post_expose(struct dt_iop_module_t *self, cairo_t *cr, int32_t width, int32_t height,
368 int32_t pointerx, int32_t pointery)
369{
370 dt_develop_t *dev = self->dev;
373 if(IS_NULL_PTR(g) || IS_NULL_PTR(p)) return;
374
375 const float wd = dev->roi.preview_width;
376 const float ht = dev->roi.preview_height;
377 float bigger_side, smaller_side;
378 if(wd >= ht)
379 {
380 bigger_side = wd;
381 smaller_side = ht;
382 }
383 else
384 {
385 bigger_side = ht;
386 smaller_side = wd;
387 }
388 const float zoom_scale = dt_dev_get_overlay_scale(dev);
389 float pzxpy[2] = { (float)pointerx, (float)pointery };
391 const float pzx = pzxpy[0];
392 const float pzy = pzxpy[1];
394
395 float vignette_x = (p->center.x + 1.0) * 0.5 * wd;
396 float vignette_y = (p->center.y + 1.0) * 0.5 * ht;
397
398 cairo_translate(cr, vignette_x, vignette_y);
399
400 float vignette_w = p->scale * 0.01 * 0.5 * wd; // start of falloff
401 float vignette_h = p->scale * 0.01 * 0.5 * ht;
402 float vignette_fx = vignette_w + p->falloff_scale * 0.01 * 0.5 * wd; // end of falloff
403 float vignette_fy = vignette_h + p->falloff_scale * 0.01 * 0.5 * ht;
404
405 if(p->autoratio == FALSE)
406 {
407 float factor1 = bigger_side / smaller_side;
408 if(wd >= ht)
409 {
410 float factor2 = (2.0 - p->whratio) * factor1;
411
412 if(p->whratio <= 1)
413 {
414 vignette_h *= factor1;
415 vignette_w *= p->whratio;
416 vignette_fx *= p->whratio;
417 vignette_fy *= factor1;
418 }
419 else
420 {
421 vignette_h *= factor2;
422 vignette_fy *= factor2;
423 }
424 }
425 else
426 {
427 float factor2 = (p->whratio) * factor1;
428
429 if(p->whratio <= 1)
430 {
431 vignette_w *= factor2;
432 vignette_fx *= factor2;
433 }
434 else
435 {
436 vignette_w *= factor1;
437 vignette_h *= (2.0 - p->whratio);
438 vignette_fx *= factor1;
439 vignette_fy *= (2.0 - p->whratio);
440 }
441 }
442 }
443
444 int grab = get_grab(self, pzx * wd - vignette_x, pzy * ht - vignette_y, vignette_w, -vignette_h, vignette_fx,
445 -vignette_fy, zoom_scale);
446 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
447 cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(3.0) / zoom_scale);
449 draw_overlay(cr, vignette_w, vignette_h, vignette_fx, vignette_fy, grab, zoom_scale);
450 cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.0) / zoom_scale);
452 draw_overlay(cr, vignette_w, vignette_h, vignette_fx, vignette_fy, grab, zoom_scale);
453}
454
455// FIXME: Pumping of the opposite direction when changing width/height. See two FIXMEs further down.
456int mouse_moved(struct dt_iop_module_t *self, double x, double y, double pressure, int which)
457{
458 const dt_develop_t *dev = (const dt_develop_t *)self->dev;
461 if(IS_NULL_PTR(g) || IS_NULL_PTR(p)) return 0;
462 const float wd = dev->roi.preview_width;
463 const float ht = dev->roi.preview_height;
464 float bigger_side, smaller_side;
465 if(wd >= ht)
466 {
467 bigger_side = wd;
468 smaller_side = ht;
469 }
470 else
471 {
472 bigger_side = ht;
473 smaller_side = wd;
474 }
475
476 const float zoom_scale = dev->roi.scaling;
477 float pzxpy[2] = { (float)x, (float)y };
479 const float pzx = pzxpy[0];
480 const float pzy = pzxpy[1];
481 static int old_grab = -1;
482 int grab = old_grab;
483
484 float vignette_x = (p->center.x + 1.0) * 0.5 * wd;
485 float vignette_y = (p->center.y + 1.0) * 0.5 * ht;
486
487 float vignette_w = p->scale * 0.01 * 0.5 * wd; // start of falloff
488 float vignette_h = p->scale * 0.01 * 0.5 * ht;
489 float vignette_fx = vignette_w + p->falloff_scale * 0.01 * 0.5 * wd; // end of falloff
490 float vignette_fy = vignette_h + p->falloff_scale * 0.01 * 0.5 * ht;
491
492 if(p->autoratio == FALSE)
493 {
494 float factor1 = bigger_side / smaller_side;
495 if(wd >= ht)
496 {
497 float factor2 = (2.0 - p->whratio) * factor1;
498
499 if(p->whratio <= 1)
500 {
501 vignette_h *= factor1;
502 vignette_w *= p->whratio;
503 vignette_fx *= p->whratio;
504 vignette_fy *= factor1;
505 }
506 else
507 {
508 vignette_h *= factor2;
509 vignette_fy *= factor2;
510 }
511 }
512 else
513 {
514 float factor2 = (p->whratio) * factor1;
515
516 if(p->whratio <= 1)
517 {
518 vignette_w *= factor2;
519 vignette_fx *= factor2;
520 }
521 else
522 {
523 vignette_w *= factor1;
524 vignette_h *= (2.0 - p->whratio);
525 vignette_fx *= factor1;
526 vignette_fy *= (2.0 - p->whratio);
527 }
528 }
529 }
530
531 if(grab == 0 || !(darktable.control->button_down && darktable.control->button_down_which == 1))
532 {
533 grab = get_grab(self, pzx * wd - vignette_x, pzy * ht - vignette_y, vignette_w, -vignette_h, vignette_fx,
534 -vignette_fy, zoom_scale);
535 }
536
538 {
539 if(grab == 0) // pan the image
540 {
541 dt_control_queue_cursor(GDK_HAND1);
542 return 0;
543 }
544 else if(grab == 1) // move the center
545 {
546 dt_bauhaus_slider_set(g->center_x, pzx * 2.0 - 1.0);
547 dt_bauhaus_slider_set(g->center_y, pzy * 2.0 - 1.0);
548 }
549 else if(grab == 2) // change the width
550 {
551 const float max = 0.5 * ((p->whratio <= 1.0) ? bigger_side * p->whratio : bigger_side);
552 const float new_vignette_w = MIN(bigger_side, MAX(0.1, pzx * wd - vignette_x));
553 const float ratio = new_vignette_w / vignette_h;
554 const float new_scale = 100.0 * new_vignette_w / max;
555 // FIXME: When going over the 1.0 boundary from wide to narrow (>1.0 -> <=1.0) the height slightly
556 // changes, depending on speed.
557 // I guess we have to split the computation.
558 if(ratio <= 1.0)
559 {
560 if(dt_modifier_is(which, GDK_CONTROL_MASK))
561 {
562 dt_bauhaus_slider_set(g->scale, new_scale);
563 }
564 else
565 {
566 dt_bauhaus_slider_set(g->whratio, ratio);
567 }
568 }
569 else
570 {
571 dt_bauhaus_slider_set(g->scale, new_scale);
572
573 if(!dt_modifier_is(which, GDK_CONTROL_MASK))
574 {
575 float new_whratio = 2.0 - 1.0 / ratio;
576 dt_bauhaus_slider_set(g->whratio, new_whratio);
577 }
578 }
579 }
580 else if(grab == 4) // change the height
581 {
582 const float new_vignette_h = MIN(bigger_side, MAX(0.1, vignette_y - pzy * ht));
583 const float ratio = new_vignette_h / vignette_w;
584 const float max = 0.5 * ((ratio <= 1.0) ? bigger_side * (2.0 - p->whratio) : bigger_side);
585 // FIXME: When going over the 1.0 boundary from narrow to wide (>1.0 -> <=1.0) the width slightly
586 // changes, depending on speed.
587 // I guess we have to split the computation.
588 if(ratio <= 1.0)
589 {
590 if(dt_modifier_is(which, GDK_CONTROL_MASK))
591 {
592 const float new_scale = 100.0 * new_vignette_h / max;
593 dt_bauhaus_slider_set(g->scale, new_scale);
594 }
595 else
596 {
597 dt_bauhaus_slider_set(g->whratio, 2.0 - ratio);
598 }
599 }
600 else
601 {
602 const float new_scale = 100.0 * new_vignette_h / max;
603 dt_bauhaus_slider_set(g->scale, new_scale);
604
605 if(!dt_modifier_is(which, GDK_CONTROL_MASK))
606 {
607 const float new_whratio = 1.0 / ratio;
608 dt_bauhaus_slider_set(g->whratio, new_whratio);
609 }
610 }
611 }
612 else if(grab == 8) // change the falloff on the right
613 {
614 const float new_vignette_fx = pzx * wd - vignette_x;
615 const float max = 0.5 * ((p->whratio <= 1.0) ? bigger_side * p->whratio : bigger_side);
616 const float delta_x = MIN(2.0f * max, MAX(0.0, new_vignette_fx - vignette_w));
617 const float new_falloff = 100.0 * delta_x / max;
618 dt_bauhaus_slider_set(g->falloff_scale, new_falloff);
619 }
620 else if(grab == 16) // change the falloff on the top
621 {
622 const float new_vignette_fy = vignette_y - pzy * ht;
623 const float max = 0.5 * ((p->whratio > 1.0) ? bigger_side * (2.0 - p->whratio) : bigger_side);
624 const float delta_y = MIN(2.0f * max, MAX(0.0, new_vignette_fy - vignette_h));
625 const float new_falloff = 100.0 * delta_y / max;
626 dt_bauhaus_slider_set(g->falloff_scale, new_falloff);
627 }
629 return 1;
630 }
631 else if(grab)
632 {
633 if(grab == 1)
634 dt_control_queue_cursor(GDK_FLEUR);
635 else if(grab == 2)
636 dt_control_queue_cursor(GDK_SB_H_DOUBLE_ARROW);
637 else if(grab == 4)
638 dt_control_queue_cursor(GDK_SB_V_DOUBLE_ARROW);
639 else if(grab == 8)
640 dt_control_queue_cursor(GDK_SB_H_DOUBLE_ARROW);
641 else if(grab == 16)
642 dt_control_queue_cursor(GDK_SB_V_DOUBLE_ARROW);
643 }
644 else
645 {
646 if(old_grab != grab) dt_control_queue_cursor(GDK_LEFT_PTR);
647 }
648 old_grab = grab;
650 return 0;
651}
652
653int button_pressed(struct dt_iop_module_t *self, double x, double y, double pressure, int which, int type,
654 uint32_t state)
655{
656 if(which == 1) return 1;
657 return 0;
658}
659
660int button_released(struct dt_iop_module_t *self, double x, double y, int which, uint32_t state)
661{
662 if(which == 1) return 1;
663 return 0;
664}
665
667int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
668 void *const ovoid)
669{
670 const dt_iop_roi_t *const roi_in = &piece->roi_in;
671 const dt_iop_roi_t *const roi_out = &piece->roi_out;
672 const dt_iop_vignette_data_t *data = (dt_iop_vignette_data_t *)piece->data;
673 const dt_iop_roi_t *buf_in = &piece->buf_in;
674 const size_t ch = piece->dsc_in.channels;
675 const gboolean unbound = data->unbound;
676
677 /* Center coordinates of buf_in, these should not consider buf_in->{x,y}! */
678 const dt_iop_vector_2d_t buf_center = { buf_in->width * .5f, buf_in->height * .5f };
679 /* Center coordinates of vignette center */
680 const dt_iop_vector_2d_t vignette_center = { buf_center.x + data->center.x * buf_in->width / 2.0,
681 buf_center.y + data->center.y * buf_in->height / 2.0 };
682 /* Coordinates of vignette_center in terms of roi_in */
683 const dt_iop_vector_2d_t roi_center
684 = { vignette_center.x * roi_in->scale - roi_in->x, vignette_center.y * roi_in->scale - roi_in->y };
685 float xscale;
686 float yscale;
687
688 /* w/h ratio follows piece dimensions */
689 if(data->autoratio)
690 {
691 xscale = 2.0 / (buf_in->width * roi_out->scale);
692 yscale = 2.0 / (buf_in->height * roi_out->scale);
693 }
694 else /* specified w/h ratio, scale proportional to longest side */
695 {
696 const float basis = 2.0 / (MAX(buf_in->height, buf_in->width) * roi_out->scale);
697 // w/h ratio from 0-1 use as-is
698 if(data->whratio <= 1.0)
699 {
700 yscale = basis;
701 xscale = yscale / data->whratio;
702 }
703 // w/h ratio from 1-2 interpret as 1-inf
704 // that is, the h/w ratio + 1
705 else
706 {
707 xscale = basis;
708 yscale = xscale / (2.0 - data->whratio);
709 }
710 }
711 const float dscale = data->scale / 100.0;
712 // A minimum falloff is used, based on the image size, to smooth out aliasing artifacts
713 const float min_falloff = 100.0 / MIN(buf_in->width, buf_in->height);
714 const float fscale = MAX(data->falloff_scale, min_falloff) / 100.0;
715 const float shape = MAX(data->shape, 0.001);
716 const float exp1 = 2.0 / shape;
717 const float exp2 = shape / 2.0;
718 // Pre-scale the center offset
719 const dt_iop_vector_2d_t roi_center_scaled = { roi_center.x * xscale, roi_center.y * yscale };
720
721 float dither = 0.0f;
722
723 switch(data->dithering)
724 {
725 case DITHER_8BIT:
726 dither = 1.0f / 256;
727 break;
728 case DITHER_16BIT:
729 dither = 1.0f / 65536;
730 break;
731 case DITHER_OFF:
732 default:
733 dither = 0.0f;
734 }
735
736 unsigned int *const tea_states = alloc_tea_states(darktable.num_openmp_threads);
738 for(int j = 0; j < roi_out->height; j++)
739 {
740 const size_t k = (size_t)ch * roi_out->width * j;
741 const float *in = (const float *)ivoid + k;
742 float *out = (float *)ovoid + k;
743 unsigned int *tea_state = get_tea_state(tea_states,dt_get_thread_num());
744 tea_state[0] = j * roi_out->height; /* + dt_get_thread_num() -- do not include, makes results unreproducible */
745 for(int i = 0; i < roi_out->width; i++, in += ch, out += ch)
746 {
747 // current pixel coord translated to local coord
748 const dt_iop_vector_2d_t pv
749 = { fabsf(i * xscale - roi_center_scaled.x), fabsf(j * yscale - roi_center_scaled.y) };
750
751 // Calculate the pixel weight in vignette
752 const float cplen = powf(powf(pv.x, exp1) + powf(pv.y, exp1), exp2); // Length from center to pv
753 float weight = 0.0;
754 float dith = 0.0;
755
756 if(cplen >= dscale) // pixel is outside the inner vignette circle, lets calculate weight of vignette
757 {
758 weight = ((cplen - dscale) / fscale);
759 if(weight >= 1.0)
760 weight = 1.0;
761 else if(weight <= 0.0)
762 weight = 0.0;
763 else if(dither == 0.0f)
764 {
765 // don't bother computing the random number if dithering is disabled
766 dith = 0.0f;
767 }
768 else
769 {
770 weight = 0.5 - cosf(M_PI * weight) / 2.0;
771 encrypt_tea(tea_state);
772 dith = dither * tpdf(tea_state[0]);
773 }
774 }
775
776 // Let's apply weighted effect on brightness and desaturation
777 float col0 = in[0], col1 = in[1], col2 = in[2], col3 = in[3];
778 if(weight > 0)
779 {
780 // Then apply falloff vignette
781 float falloff = (data->brightness < 0) ? (1.0f + (weight * data->brightness))
782 : (weight * data->brightness);
783 col0 = data->brightness < 0 ? col0 * falloff + dith : col0 + falloff + dith;
784 col1 = data->brightness < 0 ? col1 * falloff + dith : col1 + falloff + dith;
785 col2 = data->brightness < 0 ? col2 * falloff + dith : col2 + falloff + dith;
786
787 col0 = unbound ? col0 : CLIP(col0);
788 col1 = unbound ? col1 : CLIP(col1);
789 col2 = unbound ? col2 : CLIP(col2);
790
791 // apply saturation
792 float mv = (col0 + col1 + col2) / 3.0f;
793 float wss = weight * data->saturation;
794 col0 = col0 - ((mv - col0) * wss);
795 col1 = col1 - ((mv - col1) * wss);
796 col2 = col2 - ((mv - col2) * wss);
797
798 col0 = unbound ? col0 : CLIP(col0);
799 col1 = unbound ? col1 : CLIP(col1);
800 col2 = unbound ? col2 : CLIP(col2);
801 }
802
803 out[0] = col0;
804 out[1] = col1;
805 out[2] = col2;
806 out[3] = col3;
807 }
808 }
809
810 free_tea_states(tea_states);
811 return 0;
812}
813
814
815#ifdef HAVE_OPENCL
816int 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)
817{
818 const dt_iop_roi_t *const roi_in = &piece->roi_in;
819 const dt_iop_roi_t *const roi_out = &piece->roi_out;
822
823 cl_int err = -999;
824 const int devid = pipe->devid;
825 const int width = roi_out->width;
826 const int height = roi_out->height;
827
828 const dt_iop_roi_t *buf_in = &piece->buf_in;
829
830 /* Center coordinates of buf_in, these should not consider buf_in->{x,y}! */
831 const dt_iop_vector_2d_t buf_center = { buf_in->width * .5f, buf_in->height * .5f };
832 /* Center coordinates of vignette center */
833 const dt_iop_vector_2d_t vignette_center = { buf_center.x + data->center.x * buf_in->width / 2.0,
834 buf_center.y + data->center.y * buf_in->height / 2.0 };
835 /* Coordinates of vignette_center in terms of roi_in */
836 const dt_iop_vector_2d_t roi_center
837 = { vignette_center.x * roi_in->scale - roi_in->x, vignette_center.y * roi_in->scale - roi_in->y };
838 float xscale;
839 float yscale;
840
841 /* w/h ratio follows piece dimensions */
842 if(data->autoratio)
843 {
844 xscale = 2.0 / (buf_in->width * roi_out->scale);
845 yscale = 2.0 / (buf_in->height * roi_out->scale);
846 }
847 else /* specified w/h ratio, scale proportional to longest side */
848 {
849 const float basis = 2.0 / (MAX(buf_in->height, buf_in->width) * roi_out->scale);
850 // w/h ratio from 0-1 use as-is
851 if(data->whratio <= 1.0)
852 {
853 yscale = basis;
854 xscale = yscale / data->whratio;
855 }
856 // w/h ratio from 1-2 interpret as 1-inf
857 // that is, the h/w ratio + 1
858 else
859 {
860 xscale = basis;
861 yscale = xscale / (2.0 - data->whratio);
862 }
863 }
864 const float dscale = data->scale / 100.0;
865 // A minimum falloff is used, based on the image size, to smooth out aliasing artifacts
866 const float min_falloff = 100.0 / MIN(buf_in->width, buf_in->height);
867 const float fscale = MAX(data->falloff_scale, min_falloff) / 100.0;
868 const float shape = MAX(data->shape, 0.001);
869 const float exp1 = 2.0 / shape;
870 const float exp2 = shape / 2.0;
871 // Pre-scale the center offset
872 const dt_iop_vector_2d_t roi_center_scaled = { roi_center.x * xscale, roi_center.y * yscale };
873
874 float dither = 0.0f;
875
876 switch(data->dithering)
877 {
878 case DITHER_8BIT:
879 dither = 1.0f / 256;
880 break;
881 case DITHER_16BIT:
882 dither = 1.0f / 65536;
883 break;
884 case DITHER_OFF:
885 default:
886 dither = 0.0f;
887 }
888
889 float scale[2] = { xscale, yscale };
890 float roi_center_scaled_f[2] = { roi_center_scaled.x, roi_center_scaled.y };
891 float expt[2] = { exp1, exp2 };
892 const float brightness = data->brightness;
893 const float saturation = data->saturation;
894 const int unbound = data->unbound;
895
896 size_t sizes[2] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid) };
897
898 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 0, sizeof(cl_mem), &dev_in);
899 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 1, sizeof(cl_mem), &dev_out);
900 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 2, sizeof(int), &width);
901 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 3, sizeof(int), &height);
902 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 4, 2 * sizeof(float), &scale);
903 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 5, 2 * sizeof(float), &roi_center_scaled_f);
904 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 6, 2 * sizeof(float), &expt);
905 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 7, sizeof(float), &dscale);
906 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 8, sizeof(float), &fscale);
907 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 9, sizeof(float), &brightness);
908 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 10, sizeof(float), &saturation);
909 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 11, sizeof(float), &dither);
910 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 12, sizeof(int), &unbound);
911 err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_vignette, sizes);
912 if(err != CL_SUCCESS) goto error;
913
914 return TRUE;
915
916error:
917 dt_print(DT_DEBUG_OPENCL, "[opencl_vignette] couldn't enqueue kernel! %d\n", err);
918 return FALSE;
919}
920#endif
921
922
924{
925 const int program = 8; // extended.cl from programs.conf
928 module->data = gd;
929 gd->kernel_vignette = dt_opencl_create_kernel(program, "vignette");
930}
931
932
939
940
941void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
942{
945 if(IS_NULL_PTR(g) || IS_NULL_PTR(p)) return;
946
947 gtk_widget_set_sensitive(GTK_WIDGET(g->whratio), !p->autoratio);
948}
949
952{
955 d->scale = p->scale;
956 d->falloff_scale = p->falloff_scale;
957 d->brightness = p->brightness;
958 d->saturation = p->saturation;
959 d->center = p->center;
960 d->autoratio = p->autoratio;
961 d->whratio = p->whratio;
962 d->shape = p->shape;
963 d->dithering = p->dithering;
964 d->unbound = p->unbound;
965}
966
968{
971 p.scale = 40.0f;
972 p.falloff_scale = 100.0f;
973 p.brightness = -1.0f;
974 p.saturation = 0.5f;
975 p.center.x = 0.0f;
976 p.center.y = 0.0f;
977 p.autoratio = FALSE;
978 p.whratio = 1.0f;
979 p.shape = 1.0f;
980 p.dithering = 0;
981 p.unbound = TRUE;
982 dt_gui_presets_add_generic(_("lomo"), self->op,
983 self->version(), &p, sizeof(p), 1, DEVELOP_BLEND_CS_RGB_DISPLAY);
985}
986
988{
990 piece->data_size = sizeof(dt_iop_vignette_data_t);
991}
992
994{
995 dt_free_align(piece->data);
996 piece->data = NULL;
997}
998
999void gui_update(struct dt_iop_module_t *self)
1000{
1003 if(IS_NULL_PTR(g) || IS_NULL_PTR(p)) return;
1004 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autoratio), p->autoratio);
1005 gtk_widget_set_sensitive(GTK_WIDGET(g->whratio), !p->autoratio);
1006}
1007
1008void gui_init(struct dt_iop_module_t *self)
1009{
1011
1012 g->scale = dt_bauhaus_slider_from_params(self, N_("scale"));
1013 g->falloff_scale = dt_bauhaus_slider_from_params(self, "falloff_scale");
1014 g->brightness = dt_bauhaus_slider_from_params(self, N_("brightness"));
1015 g->saturation = dt_bauhaus_slider_from_params(self, N_("saturation"));
1016
1017 gtk_box_pack_start(GTK_BOX(self->widget),
1018 dt_ui_section_label_new(_("position / form")), FALSE, FALSE, 0);
1019
1020 g->center_x = dt_bauhaus_slider_from_params(self, "center.x");
1021 g->center_y = dt_bauhaus_slider_from_params(self, "center.y");
1022 g->shape = dt_bauhaus_slider_from_params(self, N_("shape"));
1023 g->autoratio = dt_bauhaus_toggle_from_params(self, "autoratio");
1024 g->whratio = dt_bauhaus_slider_from_params(self, "whratio");
1025 g->dithering = dt_bauhaus_combobox_from_params(self, N_("dithering"));
1026
1027 dt_bauhaus_slider_set_digits(g->brightness, 3);
1028 dt_bauhaus_slider_set_digits(g->saturation, 3);
1029 dt_bauhaus_slider_set_digits(g->center_x, 3);
1030 dt_bauhaus_slider_set_digits(g->center_y, 3);
1031 dt_bauhaus_slider_set_digits(g->whratio, 3);
1032
1033 dt_bauhaus_slider_set_format(g->scale, "%");
1034 dt_bauhaus_slider_set_format(g->falloff_scale, "%");
1035
1036 gtk_widget_set_tooltip_text(g->scale, _("the radii scale of vignette for start of fall-off"));
1037 gtk_widget_set_tooltip_text(g->falloff_scale, _("the radii scale of vignette for end of fall-off"));
1038 gtk_widget_set_tooltip_text(g->brightness, _("strength of effect on brightness"));
1039 gtk_widget_set_tooltip_text(g->saturation, _("strength of effect on saturation"));
1040 gtk_widget_set_tooltip_text(g->center_x, _("horizontal offset of center of the effect"));
1041 gtk_widget_set_tooltip_text(g->center_y, _("vertical offset of center of the effect"));
1042 gtk_widget_set_tooltip_text(g->shape, _("shape factor\n0 produces a rectangle\n1 produces a circle or ellipse\n"
1043 "2 produces a diamond"));
1044 gtk_widget_set_tooltip_text(GTK_WIDGET(g->autoratio), _("enable to have the ratio automatically follow the image size"));
1045 gtk_widget_set_tooltip_text(g->whratio, _("width-to-height ratio"));
1046 gtk_widget_set_tooltip_text(g->dithering, _("add some level of random noise to prevent banding"));
1047}
1048
1049// clang-format off
1050// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1051// vim: shiftwidth=2 expandtab tabstop=2 cindent
1052// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1053// clang-format on
static void error(char *msg)
Definition ashift_lsd.c:202
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
Definition bauhaus.c:3534
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
Definition bauhaus.c:3506
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3598
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
@ DEVELOP_BLEND_CS_RGB_DISPLAY
Definition blend.h:59
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
@ IOP_CS_RGB
const float max
const dt_colormatrix_t dt_aligned_pixel_t out
int type
void dt_control_queue_redraw_center()
request redraw of center window. This redraws the center view within a gdk critical section to preven...
Definition control.c:861
#define dt_control_queue_cursor(cursor)
Definition control.h:135
darktable_t darktable
Definition darktable.c:181
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1542
#define dt_free_align(ptr)
Definition darktable.h:481
static void * dt_calloc_align(size_t size)
Definition darktable.h:488
@ DT_DEBUG_OPENCL
Definition darktable.h:722
static int dt_get_thread_num()
Definition darktable.h:291
#define dt_free(ptr)
Definition darktable.h:456
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
Definition darktable.h:151
#define __DT_CLONE_TARGETS__
Definition darktable.h:367
#define __OMP_PARALLEL_FOR__(...)
Definition darktable.h:258
static gboolean dt_modifier_is(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
Definition darktable.h:893
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
#define dt_database_start_transaction(db)
Definition database.h:77
#define dt_database_release_transaction(db)
Definition database.h:78
void dt_iop_params_t
Definition dev_history.h:41
void dt_dev_coordinates_image_abs_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
Definition develop.c:1075
float dt_dev_get_overlay_scale(dt_develop_t *dev)
Get the overlay scale factor in GUI logical coordinates.
Definition develop.c:1712
void dt_dev_coordinates_image_norm_to_preview_abs(dt_develop_t *dev, float *points, size_t num_points)
Definition develop.c:1144
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.
Definition develop.c:1824
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.
Definition develop.c:1003
static void dt_draw_set_color_overlay(cairo_t *cr, gboolean bright, double alpha)
Definition draw.h:106
static void weight(const float *c1, const float *c2, const float sharpen, dt_aligned_pixel_t weight)
Definition eaw.c:30
#define DT_GUI_MOUSE_EFFECT_RADIUS
Definition gtk.h:70
static GtkWidget * dt_ui_section_label_new(const gchar *str)
Definition gtk.h:451
#define DT_PIXEL_APPLY_DPI(value)
Definition gtk.h:90
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 dt_develop_blend_colorspace_t blend_cst)
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)
Definition imageop.c:3141
@ IOP_FLAGS_INCLUDE_IN_STYLES
Definition imageop.h:166
@ IOP_FLAGS_SUPPORTS_BLENDING
Definition imageop.h:167
@ IOP_FLAGS_ALLOW_TILING
Definition imageop.h:169
@ IOP_FLAGS_TILING_FULL_ROI
Definition imageop.h:171
@ IOP_GROUP_EFFECTS
Definition imageop.h:142
#define IOP_GUI_ALLOC(module)
Definition imageop.h:599
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)
Definition imageop_gui.c:77
GtkWidget * dt_bauhaus_combobox_from_params(dt_iop_module_t *self, const char *param)
void *const ovoid
static const float x
dt_iop_dither_t
Definition lightroom.c:109
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#define CLIP(x)
Definition math.h:81
#define M_PI
Definition math.h:45
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
Definition opencl.c:2136
int dt_opencl_create_kernel(const int prog, const char *name)
Definition opencl.c:2030
void dt_opencl_free_kernel(const int kernel)
Definition opencl.c:2073
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
Definition opencl.c:2127
#define ROUNDUPDHT(a, b)
Definition opencl.h:82
#define ROUNDUPDWD(a, b)
Definition opencl.h:81
struct _GtkWidget GtkWidget
Definition splash.h:29
const float uint32_t state[4]
int32_t num_openmp_threads
Definition darktable.h:758
const struct dt_database_t * db
Definition darktable.h:779
struct dt_control_t * control
Definition darktable.h:773
int button_down_which
Definition control.h:216
int button_down
Definition control.h:216
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
int32_t preview_height
Definition develop.h:213
float scaling
Definition develop.h:193
struct dt_develop_t::@17 roi
int32_t preview_width
Definition develop.h:213
unsigned int channels
Definition format.h:54
GModule *dt_dev_operation_t op
Definition imageop.h:230
dt_iop_global_data_t * data
Definition imageop.h:233
GtkWidget * widget
Definition imageop.h:337
struct dt_develop_t * dev
Definition imageop.h:296
dt_iop_gui_data_t * gui_data
Definition imageop.h:311
dt_iop_global_data_t * global_data
Definition imageop.h:314
dt_iop_params_t * params
Definition imageop.h:307
Region of interest passed through the pixelpipe.
Definition imageop.h:72
double scale
Definition imageop.h:74
dt_iop_vector_2d_t center
Definition vignette.c:170
dt_iop_dvector_2d_t center
Definition vignette.c:107
dt_iop_vector_2d_t center
Definition vignette.c:116
dt_iop_vector_2d_t center
Definition vignette.c:128
dt_iop_dither_t dithering
Definition vignette.c:145
dt_iop_vector_2d_t center
Definition lightroom.c:128
static float tpdf(unsigned int urandom)
Definition tea.h:71
static unsigned int * get_tea_state(unsigned int *const states, int threadnum)
Definition tea.h:40
static void free_tea_states(unsigned int *states)
Definition tea.h:45
static unsigned int * alloc_tea_states(size_t numthreads)
Definition tea.h:31
static void encrypt_tea(unsigned int *arg)
Definition tea.h:55
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29
static int get_grab(dt_iop_module_t *self, float pointerx, float pointery, float startx, float starty, float endx, float endy, float zoom_scale)
Definition vignette.c:274
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)
Definition vignette.c:950
const char ** description(struct dt_iop_module_t *self)
Definition vignette.c:189
int default_group()
Definition vignette.c:204
__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)
Definition vignette.c:667
dt_iop_dither_t
Definition vignette.c:79
@ DITHER_16BIT
Definition vignette.c:82
@ DITHER_8BIT
Definition vignette.c:81
@ DITHER_OFF
Definition vignette.c:80
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition vignette.c:987
const char * name()
Definition vignette.c:184
void gui_update(struct dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
Definition vignette.c:999
void gui_init(struct dt_iop_module_t *self)
Definition vignette.c:1008
int button_pressed(struct dt_iop_module_t *self, double x, double y, double pressure, int which, int type, uint32_t state)
Definition vignette.c:653
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
Definition vignette.c:941
int button_released(struct dt_iop_module_t *self, double x, double y, int which, uint32_t state)
Definition vignette.c:660
void cleanup_global(dt_iop_module_so_t *module)
Definition vignette.c:933
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition vignette.c:209
int flags()
Definition vignette.c:198
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)
Definition vignette.c:367
void init_presets(dt_iop_module_so_t *self)
Definition vignette.c:967
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)
Definition vignette.c:993
void init_global(dt_iop_module_so_t *module)
Definition vignette.c:923
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)
Definition vignette.c:816
int mouse_moved(struct dt_iop_module_t *self, double x, double y, double pressure, int which)
Definition vignette.c:456
static void draw_overlay(cairo_t *cr, float x, float y, float fx, float fy, int grab, float zoom_scale)
Definition vignette.c:292
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
Definition vignette.c:214