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 "config.h"
52#endif
53#include <assert.h>
54#include "system/macros.h"
55#include "system/openmp.h"
57#include "system/mem_alloc.h"
58#include "common/logging.h"
60#include "database/database.h"
61#include <stdlib.h>
62#include <string.h>
63
64#include "widgets/bauhaus.h"
66#include "math/math.h"
67#include "common/opencl.h"
68#include "pixel/tea.h"
69#include "control/input.h"
70#include "control/control.h"
71#include "develop/develop.h"
72#include "develop/imageop.h"
73#include "develop/imageop_gui.h"
74
75#include "gui/presets.h"
76#include "widgets/draw.h"
77#include "iop/iop_api.h"
78#include <gtk/gtk.h>
79#include <inttypes.h>
80#include "widgets/label.h"
81
83
84typedef enum dt_iop_dither_t
85{
86 DITHER_OFF = 0, // $DESCRIPTION: "off"
87 DITHER_8BIT = 1, // $DESCRIPTION: "8-bit output"
88 DITHER_16BIT = 2 // $DESCRIPTION: "16-bit output"
90
91typedef struct dt_iop_dvector_2d_t
92{
93 double x;
94 double y;
96
97typedef struct dt_iop_fvector_2d_t
98{
99 float x; // $MIN: -1.0 $MAX: 1.0 $DESCRIPTION: "horizontal center"
100 float y; // $MIN: -1.0 $MAX: 1.0 $DESCRIPTION: "vertical center"
102
104{
105 double scale; // 0 - 100 Radie
106 double falloff_scale; // 0 - 100 Radie for falloff inner radie of falloff=scale and
107 // outer=scale+falloff_scale
108 double strength; // 0 - 1 strength of effect
109 double uniformity; // 0 - 1 uniformity of center
110 double bsratio; // -1 - +1 ratio of brightness/saturation effect
113 dt_iop_dvector_2d_t center; // Center of vignette
115
117{
118 float scale; // 0 - 100 Inner radius, percent of largest image dimension
119 float falloff_scale; // 0 - 100 Radius for falloff -- outer radius = inner radius + falloff_scale
120 float brightness; // -1 - 1 Strength of brightness reduction
121 float saturation; // -1 - 1 Strength of saturation reduction
122 dt_iop_vector_2d_t center; // Center of vignette
123 gboolean autoratio; //
124 float whratio; // 0-1 = width/height ratio, 1-2 = height/width ratio + 1
125 float shape;
127
129{
130 float scale; // 0 - 100 Inner radius, percent of largest image dimension
131 float falloff_scale; // 0 - 100 Radius for falloff -- outer radius = inner radius + falloff_scale
132 float brightness; // -1 - 1 Strength of brightness reduction
133 float saturation; // -1 - 1 Strength of saturation reduction
134 dt_iop_vector_2d_t center; // Center of vignette
135 gboolean autoratio; //
136 float whratio; // 0-1 = width/height ratio, 1-2 = height/width ratio + 1
137 float shape;
138 int dithering; // if and how to perform dithering
140
141typedef struct dt_iop_vignette_params_t
142{
143 float scale; // $MIN: 0.0 $MAX: 200.0 $DEFAULT: 80.0 Inner radius, percent of largest image dimension
144 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
145 float brightness; // $MIN: -1.0 $MAX: 1.0 $DEFAULT: -0.5 -1 - 1 Strength of brightness reduction
146 float saturation; // $MIN: -1.0 $MAX: 1.0 $DEFAULT: -0.5 -1 - 1 Strength of saturation reduction
147 dt_iop_vector_2d_t center; // Center of vignette
148 gboolean autoratio; // $DEFAULT: FALSE $DESCRIPTION: "automatic ratio"
149 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
150 float shape; // $MIN: 0.0 $MAX: 5.0 $DEFAULT: 1.0 $DESCRIPTION: "shape"
151 dt_iop_dither_t dithering; // $DEFAULT: DITHER_OFF if and how to perform dithering
152 gboolean unbound; // $DEFAULT: TRUE whether the values should be clipped
154
155
169
183
188
189
190const char *name()
191{
192 return _("_Vignetting");
193}
194
195const char **description(struct dt_iop_module_t *self)
196{
197 return dt_iop_set_description(self, _("simulate a lens fall-off close to edges"),
198 _("creative"),
199 _("non-linear, RGB, display-referred"),
200 _("non-linear, RGB"),
201 _("non-linear, RGB, display-referred"));
202}
203
209
211{
212 return IOP_GROUP_EFFECTS;
213}
214
216{
217 return IOP_CS_RGB;
218}
219
220int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version,
221 void *new_params, const int new_version)
222{
223 if(old_version == 1 && new_version == 4)
224 {
225 const dt_iop_vignette_params1_t *old = old_params;
226 dt_iop_vignette_params_t *new = new_params;
227 new->scale = old->scale;
228 new->falloff_scale = old->falloff_scale;
229 new->brightness = -(1.0 - MAX(old->bsratio, 0.0)) * old->strength / 100.0;
230 new->saturation = -(1.0 + MIN(old->bsratio, 0.0)) * old->strength / 100.0;
231 if(old->invert_saturation) new->saturation *= -2.0; // Double effect for increasing saturation
232 if(old->invert_falloff) new->brightness = -new->brightness;
233 new->center.x = old->center.x;
234 new->center.y = old->center.y;
235 new->autoratio = TRUE;
236 new->whratio = 1.0;
237 new->shape = 1.0;
238 new->dithering = DITHER_OFF;
239 new->unbound = FALSE;
240 return 0;
241 }
242 if(old_version == 2 && new_version == 4)
243 {
244 const dt_iop_vignette_params2_t *old = old_params;
245 dt_iop_vignette_params_t *new = new_params;
246 new->scale = old->scale;
247 new->falloff_scale = old->falloff_scale;
248 new->brightness = old->brightness;
249 new->saturation = old->saturation;
250 new->center.x = old->center.x;
251 new->center.y = old->center.y;
252 new->autoratio = old->autoratio;
253 new->whratio = old->whratio;
254 new->shape = old->shape;
255 new->dithering = DITHER_OFF;
256 new->unbound = FALSE;
257 return 0;
258 }
259 if(old_version == 3 && new_version == 4)
260 {
261 const dt_iop_vignette_params3_t *old = old_params;
262 dt_iop_vignette_params_t *new = new_params;
263 new->scale = old->scale;
264 new->falloff_scale = old->falloff_scale;
265 new->brightness = old->brightness;
266 new->saturation = old->saturation;
267 new->center.x = old->center.x;
268 new->center.y = old->center.y;
269 new->autoratio = old->autoratio;
270 new->whratio = old->whratio;
271 new->shape = old->shape;
272 new->dithering = old->dithering;
273 new->unbound = FALSE;
274 return 0;
275 }
276
277 return 1;
278}
279
280static int get_grab(dt_iop_module_t *self, float pointerx, float pointery, float startx, float starty, float endx, float endy,
281 float zoom_scale)
282{
283 // trick to convert the radius from image norm to preview abs
284 float radius[2] = { DT_GUI_MOUSE_EFFECT_RADIUS, 0 };
287 const float radius_sq = radius[0] * radius[0];
288
289 if((pointerx - startx) * (pointerx - startx) + pointery * pointery <= radius_sq) return 2; // x size
290 if(pointerx * pointerx + (pointery - starty) * (pointery - starty) <= radius_sq) return 4; // y size
291 if(pointerx * pointerx + pointery * pointery <= radius_sq) return 1; // center
292 if((pointerx - endx) * (pointerx - endx) + pointery * pointery <= radius_sq) return 8; // x falloff
293 if(pointerx * pointerx + (pointery - endy) * (pointery - endy) <= radius_sq) return 16; // y falloff
294
295 return 0;
296}
297
298static void draw_overlay(cairo_t *cr, float x, float y, float fx, float fy, int grab, float zoom_scale)
299{
300 // half width/height of the crosshair
301 const float crosshair_w = DT_PIXEL_APPLY_DPI(10.0) / zoom_scale;
302 const float crosshair_h = DT_PIXEL_APPLY_DPI(10.0) / zoom_scale;
303
304 // center crosshair
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);
309 cairo_stroke(cr);
310
311 // inner border of the vignette
312 cairo_save(cr);
313 if(x <= y)
314 {
315 cairo_scale(cr, x / y, 1.0);
316 cairo_arc(cr, 0.0, 0.0, y, 0.0, M_PI * 2.0);
317 }
318 else
319 {
320 cairo_scale(cr, 1.0, y / x);
321 cairo_arc(cr, 0.0, 0.0, x, 0.0, M_PI * 2.0);
322 }
323 cairo_restore(cr);
324 cairo_stroke(cr);
325
326 // outer border of the vignette
327 cairo_save(cr);
328 if(fx <= fy)
329 {
330 cairo_scale(cr, fx / fy, 1.0);
331 cairo_arc(cr, 0.0, 0.0, fy, 0.0, M_PI * 2.0);
332 }
333 else
334 {
335 cairo_scale(cr, 1.0, fy / fx);
336 cairo_arc(cr, 0.0, 0.0, fx, 0.0, M_PI * 2.0);
337 }
338 cairo_restore(cr);
339 cairo_stroke(cr);
340
341 // the handles
342 const float radius_sel = DT_PIXEL_APPLY_DPI(6.0) / zoom_scale;
343 const float radius_reg = DT_PIXEL_APPLY_DPI(4.0) / zoom_scale;
344 if(grab == 1)
345 cairo_arc(cr, 0.0, 0.0, radius_sel, 0.0, M_PI * 2.0);
346 else
347 cairo_arc(cr, 0.0, 0.0, radius_reg, 0.0, M_PI * 2.0);
348 cairo_stroke(cr);
349 if(grab == 2)
350 cairo_arc(cr, x, 0.0, radius_sel, 0.0, M_PI * 2.0);
351 else
352 cairo_arc(cr, x, 0.0, radius_reg, 0.0, M_PI * 2.0);
353 cairo_stroke(cr);
354 if(grab == 4)
355 cairo_arc(cr, 0.0, -y, radius_sel, 0.0, M_PI * 2.0);
356 else
357 cairo_arc(cr, 0.0, -y, radius_reg, 0.0, M_PI * 2.0);
358 cairo_stroke(cr);
359 if(grab == 8)
360 cairo_arc(cr, fx, 0.0, radius_sel, 0.0, M_PI * 2.0);
361 else
362 cairo_arc(cr, fx, 0.0, radius_reg, 0.0, M_PI * 2.0);
363 cairo_stroke(cr);
364 if(grab == 16)
365 cairo_arc(cr, 0.0, -fy, radius_sel, 0.0, M_PI * 2.0);
366 else
367 cairo_arc(cr, 0.0, -fy, radius_reg, 0.0, M_PI * 2.0);
368 cairo_stroke(cr);
369}
370
371// FIXME: For portrait images the overlay is a bit off. The coordinates in mouse_moved seem to be ok though.
372// WTF?
373void gui_post_expose(struct dt_iop_module_t *self, cairo_t *cr, int32_t width, int32_t height,
374 int32_t pointerx, int32_t pointery)
375{
376 dt_develop_t *dev = self->dev;
379 if(IS_NULL_PTR(g) || IS_NULL_PTR(p)) return;
380
381 const float wd = dt_dev_roi_request_preview_width(dev);
382 const float ht = dt_dev_roi_request_preview_height(dev);
383 float bigger_side, smaller_side;
384 if(wd >= ht)
385 {
386 bigger_side = wd;
387 smaller_side = ht;
388 }
389 else
390 {
391 bigger_side = ht;
392 smaller_side = wd;
393 }
394 const float zoom_scale = dt_dev_get_overlay_scale(dev);
395 float pzxpy[2] = { (float)pointerx, (float)pointery };
397 const float pzx = pzxpy[0];
398 const float pzy = pzxpy[1];
400
401 float vignette_x = (p->center.x + 1.0) * 0.5 * wd;
402 float vignette_y = (p->center.y + 1.0) * 0.5 * ht;
403
404 cairo_translate(cr, vignette_x, vignette_y);
405
406 float vignette_w = p->scale * 0.01 * 0.5 * wd; // start of falloff
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; // end of falloff
409 float vignette_fy = vignette_h + p->falloff_scale * 0.01 * 0.5 * ht;
410
411 if(p->autoratio == FALSE)
412 {
413 float factor1 = bigger_side / smaller_side;
414 if(wd >= ht)
415 {
416 float factor2 = (2.0 - p->whratio) * factor1;
417
418 if(p->whratio <= 1)
419 {
420 vignette_h *= factor1;
421 vignette_w *= p->whratio;
422 vignette_fx *= p->whratio;
423 vignette_fy *= factor1;
424 }
425 else
426 {
427 vignette_h *= factor2;
428 vignette_fy *= factor2;
429 }
430 }
431 else
432 {
433 float factor2 = (p->whratio) * factor1;
434
435 if(p->whratio <= 1)
436 {
437 vignette_w *= factor2;
438 vignette_fx *= factor2;
439 }
440 else
441 {
442 vignette_w *= factor1;
443 vignette_h *= (2.0 - p->whratio);
444 vignette_fx *= factor1;
445 vignette_fy *= (2.0 - p->whratio);
446 }
447 }
448 }
449
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);
453 cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(3.0) / zoom_scale);
455 draw_overlay(cr, vignette_w, vignette_h, vignette_fx, vignette_fy, grab, zoom_scale);
456 cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.0) / zoom_scale);
458 draw_overlay(cr, vignette_w, vignette_h, vignette_fx, vignette_fy, grab, zoom_scale);
459}
460
461// FIXME: Pumping of the opposite direction when changing width/height. See two FIXMEs further down.
462int mouse_moved(struct dt_iop_module_t *self, double x, double y, double pressure, int which)
463{
464 const dt_develop_t *dev = (const dt_develop_t *)self->dev;
467 if(IS_NULL_PTR(g) || IS_NULL_PTR(p)) return 0;
468 const float wd = dt_dev_roi_request_preview_width(dev);
469 const float ht = dt_dev_roi_request_preview_height(dev);
470 float bigger_side, smaller_side;
471 if(wd >= ht)
472 {
473 bigger_side = wd;
474 smaller_side = ht;
475 }
476 else
477 {
478 bigger_side = ht;
479 smaller_side = wd;
480 }
481
482 const float zoom_scale = dt_dev_viewport_scaling(dev);
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;
488 int grab = old_grab;
489
490 float vignette_x = (p->center.x + 1.0) * 0.5 * wd;
491 float vignette_y = (p->center.y + 1.0) * 0.5 * ht;
492
493 float vignette_w = p->scale * 0.01 * 0.5 * wd; // start of falloff
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; // end of falloff
496 float vignette_fy = vignette_h + p->falloff_scale * 0.01 * 0.5 * ht;
497
498 if(p->autoratio == FALSE)
499 {
500 float factor1 = bigger_side / smaller_side;
501 if(wd >= ht)
502 {
503 float factor2 = (2.0 - p->whratio) * factor1;
504
505 if(p->whratio <= 1)
506 {
507 vignette_h *= factor1;
508 vignette_w *= p->whratio;
509 vignette_fx *= p->whratio;
510 vignette_fy *= factor1;
511 }
512 else
513 {
514 vignette_h *= factor2;
515 vignette_fy *= factor2;
516 }
517 }
518 else
519 {
520 float factor2 = (p->whratio) * factor1;
521
522 if(p->whratio <= 1)
523 {
524 vignette_w *= factor2;
525 vignette_fx *= factor2;
526 }
527 else
528 {
529 vignette_w *= factor1;
530 vignette_h *= (2.0 - p->whratio);
531 vignette_fx *= factor1;
532 vignette_fy *= (2.0 - p->whratio);
533 }
534 }
535 }
536
537 if(grab == 0 || !(dt_control_button_down(1)))
538 {
539 grab = get_grab(self, pzx * wd - vignette_x, pzy * ht - vignette_y, vignette_w, -vignette_h, vignette_fx,
540 -vignette_fy, zoom_scale);
541 }
542
544 {
545 if(grab == 0) // pan the image
546 {
547 dt_control_queue_cursor(GDK_HAND1);
548 return 0;
549 }
550 else if(grab == 1) // move the center
551 {
552 dt_bauhaus_slider_set(g->center_x, pzx * 2.0 - 1.0);
553 dt_bauhaus_slider_set(g->center_y, pzy * 2.0 - 1.0);
554 }
555 else if(grab == 2) // change the width
556 {
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;
561 // FIXME: When going over the 1.0 boundary from wide to narrow (>1.0 -> <=1.0) the height slightly
562 // changes, depending on speed.
563 // I guess we have to split the computation.
564 if(ratio <= 1.0)
565 {
567 {
568 dt_bauhaus_slider_set(g->scale, new_scale);
569 }
570 else
571 {
572 dt_bauhaus_slider_set(g->whratio, ratio);
573 }
574 }
575 else
576 {
577 dt_bauhaus_slider_set(g->scale, new_scale);
578
580 {
581 float new_whratio = 2.0 - 1.0 / ratio;
582 dt_bauhaus_slider_set(g->whratio, new_whratio);
583 }
584 }
585 }
586 else if(grab == 4) // change the height
587 {
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);
591 // FIXME: When going over the 1.0 boundary from narrow to wide (>1.0 -> <=1.0) the width slightly
592 // changes, depending on speed.
593 // I guess we have to split the computation.
594 if(ratio <= 1.0)
595 {
597 {
598 const float new_scale = 100.0 * new_vignette_h / max;
599 dt_bauhaus_slider_set(g->scale, new_scale);
600 }
601 else
602 {
603 dt_bauhaus_slider_set(g->whratio, 2.0 - ratio);
604 }
605 }
606 else
607 {
608 const float new_scale = 100.0 * new_vignette_h / max;
609 dt_bauhaus_slider_set(g->scale, new_scale);
610
612 {
613 const float new_whratio = 1.0 / ratio;
614 dt_bauhaus_slider_set(g->whratio, new_whratio);
615 }
616 }
617 }
618 else if(grab == 8) // change the falloff on the right
619 {
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;
624 dt_bauhaus_slider_set(g->falloff_scale, new_falloff);
625 }
626 else if(grab == 16) // change the falloff on the top
627 {
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;
632 dt_bauhaus_slider_set(g->falloff_scale, new_falloff);
633 }
635 return 1;
636 }
637 else if(grab)
638 {
639 if(grab == 1)
640 dt_control_queue_cursor(GDK_FLEUR);
641 else if(grab == 2)
642 dt_control_queue_cursor(GDK_SB_H_DOUBLE_ARROW);
643 else if(grab == 4)
644 dt_control_queue_cursor(GDK_SB_V_DOUBLE_ARROW);
645 else if(grab == 8)
646 dt_control_queue_cursor(GDK_SB_H_DOUBLE_ARROW);
647 else if(grab == 16)
648 dt_control_queue_cursor(GDK_SB_V_DOUBLE_ARROW);
649 }
650 else
651 {
652 if(old_grab != grab) dt_control_queue_cursor(GDK_LEFT_PTR);
653 }
654 old_grab = grab;
656 return 0;
657}
658
659int button_pressed(struct dt_iop_module_t *self, double x, double y, double pressure, int which, int type,
660 uint32_t state)
661{
662 if(which == 1) return 1;
663 return 0;
664}
665
666int button_released(struct dt_iop_module_t *self, double x, double y, int which, uint32_t state)
667{
668 if(which == 1) return 1;
669 return 0;
670}
671
673int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
674 void *const ovoid)
675{
676 const dt_iop_roi_t *const roi_in = &piece->roi_in;
677 const dt_iop_roi_t *const roi_out = &piece->roi_out;
678 const dt_iop_vignette_data_t *data = (dt_iop_vignette_data_t *)piece->data;
679 const dt_iop_roi_t *buf_in = &piece->buf_in;
680 const size_t ch = piece->dsc_in.channels;
681 const gboolean unbound = data->unbound;
682
683 /* Center coordinates of buf_in, these should not consider buf_in->{x,y}! */
684 const dt_iop_vector_2d_t buf_center = { buf_in->width * .5f, buf_in->height * .5f };
685 /* Center coordinates of vignette center */
686 const dt_iop_vector_2d_t vignette_center = { buf_center.x + data->center.x * buf_in->width / 2.0,
687 buf_center.y + data->center.y * buf_in->height / 2.0 };
688 /* Coordinates of vignette_center in terms of roi_in */
689 const dt_iop_vector_2d_t roi_center
690 = { vignette_center.x * roi_in->scale - roi_in->x, vignette_center.y * roi_in->scale - roi_in->y };
691 float xscale;
692 float yscale;
693
694 /* w/h ratio follows piece dimensions */
695 if(data->autoratio)
696 {
697 xscale = 2.0 / (buf_in->width * roi_out->scale);
698 yscale = 2.0 / (buf_in->height * roi_out->scale);
699 }
700 else /* specified w/h ratio, scale proportional to longest side */
701 {
702 const float basis = 2.0 / (MAX(buf_in->height, buf_in->width) * roi_out->scale);
703 // w/h ratio from 0-1 use as-is
704 if(data->whratio <= 1.0)
705 {
706 yscale = basis;
707 xscale = yscale / data->whratio;
708 }
709 // w/h ratio from 1-2 interpret as 1-inf
710 // that is, the h/w ratio + 1
711 else
712 {
713 xscale = basis;
714 yscale = xscale / (2.0 - data->whratio);
715 }
716 }
717 const float dscale = data->scale / 100.0;
718 // A minimum falloff is used, based on the image size, to smooth out aliasing artifacts
719 const float min_falloff = 100.0 / MIN(buf_in->width, buf_in->height);
720 const float fscale = MAX(data->falloff_scale, min_falloff) / 100.0;
721 const float shape = MAX(data->shape, 0.001);
722 const float exp1 = 2.0 / shape;
723 const float exp2 = shape / 2.0;
724 // Pre-scale the center offset
725 const dt_iop_vector_2d_t roi_center_scaled = { roi_center.x * xscale, roi_center.y * yscale };
726
727 float dither = 0.0f;
728
729 switch(data->dithering)
730 {
731 case DITHER_8BIT:
732 dither = 1.0f / 256;
733 break;
734 case DITHER_16BIT:
735 dither = 1.0f / 65536;
736 break;
737 case DITHER_OFF:
738 default:
739 dither = 0.0f;
740 }
741
742 unsigned int *const tea_states = alloc_tea_states(dt_get_num_openmp_threads());
744 for(int j = 0; j < roi_out->height; j++)
745 {
746 const size_t k = (size_t)ch * roi_out->width * j;
747 const float *in = (const float *)ivoid + k;
748 float *out = (float *)ovoid + k;
749 unsigned int *tea_state = get_tea_state(tea_states,dt_get_thread_num());
750 tea_state[0] = j * roi_out->height; /* + dt_get_thread_num() -- do not include, makes results unreproducible */
751 for(int i = 0; i < roi_out->width; i++, in += ch, out += ch)
752 {
753 // current pixel coord translated to local coord
754 const dt_iop_vector_2d_t pv
755 = { fabsf(i * xscale - roi_center_scaled.x), fabsf(j * yscale - roi_center_scaled.y) };
756
757 // Calculate the pixel weight in vignette
758 const float cplen = powf(powf(pv.x, exp1) + powf(pv.y, exp1), exp2); // Length from center to pv
759 float weight = 0.0;
760 float dith = 0.0;
761
762 if(cplen >= dscale) // pixel is outside the inner vignette circle, lets calculate weight of vignette
763 {
764 weight = ((cplen - dscale) / fscale);
765 if(weight >= 1.0)
766 weight = 1.0;
767 else if(weight <= 0.0)
768 weight = 0.0;
769 else if(dither == 0.0f)
770 {
771 // don't bother computing the random number if dithering is disabled
772 dith = 0.0f;
773 }
774 else
775 {
776 weight = 0.5 - cosf(M_PI * weight) / 2.0;
777 encrypt_tea(tea_state);
778 dith = dither * tpdf(tea_state[0]);
779 }
780 }
781
782 // Let's apply weighted effect on brightness and desaturation
783 float col0 = in[0], col1 = in[1], col2 = in[2], col3 = in[3];
784 if(weight > 0)
785 {
786 // Then apply falloff vignette
787 float falloff = (data->brightness < 0) ? (1.0f + (weight * data->brightness))
788 : (weight * data->brightness);
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;
792
793 col0 = unbound ? col0 : CLIP(col0);
794 col1 = unbound ? col1 : CLIP(col1);
795 col2 = unbound ? col2 : CLIP(col2);
796
797 // apply saturation
798 float mv = (col0 + col1 + col2) / 3.0f;
799 float wss = weight * data->saturation;
800 col0 = col0 - ((mv - col0) * wss);
801 col1 = col1 - ((mv - col1) * wss);
802 col2 = col2 - ((mv - col2) * wss);
803
804 col0 = unbound ? col0 : CLIP(col0);
805 col1 = unbound ? col1 : CLIP(col1);
806 col2 = unbound ? col2 : CLIP(col2);
807 }
808
809 out[0] = col0;
810 out[1] = col1;
811 out[2] = col2;
812 out[3] = col3;
813 }
814 }
815
816 free_tea_states(tea_states);
817 return 0;
818}
819
820
821#ifdef HAVE_OPENCL
822int 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)
823{
824 const dt_iop_roi_t *const roi_in = &piece->roi_in;
825 const dt_iop_roi_t *const roi_out = &piece->roi_out;
828
829 cl_int err = -999;
830 const int devid = pipe->devid;
831 const int width = roi_out->width;
832 const int height = roi_out->height;
833
834 const dt_iop_roi_t *buf_in = &piece->buf_in;
835
836 /* Center coordinates of buf_in, these should not consider buf_in->{x,y}! */
837 const dt_iop_vector_2d_t buf_center = { buf_in->width * .5f, buf_in->height * .5f };
838 /* Center coordinates of vignette center */
839 const dt_iop_vector_2d_t vignette_center = { buf_center.x + data->center.x * buf_in->width / 2.0,
840 buf_center.y + data->center.y * buf_in->height / 2.0 };
841 /* Coordinates of vignette_center in terms of roi_in */
842 const dt_iop_vector_2d_t roi_center
843 = { vignette_center.x * roi_in->scale - roi_in->x, vignette_center.y * roi_in->scale - roi_in->y };
844 float xscale;
845 float yscale;
846
847 /* w/h ratio follows piece dimensions */
848 if(data->autoratio)
849 {
850 xscale = 2.0 / (buf_in->width * roi_out->scale);
851 yscale = 2.0 / (buf_in->height * roi_out->scale);
852 }
853 else /* specified w/h ratio, scale proportional to longest side */
854 {
855 const float basis = 2.0 / (MAX(buf_in->height, buf_in->width) * roi_out->scale);
856 // w/h ratio from 0-1 use as-is
857 if(data->whratio <= 1.0)
858 {
859 yscale = basis;
860 xscale = yscale / data->whratio;
861 }
862 // w/h ratio from 1-2 interpret as 1-inf
863 // that is, the h/w ratio + 1
864 else
865 {
866 xscale = basis;
867 yscale = xscale / (2.0 - data->whratio);
868 }
869 }
870 const float dscale = data->scale / 100.0;
871 // A minimum falloff is used, based on the image size, to smooth out aliasing artifacts
872 const float min_falloff = 100.0 / MIN(buf_in->width, buf_in->height);
873 const float fscale = MAX(data->falloff_scale, min_falloff) / 100.0;
874 const float shape = MAX(data->shape, 0.001);
875 const float exp1 = 2.0 / shape;
876 const float exp2 = shape / 2.0;
877 // Pre-scale the center offset
878 const dt_iop_vector_2d_t roi_center_scaled = { roi_center.x * xscale, roi_center.y * yscale };
879
880 float dither = 0.0f;
881
882 switch(data->dithering)
883 {
884 case DITHER_8BIT:
885 dither = 1.0f / 256;
886 break;
887 case DITHER_16BIT:
888 dither = 1.0f / 65536;
889 break;
890 case DITHER_OFF:
891 default:
892 dither = 0.0f;
893 }
894
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 };
898 const float brightness = data->brightness;
899 const float saturation = data->saturation;
900 const int unbound = data->unbound;
901
902 size_t sizes[2] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid) };
903
904 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 0, sizeof(cl_mem), &dev_in);
905 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 1, sizeof(cl_mem), &dev_out);
906 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 2, sizeof(int), &width);
907 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 3, sizeof(int), &height);
908 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 4, 2 * sizeof(float), &scale);
909 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 5, 2 * sizeof(float), &roi_center_scaled_f);
910 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 6, 2 * sizeof(float), &expt);
911 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 7, sizeof(float), &dscale);
912 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 8, sizeof(float), &fscale);
913 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 9, sizeof(float), &brightness);
914 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 10, sizeof(float), &saturation);
915 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 11, sizeof(float), &dither);
916 dt_opencl_set_kernel_arg(devid, gd->kernel_vignette, 12, sizeof(int), &unbound);
917 err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_vignette, sizes);
918 if(err != CL_SUCCESS) goto error;
919
920 return TRUE;
921
922error:
923 dt_print(DT_DEBUG_OPENCL, "[opencl_vignette] couldn't enqueue kernel! %d\n", err);
924 return FALSE;
925}
926#endif
927
928
930{
931 const int program = 8; // extended.cl from programs.conf
934 module->data = gd;
935 gd->kernel_vignette = dt_opencl_create_kernel(program, "vignette");
936}
937
938
945
946
947void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
948{
951 if(IS_NULL_PTR(g) || IS_NULL_PTR(p)) return;
952
953 gtk_widget_set_sensitive(GTK_WIDGET(g->whratio), !p->autoratio);
954}
955
958{
961 d->scale = p->scale;
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;
968 d->shape = p->shape;
969 d->dithering = p->dithering;
970 d->unbound = p->unbound;
971}
972
974{
977 p.scale = 40.0f;
978 p.falloff_scale = 100.0f;
979 p.brightness = -1.0f;
980 p.saturation = 0.5f;
981 p.center.x = 0.0f;
982 p.center.y = 0.0f;
983 p.autoratio = FALSE;
984 p.whratio = 1.0f;
985 p.shape = 1.0f;
986 p.dithering = 0;
987 p.unbound = TRUE;
988 dt_gui_presets_add_generic(_("lomo"), self->op,
989 self->version(), &p, sizeof(p), 1);
991}
992
994{
996 piece->data_size = sizeof(dt_iop_vignette_data_t);
997}
998
1000{
1001 dt_free_align(piece->data);
1002 piece->data = NULL;
1003}
1004
1005void gui_update(struct dt_iop_module_t *self)
1006{
1009 if(IS_NULL_PTR(g) || IS_NULL_PTR(p)) return;
1010 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autoratio), p->autoratio);
1011 gtk_widget_set_sensitive(GTK_WIDGET(g->whratio), !p->autoratio);
1012}
1013
1014void gui_init(struct dt_iop_module_t *self)
1015{
1017
1018 g->scale = dt_bauhaus_slider_from_params(self, N_("scale"));
1019 g->falloff_scale = dt_bauhaus_slider_from_params(self, "falloff_scale");
1020 g->brightness = dt_bauhaus_slider_from_params(self, N_("brightness"));
1021 g->saturation = dt_bauhaus_slider_from_params(self, N_("saturation"));
1022
1023 gtk_box_pack_start(GTK_BOX(self->gui->widget),
1024 dt_ui_section_label_new(_("position / form")), FALSE, FALSE, 0);
1025
1026 g->center_x = dt_bauhaus_slider_from_params(self, "center.x");
1027 g->center_y = dt_bauhaus_slider_from_params(self, "center.y");
1028 g->shape = dt_bauhaus_slider_from_params(self, N_("shape"));
1029 g->autoratio = dt_bauhaus_toggle_from_params(self, "autoratio");
1030 g->whratio = dt_bauhaus_slider_from_params(self, "whratio");
1031 g->dithering = dt_bauhaus_combobox_from_params(self, N_("dithering"));
1032
1033 dt_bauhaus_slider_set_digits(g->brightness, 3);
1034 dt_bauhaus_slider_set_digits(g->saturation, 3);
1035 dt_bauhaus_slider_set_digits(g->center_x, 3);
1036 dt_bauhaus_slider_set_digits(g->center_y, 3);
1037 dt_bauhaus_slider_set_digits(g->whratio, 3);
1038
1039 dt_bauhaus_slider_set_format(g->scale, "%");
1040 dt_bauhaus_slider_set_format(g->falloff_scale, "%");
1041
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"));
1053}
1054
1055// clang-format off
1056// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1057// vim: shiftwidth=2 expandtab tabstop=2 cindent
1058// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1059// clang-format on
Handle default and user-set shortcuts (accelerators)
#define DT_PRIMARY_MASK
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:3343
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
Definition bauhaus.c:3331
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3407
@ IOP_CS_RGB
static const float x
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
const float max
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_control_queue_redraw_center()
Request a redraw of the centre view.
Definition control.c:924
gboolean dt_control_button_down(int which)
Is mouse button which currently held down?
Definition control.c:563
#define dt_control_queue_cursor(cursor)
Definition control.h:140
int dt_get_num_openmp_threads(void)
Number of OpenMP threads the application decided to use.
Definition darktable.c:518
#define dt_database_start_transaction()
Definition database.h:290
#define dt_database_release_transaction()
Definition database.h:291
void dt_iop_params_t
Definition dev_history.h:43
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)
Definition develop.c:1219
float dt_dev_get_overlay_scale(dt_develop_t *dev)
Get the overlay scale factor in GUI logical coordinates.
Definition develop.c:1959
void dt_dev_coordinates_image_norm_to_preview_abs(dt_develop_t *dev, float *points, size_t num_points)
Definition develop.c:1291
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:2071
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:1144
static void dt_draw_set_color_overlay(cairo_t *cr, gboolean bright, double alpha)
Definition draw.h:147
static void weight(const float *c1, const float *c2, const float sharpen, dt_aligned_pixel_t weight)
Definition eaw.c:29
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)
Definition imageop.c:1893
@ IOP_FLAGS_INCLUDE_IN_STYLES
Definition imageop.h:185
@ IOP_FLAGS_SUPPORTS_BLENDING
Definition imageop.h:186
@ IOP_FLAGS_ALLOW_TILING
Definition imageop.h:188
@ IOP_FLAGS_TILING_FULL_ROI
Definition imageop.h:190
@ IOP_GROUP_EFFECTS
Definition imageop.h:161
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...
Definition imageop_gui.h:81
#define IOP_GUI_ALLOC(module)
Definition imageop_gui.h:93
void *const ovoid
Which mouse buttons are held, asked of the toolkit rather than remembered.
GtkWidget * dt_ui_section_label_new(const gchar *str)
Definition label.c:114
dt_iop_dither_t
Definition lightroom.c:110
_lib_location_type_t type
Definition location.c:1
@ DT_DEBUG_OPENCL
Definition logging.h:57
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...
Definition macros.h:96
#define CLIP(x)
Definition math.h:83
#define M_PI
Definition math.h:47
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
Definition mem_alloc.h:214
static void * dt_calloc_align(size_t size)
dt_alloc_align() followed by a zero fill.
Definition mem_alloc.h:225
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
#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)
Definition opencl.c:2554
int dt_opencl_create_kernel(const int prog, const char *name)
Definition opencl.c:2448
void dt_opencl_free_kernel(const int kernel)
Definition opencl.c:2491
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:2545
#define ROUNDUPDHT(a, b)
Definition opencl.h:86
#define ROUNDUPDWD(a, b)
Definition opencl.h:85
static int dt_get_thread_num()
Index of the calling thread within its parallel region, 0 outside one.
Definition openmp.h:129
#define __OMP_PARALLEL_FOR__(...)
Definition openmp.h:95
const float uint32_t state[4]
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
unsigned int channels
Definition format.h:83
GtkWidget * widget
Definition imageop_gui.h:47
dt_dev_operation_t op
Definition imageop.h:235
dt_iop_global_data_t * data
Definition imageop.h:238
struct dt_iop_module_gui_t * gui
Definition imageop.h:346
struct dt_develop_t * dev
Definition imageop.h:311
dt_iop_global_data_t * global_data
Definition imageop.h:337
dt_iop_params_t * params
Definition imageop.h:333
Region of interest passed through the pixelpipe.
Definition format.h:49
double scale
Definition format.h:51
int width
Definition format.h:50
int height
Definition format.h:50
dt_iop_vector_2d_t center
Definition vignette.c:176
dt_iop_dvector_2d_t center
Definition vignette.c:113
dt_iop_vector_2d_t center
Definition vignette.c:122
dt_iop_vector_2d_t center
Definition vignette.c:134
dt_iop_dither_t dithering
Definition vignette.c:151
dt_iop_vector_2d_t center
Definition lightroom.c:129
#define __DT_CLONE_TARGETS__
static float tpdf(unsigned int urandom)
Definition tea.h:74
static unsigned int * get_tea_state(unsigned int *const states, int threadnum)
Definition tea.h:43
static void free_tea_states(unsigned int *states)
Definition tea.h:48
static unsigned int * alloc_tea_states(size_t numthreads)
Definition tea.h:34
static void encrypt_tea(unsigned int *arg)
Definition tea.h:58
#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:280
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:956
const char ** description(struct dt_iop_module_t *self)
Definition vignette.c:195
int default_group()
Definition vignette.c:210
__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:673
dt_iop_dither_t
Definition vignette.c:85
@ DITHER_16BIT
Definition vignette.c:88
@ DITHER_8BIT
Definition vignette.c:87
@ DITHER_OFF
Definition vignette.c:86
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition vignette.c:993
const char * name()
Definition vignette.c:190
void gui_update(struct dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
Definition vignette.c:1005
void gui_init(struct dt_iop_module_t *self)
Definition vignette.c:1014
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:659
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
Definition vignette.c:947
int button_released(struct dt_iop_module_t *self, double x, double y, int which, uint32_t state)
Definition vignette.c:666
void cleanup_global(dt_iop_module_so_t *module)
Definition vignette.c:939
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition vignette.c:215
int flags()
Definition vignette.c:204
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:373
void init_presets(dt_iop_module_so_t *self)
Definition vignette.c:973
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:999
void init_global(dt_iop_module_so_t *module)
Definition vignette.c:929
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:822
int mouse_moved(struct dt_iop_module_t *self, double x, double y, double pressure, int which)
Definition vignette.c:462
static void draw_overlay(cairo_t *cr, float x, float y, float fx, float fy, int grab, float zoom_scale)
Definition vignette.c:298
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:220
static gboolean dt_modifier_is(GdkModifierType state, const GdkModifierType desired_modifier_mask)
#define DT_GUI_MOUSE_EFFECT_RADIUS
#define DT_PIXEL_APPLY_DPI(value)