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 "widgets/bauhaus.h"
55#include "pixel/box_filters.h"
57#include "common/imagebuf.h"
58#include "math/math.h"
59#include "develop/develop.h"
60#include "develop/imageop.h"
61#include "develop/imageop_gui.h"
62#include "develop/tiling.h"
63
64#include "iop/iop_api.h"
65#include <gtk/gtk.h>
66#include <inttypes.h>
67
68
69#define MAX_RADIUS 32
70
72
74{
75 float size; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 50.0
76 float saturation; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 100.0
77 float brightness; // $MIN: -2.0 $MAX: 2.0 $DEFAULT: 0.33
78 float amount; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 50.0 $DESCRIPTION: "mix"
80
85
93
94const char *name()
95{
96 return _("soften");
97}
98
103
105{
106 return IOP_GROUP_EFFECTS;
107}
108
110{
111 return IOP_CS_RGB;
112}
113
114const char **description(struct dt_iop_module_t *self)
115{
116 return dt_iop_set_description(self, _("create a softened image using the Orton effect"),
117 _("creative"),
118 _("linear, RGB, display-referred"),
119 _("linear, RGB"),
120 _("linear, RGB, display-referred"));
121}
122
124int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
125 void *const ovoid)
126{
127 (void)self;
128 (void)pipe;
129 const dt_iop_roi_t *const roi_in = &piece->roi_in;
130 const dt_iop_roi_t *const roi_out = &piece->roi_out;
131 const dt_iop_soften_data_t *const d = (const dt_iop_soften_data_t *const)piece->data;
132
133 const float brightness = 1.0 / exp2f(-d->brightness);
134 const float saturation = d->saturation / 100.0;
135
136 const float *const restrict in = (const float *const)ivoid;
137 float *const restrict out = (float *const)ovoid;
138
139 const size_t npixels = (size_t)roi_out->width * roi_out->height;
140/* create overexpose image and then blur */
142 for(size_t k = 0; k < 4 * npixels; k += 4)
143 {
144 float h, s, l;
145 rgb2hsl(&in[k], &h, &s, &l);
146 s *= saturation;
147 l *= brightness;
148 hsl2rgb(&out[k], h, CLIP(s), CLIP(l));
149 }
150
151 const float w = piece->iwidth;
152 const float h = piece->iheight;
153 const int mrad = sqrt(w * w + h * h) * 0.01;
154 const int rad = mrad * (fmin(100.0, d->size + 1) / 100.0);
155 const int radius = MIN(mrad, ceilf(rad * roi_in->scale));
156
157 if(dt_box_mean(out, roi_out->height, roi_out->width, 4, radius, BOX_ITERATIONS) != 0)
158 {
159 return 1;
160 }
161
162 const float amt = d->amount / 100.0f;
163 dt_iop_image_linear_blend(out, amt, in, roi_out->width, roi_out->height, 4);
164
165 return 0;
166}
167
168void 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)
169{
170 (void)self;
171 (void)pipe;
172 const dt_iop_roi_t *const roi_in = &piece->roi_in;
174
175 const float w = piece->iwidth;
176 const float h = piece->iheight;
177 const int mrad = sqrt(w * w + h * h) * 0.01f;
178
179 const int rad = mrad * (fmin(100.0f, d->size + 1) / 100.0f);
180 const int radius = MIN(mrad, ceilf(rad * roi_in->scale));
181
182 /* sigma-radius correlation to match opencl vs. non-opencl. identified by numerical experiments but
183 * unproven. ask me if you need details. ulrich */
184 const float sigma = sqrtf((radius * (radius + 1) * BOX_ITERATIONS + 2) / 3.0f);
185 const int wdh = ceilf(3.0f * sigma);
186
187 tiling->factor = 2.1f; // in + out + small slice for box_mean
188 tiling->factor_cl = 3.0f; // in + out + tmp
189 tiling->maxbuf = 1.0f;
190 tiling->overhead = 0;
191 tiling->overlap = wdh;
192 tiling->xalign = 1;
193 tiling->yalign = 1;
194 return;
195}
196
199{
202
203 d->size = p->size;
204 d->saturation = p->saturation;
205 d->brightness = p->brightness;
206 d->amount = p->amount;
207}
208
210{
211 piece->data = dt_calloc_align(sizeof(dt_iop_soften_data_t));
212 piece->data_size = sizeof(dt_iop_soften_data_t);
213}
214
216{
217 dt_free_align(piece->data);
218 piece->data = NULL;
219}
220
221void gui_init(struct dt_iop_module_t *self)
222{
224
225 g->size = dt_bauhaus_slider_from_params(self, N_("size"));
227 gtk_widget_set_tooltip_text(g->size, _("the size of blur"));
228
229 g->saturation = dt_bauhaus_slider_from_params(self, N_("saturation"));
230 dt_bauhaus_slider_set_format(g->saturation, "%");
231 gtk_widget_set_tooltip_text(g->saturation, _("the saturation of blur"));
232
233 g->brightness = dt_bauhaus_slider_from_params(self, N_("brightness"));
234 dt_bauhaus_slider_set_format(g->brightness, _(" EV"));
235 gtk_widget_set_tooltip_text(g->brightness, _("the brightness of blur"));
236
237 g->amount = dt_bauhaus_slider_from_params(self, "amount");
238 dt_bauhaus_slider_set_format(g->amount, "%");
239 gtk_widget_set_tooltip_text(g->amount, _("the mix of effect"));
240}
241
242// clang-format off
243// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
244// vim: shiftwidth=2 expandtab tabstop=2 cindent
245// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
246// clang-format on
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3407
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:33
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
@ IOP_CS_RGB
void rgb2hsl(const dt_aligned_pixel_t rgb, float *h, float *s, float *l)
Convert RGB to HSL. Common helper used by iop modules.
void hsl2rgb(dt_aligned_pixel_t rgb, float h, float s, float l)
Convert HSL back to RGB. Common helper used by iop modules.
The colour-profile module's API: which profiles exist, and how to apply one.
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_iop_params_t
Definition dev_history.h:43
__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:406
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_DEPRECATED
Definition imageop.h:187
@ IOP_FLAGS_SUPPORTS_BLENDING
Definition imageop.h:186
@ IOP_FLAGS_ALLOW_TILING
Definition imageop.h:188
@ IOP_GROUP_EFFECTS
Definition imageop.h:161
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
#define IOP_GUI_ALLOC(module)
Definition imageop_gui.h:93
void *const ovoid
float *const restrict const size_t k
#define CLIP(x)
Definition math.h:83
#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_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
#define __OMP_PARALLEL_FOR__(...)
Definition openmp.h:95
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:197
const char ** description(struct dt_iop_module_t *self)
Definition soften.c:114
int default_group()
Definition soften.c:104
__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:124
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition soften.c:209
const char * name()
Definition soften.c:94
void gui_init(struct dt_iop_module_t *self)
Definition soften.c:221
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:168
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition soften.c:109
int flags()
Definition soften.c:99
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition soften.c:215
const float sigma
struct dt_iop_module_t *void * data
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
GtkWidget * brightness
Definition soften.c:83
GtkWidget * saturation
Definition soften.c:83
GtkWidget * amount
Definition soften.c:83
#define __DT_CLONE_TARGETS__
#define MIN(a, b)
Definition thinplate.c:32