Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
bloom.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2013, 2016 johannes hanika.
4 Copyright (C) 2010-2011 Bruce Guenter.
5 Copyright (C) 2010-2012 Henrik Andersson.
6 Copyright (C) 2010 jan rinze.
7 Copyright (C) 2010 Pascal de Bruijn.
8 Copyright (C) 2011 Antony Dovgal.
9 Copyright (C) 2011 Olivier Tribout.
10 Copyright (C) 2011 Robert Bieber.
11 Copyright (C) 2011-2016, 2019 Tobias Ellinghaus.
12 Copyright (C) 2012 Richard Wonka.
13 Copyright (C) 2012, 2014, 2016-2017 Ulrich Pegelow.
14 Copyright (C) 2013 Simon Spannagel.
15 Copyright (C) 2014-2016 Roman Lebedev.
16 Copyright (C) 2015, 2018, 2020-2022 Pascal Obry.
17 Copyright (C) 2015 Pedro Côrte-Real.
18 Copyright (C) 2017 Heiko Bauke.
19 Copyright (C) 2018, 2020, 2022-2023, 2025-2026 Aurélien PIERRE.
20 Copyright (C) 2018 Edgardo Hoszowski.
21 Copyright (C) 2018 Maurizio Paglia.
22 Copyright (C) 2018 rawfiner.
23 Copyright (C) 2019 Andreas Schneider.
24 Copyright (C) 2020 Aldric Renaudin.
25 Copyright (C) 2020, 2022 Diederik Ter Rahe.
26 Copyright (C) 2020 Hubert Kowalski.
27 Copyright (C) 2020-2021 Ralf Brown.
28 Copyright (C) 2022 Hanno Schwalm.
29 Copyright (C) 2022 Martin Bařinka.
30 Copyright (C) 2022 Philipp Lutz.
31
32 darktable is free software: you can redistribute it and/or modify
33 it under the terms of the GNU General Public License as published by
34 the Free Software Foundation, either version 3 of the License, or
35 (at your option) any later version.
36
37 darktable is distributed in the hope that it will be useful,
38 but WITHOUT ANY WARRANTY; without even the implied warranty of
39 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 GNU General Public License for more details.
41
42 You should have received a copy of the GNU General Public License
43 along with darktable. If not, see <http://www.gnu.org/licenses/>.
44*/
45#ifdef HAVE_CONFIG_H
46#include "config.h"
47#endif
48#include "bauhaus/bauhaus.h"
49#include "common/box_filters.h"
50#include "common/imagebuf.h"
51#include "common/math.h"
52#include "common/opencl.h"
53#include "control/control.h"
54#include "develop/develop.h"
55#include "develop/imageop.h"
57#include "develop/imageop_gui.h"
58#include "develop/tiling.h"
59
60#include "gui/gtk.h"
61#include "iop/iop_api.h"
62
63#include <assert.h>
64#include <gtk/gtk.h>
65#include <inttypes.h>
66#include <stdlib.h>
67#include <string.h>
68
69#define NUM_BUCKETS 4 /* OpenCL bucket chain size for tmp buffers; minimum 2 */
70
72
74{
75 float size; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 20.0
76 float threshold; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 90.0
77 float strength; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 25.0
79
81{
82 GtkWidget *size, *threshold, *strength; // size,threshold,strength
84
91
92const char *name()
93{
94 return _("bloom");
95}
96
97const char **description(struct dt_iop_module_t *self)
98{
99 return dt_iop_set_description(self, _("apply Orton effect for a dreamy aetherical look"),
100 _("creative"),
101 _("non-linear, Lab, display-referred"),
102 _("non-linear, Lab"),
103 _("non-linear, Lab, display-referred"));
104}
105
106
111
113{
114 return IOP_GROUP_EFFECTS;
115}
116
118{
119 return IOP_CS_LAB;
120}
121
123int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
124 void *const ovoid)
125{
126 const dt_iop_roi_t *const roi_in = &piece->roi_in;
127 const dt_iop_roi_t *const roi_out = &piece->roi_out;
128 const dt_iop_bloom_data_t *const data = (dt_iop_bloom_data_t *)piece->data;
129
130 float *restrict blurlightness;
131 if (dt_iop_alloc_image_buffers(self, roi_in, roi_out, 1, &blurlightness, 0))
132 {
133 // out of memory, so just copy image through to output
134 dt_iop_copy_image_roi(ovoid, ivoid, piece->dsc_in.channels, roi_in, roi_out, TRUE);
135 return 1;
136 }
137
138 const float *const restrict in = DT_IS_ALIGNED((float *)ivoid);
139 float *const restrict out = DT_IS_ALIGNED((float *)ovoid);
140 const size_t npixels = (size_t)roi_out->width * roi_out->height;
141
142 /* gather light by threshold */
143 const int rad = 256.0f * (fmin(100.0f, data->size + 1.0f) / 100.0f);
144 const float _r = ceilf(rad * roi_in->scale);
145 const int radius = MIN(256.0f, _r);
146
147 const float scale = 1.0f / exp2f(-1.0f * (fmin(100.0f, data->strength + 1.0f) / 100.0f));
148
149 const float threshold = data->threshold;
150/* get the thresholded lights into buffer */
152 for(size_t k = 0; k < npixels; k++)
153 {
154 const float L = in[4*k] * scale;
155 blurlightness[k] = (L > threshold) ? L : 0.0f;
156 }
157
158 /* horizontal blur into memchannel lightness */
159 const int range = 2 * radius + 1;
160 const int hr = range / 2;
161
162 if(dt_box_mean(blurlightness, roi_out->height, roi_out->width, 1, hr, BOX_ITERATIONS) != 0)
163 {
164 dt_pixelpipe_cache_free_align(blurlightness);
165 return 1;
166 }
167
168/* screen blend lightness with original */
170 for(size_t k = 0; k < npixels; k++)
171 {
172 out[4*k+0] = 100.0f - (((100.0f - in[4*k]) * (100.0f - blurlightness[k])) / 100.0f); // Screen blend
173 out[4*k+1] = in[4*k+1];
174 out[4*k+2] = in[4*k+2];
175 out[4*k+3] = in[4*k+3];
176 }
177 dt_pixelpipe_cache_free_align(blurlightness);
178
179// if(pipe->mask_display & DT_DEV_PIXELPIPE_DISPLAY_MASK)
180// dt_iop_alpha_copy(ivoid, ovoid, roi_out->width, roi_out->height);
181
182 return 0;
183}
184
185void 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)
186{
187 (void)self;
188 (void)pipe;
189 const dt_iop_roi_t *const roi_in = &piece->roi_in;
191
192 const int rad = 256.0f * (fmin(100.0f, d->size + 1.0f) / 100.0f);
193 const float _r = ceilf(rad * roi_in->scale);
194 const int radius = MIN(256.0f, _r);
195
196 tiling->factor = 2.0f + 0.25f + 0.05f; // in + out + blurlightness + slice for dt_box_mean
197 tiling->factor_cl = 2.0f + NUM_BUCKETS * 0.25f; // in + out + NUM_BUCKETS * 0.25 tmp
198 tiling->maxbuf = 1.0f;
199 tiling->overhead = 0;
200 tiling->overlap = 5 * radius; // This is a guess. TODO: check if that's sufficiently large
201 tiling->xalign = 1;
202 tiling->yalign = 1;
203 return;
204}
205
208{
211
212 d->strength = p->strength;
213 d->size = p->size;
214 d->threshold = p->threshold;
215}
216
218{
219 piece->data = dt_calloc_align(sizeof(dt_iop_bloom_data_t));
220 piece->data_size = sizeof(dt_iop_bloom_data_t);
221}
222
224{
225 dt_free_align(piece->data);
226 piece->data = NULL;
227}
228
229void gui_init(struct dt_iop_module_t *self)
230{
232
233 g->size = dt_bauhaus_slider_from_params(self, N_("size"));
235 gtk_widget_set_tooltip_text(g->size, _("the size of bloom"));
236
237 g->threshold = dt_bauhaus_slider_from_params(self, N_("threshold"));
238 dt_bauhaus_slider_set_format(g->threshold, "%");
239 gtk_widget_set_tooltip_text(g->threshold, _("the threshold of light"));
240
241 g->strength = dt_bauhaus_slider_from_params(self, N_("strength"));
242 dt_bauhaus_slider_set_format(g->strength, "%");
243 gtk_widget_set_tooltip_text(g->strength, _("the strength of bloom"));
244}
245
246// clang-format off
247// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
248// vim: shiftwidth=2 expandtab tabstop=2 cindent
249// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
250// clang-format on
#define TRUE
Definition ashift_lsd.c:162
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3598
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 bloom.c:206
#define NUM_BUCKETS
Definition bloom.c:69
const char ** description(struct dt_iop_module_t *self)
Definition bloom.c:97
int default_group()
Definition bloom.c:112
__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 bloom.c:123
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition bloom.c:217
const char * name()
Definition bloom.c:92
void gui_init(struct dt_iop_module_t *self)
Definition bloom.c:229
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 bloom.c:185
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition bloom.c:117
int flags()
Definition bloom.c:107
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition bloom.c:223
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_LAB
const float threshold
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_IS_ALIGNED(x)
Definition darktable.h:371
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
Definition darktable.h:151
#define dt_pixelpipe_cache_free_align(mem)
Definition darktable.h:453
#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
int dt_iop_alloc_image_buffers(struct dt_iop_module_t *const module, const struct dt_iop_roi_t *const roi_in, const struct dt_iop_roi_t *const roi_out,...)
Definition imagebuf.c:31
void dt_iop_copy_image_roi(float *const __restrict__ out, const float *const __restrict__ in, const size_t ch, const dt_iop_roi_t *const __restrict__ roi_in, const dt_iop_roi_t *const __restrict__ roi_out, const int zero_pad)
Definition imagebuf.c:159
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_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
struct _GtkWidget GtkWidget
Definition splash.h:29
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
GtkWidget * size
Definition bloom.c:82
GtkWidget * strength
Definition bloom.c:82
GtkWidget * threshold
Definition bloom.c:82
unsigned int channels
Definition format.h:54
Region of interest passed through the pixelpipe.
Definition imageop.h:72
double scale
Definition imageop.h:74
#define MIN(a, b)
Definition thinplate.c:32