Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
soften.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011 Antony Dovgal.
4 Copyright (C) 2011, 2013 Bruce Guenter.
5 Copyright (C) 2011-2012 Henrik Andersson.
6 Copyright (C) 2011-2013, 2016 johannes hanika.
7 Copyright (C) 2011 Jérémy Rosen.
8 Copyright (C) 2011 Olivier Tribout.
9 Copyright (C) 2011 Robert Bieber.
10 Copyright (C) 2011-2014, 2016, 2019 Tobias Ellinghaus.
11 Copyright (C) 2012 Richard Wonka.
12 Copyright (C) 2012, 2014, 2016-2017 Ulrich Pegelow.
13 Copyright (C) 2013 Jean-Sébastien Pédron.
14 Copyright (C) 2014-2016 Roman Lebedev.
15 Copyright (C) 2015 Pedro Côrte-Real.
16 Copyright (C) 2017 Heiko Bauke.
17 Copyright (C) 2018-2020, 2022-2023, 2025-2026 Aurélien PIERRE.
18 Copyright (C) 2018 Edgardo Hoszowski.
19 Copyright (C) 2018 Maurizio Paglia.
20 Copyright (C) 2018-2022 Pascal Obry.
21 Copyright (C) 2018 rawfiner.
22 Copyright (C) 2019 Andreas Schneider.
23 Copyright (C) 2020 Aldric Renaudin.
24 Copyright (C) 2020, 2022 Diederik Ter Rahe.
25 Copyright (C) 2020 Hubert Kowalski.
26 Copyright (C) 2020-2021 Ralf Brown.
27 Copyright (C) 2022 Hanno Schwalm.
28 Copyright (C) 2022 Martin Bařinka.
29 Copyright (C) 2022 Philipp Lutz.
30
31 darktable is free software: you can redistribute it and/or modify
32 it under the terms of the GNU General Public License as published by
33 the Free Software Foundation, either version 3 of the License, or
34 (at your option) any later version.
35
36 darktable is distributed in the hope that it will be useful,
37 but WITHOUT ANY WARRANTY; without even the implied warranty of
38 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 GNU General Public License for more details.
40
41 You should have received a copy of the GNU General Public License
42 along with darktable. If not, see <http://www.gnu.org/licenses/>.
43*/
44#ifdef HAVE_CONFIG_H
45#include "config.h"
46#endif
47#include <assert.h>
48#include <math.h>
49#include <stdlib.h>
50#include <string.h>
51
52#include "bauhaus/bauhaus.h"
53#include "common/box_filters.h"
54#include "common/colorspaces.h"
55#include "common/imagebuf.h"
56#include "common/math.h"
57#include "common/opencl.h"
58#include "control/control.h"
59#include "develop/develop.h"
60#include "develop/imageop.h"
61#include "develop/imageop_gui.h"
62#include "develop/tiling.h"
63#include "dtgtk/resetlabel.h"
64
65#include "gui/gtk.h"
66#include "iop/iop_api.h"
67#include <gtk/gtk.h>
68#include <inttypes.h>
69
70
71#define MAX_RADIUS 32
72
74
76{
77 float size; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 50.0
78 float saturation; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 100.0
79 float brightness; // $MIN: -2.0 $MAX: 2.0 $DEFAULT: 0.33
80 float amount; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 50.0 $DESCRIPTION: "mix"
82
87
95
96const char *name()
97{
98 return _("soften");
99}
100
105
107{
108 return IOP_GROUP_EFFECTS;
109}
110
112{
113 return IOP_CS_RGB;
114}
115
116const char **description(struct dt_iop_module_t *self)
117{
118 return dt_iop_set_description(self, _("create a softened image using the Orton effect"),
119 _("creative"),
120 _("linear, RGB, display-referred"),
121 _("linear, RGB"),
122 _("linear, RGB, display-referred"));
123}
124
126int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
127 void *const ovoid)
128{
129 (void)self;
130 (void)pipe;
131 const dt_iop_roi_t *const roi_in = &piece->roi_in;
132 const dt_iop_roi_t *const roi_out = &piece->roi_out;
133 const dt_iop_soften_data_t *const d = (const dt_iop_soften_data_t *const)piece->data;
134
135 const float brightness = 1.0 / exp2f(-d->brightness);
136 const float saturation = d->saturation / 100.0;
137
138 const float *const restrict in = (const float *const)ivoid;
139 float *const restrict out = (float *const)ovoid;
140
141 const size_t npixels = (size_t)roi_out->width * roi_out->height;
142/* create overexpose image and then blur */
144 for(size_t k = 0; k < 4 * npixels; k += 4)
145 {
146 float h, s, l;
147 rgb2hsl(&in[k], &h, &s, &l);
148 s *= saturation;
149 l *= brightness;
150 hsl2rgb(&out[k], h, CLIP(s), CLIP(l));
151 }
152
153 const float w = piece->iwidth;
154 const float h = piece->iheight;
155 const int mrad = sqrt(w * w + h * h) * 0.01;
156 const int rad = mrad * (fmin(100.0, d->size + 1) / 100.0);
157 const int radius = MIN(mrad, ceilf(rad * roi_in->scale));
158
159 if(dt_box_mean(out, roi_out->height, roi_out->width, 4, radius, BOX_ITERATIONS) != 0)
160 {
161 return 1;
162 }
163
164 const float amt = d->amount / 100.0f;
165 dt_iop_image_linear_blend(out, amt, in, roi_out->width, roi_out->height, 4);
166
167 return 0;
168}
169
170void tiling_callback(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, struct dt_develop_tiling_t *tiling)
171{
172 (void)self;
173 (void)pipe;
174 const dt_iop_roi_t *const roi_in = &piece->roi_in;
176
177 const float w = piece->iwidth;
178 const float h = piece->iheight;
179 const int mrad = sqrt(w * w + h * h) * 0.01f;
180
181 const int rad = mrad * (fmin(100.0f, d->size + 1) / 100.0f);
182 const int radius = MIN(mrad, ceilf(rad * roi_in->scale));
183
184 /* sigma-radius correlation to match opencl vs. non-opencl. identified by numerical experiments but
185 * unproven. ask me if you need details. ulrich */
186 const float sigma = sqrtf((radius * (radius + 1) * BOX_ITERATIONS + 2) / 3.0f);
187 const int wdh = ceilf(3.0f * sigma);
188
189 tiling->factor = 2.1f; // in + out + small slice for box_mean
190 tiling->factor_cl = 3.0f; // in + out + tmp
191 tiling->maxbuf = 1.0f;
192 tiling->overhead = 0;
193 tiling->overlap = wdh;
194 tiling->xalign = 1;
195 tiling->yalign = 1;
196 return;
197}
198
201{
204
205 d->size = p->size;
206 d->saturation = p->saturation;
207 d->brightness = p->brightness;
208 d->amount = p->amount;
209}
210
212{
213 piece->data = dt_calloc_align(sizeof(dt_iop_soften_data_t));
214 piece->data_size = sizeof(dt_iop_soften_data_t);
215}
216
218{
219 dt_free_align(piece->data);
220 piece->data = NULL;
221}
222
223void gui_init(struct dt_iop_module_t *self)
224{
226
227 g->size = dt_bauhaus_slider_from_params(self, N_("size"));
229 gtk_widget_set_tooltip_text(g->size, _("the size of blur"));
230
231 g->saturation = dt_bauhaus_slider_from_params(self, N_("saturation"));
232 dt_bauhaus_slider_set_format(g->saturation, "%");
233 gtk_widget_set_tooltip_text(g->saturation, _("the saturation of blur"));
234
235 g->brightness = dt_bauhaus_slider_from_params(self, N_("brightness"));
236 dt_bauhaus_slider_set_format(g->brightness, _(" EV"));
237 gtk_widget_set_tooltip_text(g->brightness, _("the brightness of blur"));
238
239 g->amount = dt_bauhaus_slider_from_params(self, "amount");
240 dt_bauhaus_slider_set_format(g->amount, "%");
241 gtk_widget_set_tooltip_text(g->amount, _("the mix of effect"));
242}
243
244// clang-format off
245// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
246// vim: shiftwidth=2 expandtab tabstop=2 cindent
247// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
248// clang-format on
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3598
int dt_box_mean(float *const buf, const size_t height, const size_t width, const int ch, const int radius, const unsigned iterations)
#define BOX_ITERATIONS
Definition box_filters.h:32
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
@ IOP_CS_RGB
void rgb2hsl(const dt_aligned_pixel_t rgb, float *h, float *s, float *l)
void hsl2rgb(dt_aligned_pixel_t rgb, float h, float s, float l)
const dt_colormatrix_t dt_aligned_pixel_t out
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
#define dt_free_align(ptr)
Definition darktable.h:481
static void * dt_calloc_align(size_t size)
Definition darktable.h:488
#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
void dt_iop_params_t
Definition dev_history.h:41
__DT_CLONE_TARGETS__ void dt_iop_image_linear_blend(float *const restrict buf, const float lambda, const float *const restrict other, const size_t width, const size_t height, const size_t ch)
Definition imagebuf.c:402
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_DEPRECATED
Definition imageop.h:168
@ IOP_FLAGS_SUPPORTS_BLENDING
Definition imageop.h:167
@ IOP_FLAGS_ALLOW_TILING
Definition imageop.h:169
@ IOP_GROUP_EFFECTS
Definition imageop.h:142
#define IOP_GUI_ALLOC(module)
Definition imageop.h:599
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
Definition imageop_gui.c:77
void *const ovoid
float *const restrict const size_t k
#define CLIP(x)
Definition math.h:81
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 soften.c:199
const char ** description(struct dt_iop_module_t *self)
Definition soften.c:116
int default_group()
Definition soften.c:106
__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 soften.c:126
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition soften.c:211
const char * name()
Definition soften.c:96
void gui_init(struct dt_iop_module_t *self)
Definition soften.c:223
void tiling_callback(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, struct dt_develop_tiling_t *tiling)
Definition soften.c:170
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition soften.c:111
int flags()
Definition soften.c:101
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition soften.c:217
struct _GtkWidget GtkWidget
Definition splash.h:29
const float sigma
struct dt_iop_module_t *void * data
Region of interest passed through the pixelpipe.
Definition imageop.h:72
double scale
Definition imageop.h:74
GtkWidget * brightness
Definition soften.c:85
GtkWidget * saturation
Definition soften.c:85
GtkWidget * amount
Definition soften.c:85
#define MIN(a, b)
Definition thinplate.c:32