Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
lowpass.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011 Brian Teague.
4 Copyright (C) 2011 Henrik Andersson.
5 Copyright (C) 2011-2013, 2016 johannes hanika.
6 Copyright (C) 2011 Jérémy Rosen.
7 Copyright (C) 2011 Robert Bieber.
8 Copyright (C) 2011-2014, 2016, 2019 Tobias Ellinghaus.
9 Copyright (C) 2011-2017 Ulrich Pegelow.
10 Copyright (C) 2012 Edouard Gomez.
11 Copyright (C) 2012 Richard Wonka.
12 Copyright (C) 2013 Pascal de Bruijn.
13 Copyright (C) 2013, 2018, 2020, 2022 Pascal Obry.
14 Copyright (C) 2013-2016 Roman Lebedev.
15 Copyright (C) 2015 Pedro Côrte-Real.
16 Copyright (C) 2017, 2020 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 rawfiner.
21 Copyright (C) 2019 Andreas Schneider.
22 Copyright (C) 2020 Aldric Renaudin.
23 Copyright (C) 2020, 2022 Diederik Ter Rahe.
24 Copyright (C) 2020-2021 Hubert Kowalski.
25 Copyright (C) 2020-2021 Ralf Brown.
26 Copyright (C) 2022 Hanno Schwalm.
27 Copyright (C) 2022 Martin Bařinka.
28 Copyright (C) 2022 Philipp Lutz.
29
30 darktable is free software: you can redistribute it and/or modify
31 it under the terms of the GNU General Public License as published by
32 the Free Software Foundation, either version 3 of the License, or
33 (at your option) any later version.
34
35 darktable is distributed in the hope that it will be useful,
36 but WITHOUT ANY WARRANTY; without even the implied warranty of
37 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 GNU General Public License for more details.
39
40 You should have received a copy of the GNU General Public License
41 along with darktable. If not, see <http://www.gnu.org/licenses/>.
42*/
43
44#ifdef HAVE_CONFIG_H
45#include "config.h"
46#endif
47#include "system/macros.h"
48#include "system/openmp.h"
50#include "system/mem_alloc.h"
51#include "common/logging.h"
53#include "database/database.h"
54#include "pixel/bilateral.h"
55#include "pixel/bilateralcl.h"
56#include "pixel/gaussian.h"
57#include "math/math.h"
58#include "common/opencl.h"
59#include "develop/develop.h"
60#include "develop/imageop.h"
62#include "develop/imageop_gui.h"
63#include "develop/tiling.h"
64
65#include "gui/presets.h"
66#include "iop/iop_api.h"
67#include <assert.h>
68#include <gtk/gtk.h>
69#include <stdlib.h>
70#include <string.h>
71
72#include <inttypes.h>
73
75
77{
78 LOWPASS_ALGO_GAUSSIAN, // $DESCRIPTION: "gaussian"
79 LOWPASS_ALGO_BILATERAL // $DESCRIPTION: "bilateral filter"
81
82/* legacy version 1 params */
90
99
109
111{
113 float radius; // $MIN: 0.1 $MAX: 500.0 $DEFAULT: 10.0
114 float contrast; // $MIN: -3.0 $MAX: 3.0 $DEFAULT: 1.0
115 float brightness; // $MIN: -3.0 $MAX: 3.0 $DEFAULT: 0.0
116 float saturation; // $MIN: -3.0 $MAX: 3.0 $DEFAULT: 1.0
117 dt_iop_lowpass_algo_t lowpass_algo; // $DEFAULT: LOWPASS_ALGO_GAUSSIAN $DESCRIPTION: "soften with"
118 int unbound; // $DEFAULT: 1
120
121
131
133{
135 float radius;
136 float contrast;
141 float ctable[0x10000]; // precomputed look-up table for contrast curve
142 float cunbounded_coeffs[3]; // approximation for extrapolation of contrast curve
143 float ltable[0x10000]; // precomputed look-up table for brightness curve
144 float lunbounded_coeffs[3]; // approximation for extrapolation of brightness curve
146
151
152
153const char *name()
154{
155 return _("lowpass");
156}
157
158const char **description(struct dt_iop_module_t *self)
159{
160 return dt_iop_set_description(self, _("isolate low frequencies in the image"),
161 _("creative"),
162 _("linear or non-linear, Lab, scene-referred"),
163 _("frequential, Lab"),
164 _("special, Lab, scene-referred"));
165}
166
171
173{
174 return IOP_GROUP_EFFECTS;
175}
176
178{
179 return IOP_CS_LAB;
180}
181
182int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version,
183 void *new_params, const int new_version)
184{
185 if(old_version == 1 && new_version == 4)
186 {
187 const dt_iop_lowpass_params1_t *old = old_params;
188 dt_iop_lowpass_params_t *new = new_params;
189 new->order = old->order;
190 new->radius = fabs(old->radius);
191 new->contrast = old->contrast;
192 new->saturation = old->saturation;
193 new->brightness = 0.0f;
194 new->lowpass_algo = old->radius < 0.0f ? LOWPASS_ALGO_BILATERAL : LOWPASS_ALGO_GAUSSIAN;
195 new->unbound = 0;
196
197 return 0;
198 }
199 if(old_version == 2 && new_version == 4)
200 {
201 const dt_iop_lowpass_params2_t *old = old_params;
202 dt_iop_lowpass_params_t *new = new_params;
203 new->order = old->order;
204 new->radius = fabs(old->radius);
205 new->contrast = old->contrast;
206 new->saturation = old->saturation;
207 new->brightness = old->brightness;
208 new->lowpass_algo = old->radius < 0.0f ? LOWPASS_ALGO_BILATERAL : LOWPASS_ALGO_GAUSSIAN;
209 new->unbound = 0;
210
211 return 0;
212 }
213 if(old_version == 3 && new_version == 4)
214 {
215 const dt_iop_lowpass_params3_t *old = old_params;
216 dt_iop_lowpass_params_t *new = new_params;
217 new->order = old->order;
218 new->radius = fabs(old->radius);
219 new->contrast = old->contrast;
220 new->saturation = old->saturation;
221 new->brightness = old->brightness;
222 new->lowpass_algo = old->radius < 0.0f ? LOWPASS_ALGO_BILATERAL : LOWPASS_ALGO_GAUSSIAN;
223 new->unbound = old->unbound;
224
225 return 0;
226 }
227 return 1;
228}
229
230
231#ifdef HAVE_OPENCL
232int 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)
233{
234 const dt_iop_roi_t *const roi_in = &piece->roi_in;
235 (void)piece->roi_out;
238
239 cl_int err = -999;
240 const int devid = pipe->devid;
241
242 const int width = roi_in->width;
243 const int height = roi_in->height;
244 const int channels = piece->dsc_in.channels;
245
246 const float radius = fmax(0.1f, d->radius);
247 const float sigma = radius * roi_in->scale;
248 const float saturation = d->saturation;
249 const int order = d->order;
250 const int unbound = d->unbound;
251
252 cl_mem dev_cm = NULL;
253 cl_mem dev_ccoeffs = NULL;
254 cl_mem dev_lm = NULL;
255 cl_mem dev_lcoeffs = NULL;
256 cl_mem dev_tmp = NULL;
257
258 dt_gaussian_cl_t *g = NULL;
259 dt_bilateral_cl_t *b = NULL;
260
261 float Labmax[] = { 100.0f, 128.0f, 128.0f, 1.0f };
262 float Labmin[] = { 0.0f, -128.0f, -128.0f, 0.0f };
263
264 if(unbound)
265 {
266 for(int k = 0; k < 4; k++) Labmax[k] = INFINITY;
267 for(int k = 0; k < 4; k++) Labmin[k] = -INFINITY;
268 }
269
270 if(d->lowpass_algo == LOWPASS_ALGO_GAUSSIAN)
271 {
272 g = dt_gaussian_init_cl(devid, width, height, channels, Labmax, Labmin, sigma, order);
273 if(IS_NULL_PTR(g)) goto error;
274 err = dt_gaussian_blur_cl(g, dev_in, dev_out);
275 if(err != CL_SUCCESS) goto error;
277 g = NULL;
278 }
279 else
280 {
281 const float sigma_r = 100.0f; // does not depend on scale
282 const float sigma_s = sigma;
283 const float detail = -1.0f; // we want the bilateral base layer
284
286 if(IS_NULL_PTR(b)) goto error;
287 err = dt_bilateral_splat_cl(b, dev_in);
288 if(err != CL_SUCCESS) goto error;
289 err = dt_bilateral_blur_cl(b);
290 if(err != CL_SUCCESS) goto error;
291 err = dt_bilateral_slice_cl(b, dev_in, dev_out, detail);
292 if(err != CL_SUCCESS) goto error;
294 b = NULL; // make sure we don't clean it up twice
295 }
296
297 dev_tmp = dt_opencl_alloc_device(devid, width, height, sizeof(float) * 4);
298 if(IS_NULL_PTR(dev_tmp)) goto error;
299
300 dev_cm = dt_opencl_copy_host_to_device(devid, d->ctable, 256, 256, sizeof(float));
301 if(IS_NULL_PTR(dev_cm)) goto error;
302
303 dev_ccoeffs = dt_opencl_copy_host_to_device_constant(devid, sizeof(float) * 3, d->cunbounded_coeffs);
304 if(IS_NULL_PTR(dev_ccoeffs)) goto error;
305
306 dev_lm = dt_opencl_copy_host_to_device(devid, d->ltable, 256, 256, sizeof(float));
307 if(IS_NULL_PTR(dev_lm)) goto error;
308
309 dev_lcoeffs = dt_opencl_copy_host_to_device_constant(devid, sizeof(float) * 3, d->lunbounded_coeffs);
310 if(IS_NULL_PTR(dev_lcoeffs)) goto error;
311
312 size_t origin[] = { 0, 0, 0 };
313 size_t region[] = { width, height, 1 };
314 err = dt_opencl_enqueue_copy_image(devid, dev_out, dev_tmp, origin, origin, region);
315 if(err != CL_SUCCESS) goto error;
316
317 const size_t sizes[] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
318 dt_opencl_set_kernel_arg(devid, gd->kernel_lowpass_mix, 0, sizeof(cl_mem), (void *)&dev_tmp);
319 dt_opencl_set_kernel_arg(devid, gd->kernel_lowpass_mix, 1, sizeof(cl_mem), (void *)&dev_out);
320 dt_opencl_set_kernel_arg(devid, gd->kernel_lowpass_mix, 2, sizeof(int), (void *)&width);
321 dt_opencl_set_kernel_arg(devid, gd->kernel_lowpass_mix, 3, sizeof(int), (void *)&height);
322 dt_opencl_set_kernel_arg(devid, gd->kernel_lowpass_mix, 4, sizeof(float), (void *)&saturation);
323 dt_opencl_set_kernel_arg(devid, gd->kernel_lowpass_mix, 5, sizeof(cl_mem), (void *)&dev_cm);
324 dt_opencl_set_kernel_arg(devid, gd->kernel_lowpass_mix, 6, sizeof(cl_mem), (void *)&dev_ccoeffs);
325 dt_opencl_set_kernel_arg(devid, gd->kernel_lowpass_mix, 7, sizeof(cl_mem), (void *)&dev_lm);
326 dt_opencl_set_kernel_arg(devid, gd->kernel_lowpass_mix, 8, sizeof(cl_mem), (void *)&dev_lcoeffs);
327 dt_opencl_set_kernel_arg(devid, gd->kernel_lowpass_mix, 9, sizeof(int), (void *)&unbound);
328
329 err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_lowpass_mix, sizes);
330 if(err != CL_SUCCESS) goto error;
331
333 dt_opencl_release_mem_object(dev_lcoeffs);
335 dt_opencl_release_mem_object(dev_ccoeffs);
337
338 return TRUE;
339
340error:
342 if(b) dt_bilateral_free_cl(b);
343
345 dt_opencl_release_mem_object(dev_lcoeffs);
347 dt_opencl_release_mem_object(dev_ccoeffs);
349 dt_print(DT_DEBUG_OPENCL, "[opencl_lowpass] couldn't enqueue kernel! %d\n", err);
350 return FALSE;
351}
352#endif
353
354void 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)
355{
356 const dt_iop_roi_t *const roi_in = &piece->roi_in;
358 (void)pipe;
359
360 const float radius = fmax(0.1f, d->radius);
361 const float sigma = radius * roi_in->scale;
362 const float sigma_r = 100.0f; // does not depend on scale
363 const float sigma_s = sigma;
364
365 const int width = roi_in->width;
366 const int height = roi_in->height;
367 const int channels = piece->dsc_in.channels;
368
369 const size_t basebuffer = sizeof(float) * channels * width * height;
370
371 if(d->lowpass_algo == LOWPASS_ALGO_BILATERAL)
372 {
373 // bilateral filter
374 tiling->factor = 2.0f + fmax(1.0f, (float)dt_bilateral_memory_use(width, height, sigma_s, sigma_r) / basebuffer);
375 tiling->maxbuf
376 = fmax(1.0f, (float)dt_bilateral_singlebuffer_size(width, height, sigma_s, sigma_r) / basebuffer);
377 }
378 else
379 {
380 // gaussian blur
381 tiling->factor = 2.0f + fmax(1.0f, (float)dt_gaussian_memory_use(width, height, channels) / basebuffer);
382#ifdef HAVE_OPENCL
383 tiling->factor_cl = 2.0f + fmax(1.0f, (float)dt_gaussian_memory_use_cl(width, height, channels) / basebuffer);
384#endif
385 tiling->maxbuf = fmax(1.0f, (float)dt_gaussian_singlebuffer_size(width, height, channels) / basebuffer);
386 }
387 tiling->overhead = 0;
388 tiling->overlap = ceilf(4 * sigma);
389 tiling->xalign = 1;
390 tiling->yalign = 1;
391 return;
392}
393
395int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
396 void *const ovoid)
397{
398 const dt_iop_roi_t *const roi_in = &piece->roi_in;
399 const dt_iop_roi_t *const roi_out = &piece->roi_out;
401 float *in = (float *)ivoid;
402 float *out = (float *)ovoid;
403
404
405 const int width = roi_in->width;
406 const int height = roi_in->height;
407 const int ch = piece->dsc_in.channels;
408
409 const float radius = fmax(0.1f, data->radius);
410 const float sigma = radius * roi_in->scale;
411 const int order = data->order;
412 const int unbound = data->unbound;
413
414 float Labmax[] = { 100.0f, 128.0f, 128.0f, 1.0f };
415 float Labmin[] = { 0.0f, -128.0f, -128.0f, 0.0f };
416
417 if(unbound)
418 {
419 for(int k = 0; k < 4; k++) Labmax[k] = INFINITY;
420 for(int k = 0; k < 4; k++) Labmin[k] = -INFINITY;
421 }
422
424 {
425 dt_gaussian_t *g = dt_gaussian_init(width, height, ch, Labmax, Labmin, sigma, order);
426 if(IS_NULL_PTR(g)) return 1;
429 }
430 else
431 {
432 const float sigma_r = 100.0f; // d->sigma_r; // does not depend on scale
433 const float sigma_s = sigma;
434 const float detail = -1.0f; // we want the bilateral base layer
435
437 if(IS_NULL_PTR(b)) return 1;
438 dt_bilateral_splat(b, in);
440 dt_bilateral_slice(b, in, out, detail);
442 }
443
444 // some aliased pointers for compilers that don't yet understand operators on __m128
445 const float *const Labminf = (float *)&Labmin;
446 const float *const Labmaxf = (float *)&Labmax;
448 for(size_t k = 0; k < (size_t)roi_out->width * roi_out->height; k++)
449 {
450 out[k * ch + 0] = (out[k * ch + 0] < 100.0f)
451 ? data->ctable[CLAMP((int)(out[k * ch + 0] / 100.0f * 0x10000ul), 0, 0xffff)]
452 : dt_iop_eval_exp(data->cunbounded_coeffs, out[k * ch + 0] / 100.0f);
453 out[k * ch + 0] = (out[k * ch + 0] < 100.0f)
454 ? data->ltable[CLAMP((int)(out[k * ch + 0] / 100.0f * 0x10000ul), 0, 0xffff)]
455 : dt_iop_eval_exp(data->lunbounded_coeffs, out[k * ch + 0] / 100.0f);
456 out[k * ch + 1] = CLAMPF(out[k * ch + 1] * data->saturation, Labminf[1],
457 Labmaxf[1]); // will not clip in unbound case (see definition of Labmax/Labmin)
458 out[k * ch + 2]
459 = CLAMPF(out[k * ch + 2] * data->saturation, Labminf[2], Labmaxf[2]); // - " -
460 out[k * ch + 3] = in[k * ch + 3];
461 }
462 return 0;
463}
464
465#if 0 // gaussian order not user selectable
466static void
467order_changed (GtkComboBox *combo, gpointer user_data)
468{
469 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
470 if(dt_gui_widgets_suppressed()) return;
472 p->order = gtk_combo_box_get_active(combo);
473 dt_dev_add_history_item(self->dev, self, TRUE, TRUE);
474}
475#endif
476
479{
482 d->order = p->order;
483 d->radius = p->radius;
484 d->contrast = p->contrast;
485 d->brightness = p->brightness;
486 d->saturation = p->saturation;
487 d->lowpass_algo = p->lowpass_algo;
488 d->unbound = p->unbound;
489
490#ifdef HAVE_OPENCL
491 if(d->lowpass_algo == LOWPASS_ALGO_BILATERAL)
493#endif
494
495
496 // generate precomputed contrast curve
497 if(fabs(d->contrast) <= 1.0f)
498 {
499 // linear curve for contrast up to +/- 1
500 for(int k = 0; k < 0x10000; k++) d->ctable[k] = d->contrast * (100.0f * k / 0x10000 - 50.0f) + 50.0f;
501 }
502 else
503 {
504 // sigmoidal curve for contrast above +/-1 1
505 // going from (0,0) to (1,100) or (0,100) to (1,0), respectively
506 const float boost = 5.0f;
507 const float contrastm1sq = boost * (fabs(d->contrast) - 1.0f) * (fabs(d->contrast) - 1.0f);
508 const float contrastscale = copysign(sqrtf(1.0f + contrastm1sq), d->contrast);
510 for(int k = 0; k < 0x10000; k++)
511 {
512 float kx2m1 = 2.0f * (float)k / 0x10000 - 1.0f;
513 d->ctable[k] = 50.0f * (contrastscale * kx2m1 / sqrtf(1.0f + contrastm1sq * kx2m1 * kx2m1) + 1.0f);
514 }
515 }
516
517 // now the extrapolation stuff for the contrast curve:
518 const float xc[4] = { 0.7f, 0.8f, 0.9f, 1.0f };
519 const float yc[4] = { d->ctable[CLAMP((int)(xc[0] * 0x10000ul), 0, 0xffff)],
520 d->ctable[CLAMP((int)(xc[1] * 0x10000ul), 0, 0xffff)],
521 d->ctable[CLAMP((int)(xc[2] * 0x10000ul), 0, 0xffff)],
522 d->ctable[CLAMP((int)(xc[3] * 0x10000ul), 0, 0xffff)] };
523 dt_iop_estimate_exp(xc, yc, 4, d->cunbounded_coeffs);
524
525
526 // generate precomputed brightness curve
527 const float gamma = (d->brightness >= 0.0f) ? 1.0f / (1.0f + d->brightness) : (1.0f - d->brightness);
529 for(int k = 0; k < 0x10000; k++)
530 {
531 d->ltable[k] = 100.0f * powf((float)k / 0x10000, gamma);
532 }
533
534 // now the extrapolation stuff for the brightness curve:
535 const float xl[4] = { 0.7f, 0.8f, 0.9f, 1.0f };
536 const float yl[4] = { d->ltable[CLAMP((int)(xl[0] * 0x10000ul), 0, 0xffff)],
537 d->ltable[CLAMP((int)(xl[1] * 0x10000ul), 0, 0xffff)],
538 d->ltable[CLAMP((int)(xl[2] * 0x10000ul), 0, 0xffff)],
539 d->ltable[CLAMP((int)(xl[3] * 0x10000ul), 0, 0xffff)] };
540 dt_iop_estimate_exp(xl, yl, 4, d->lunbounded_coeffs);
541}
542
544{
546 piece->data = (void *)d;
547 piece->data_size = sizeof(dt_iop_lowpass_data_t);
548 // Checked AFTER both piece->data and piece->data_size are set, deliberately.
549 // dt_iop_init_pipe() disables the node for us when it sees data_size > 0 with a NULL
550 // data -- returning before data_size is assigned skips that and leaves the node enabled
551 // with no storage. dt_calloc_align() returns NULL on failure and pipe nodes are built
552 // exactly when memory is tightest (Sentry 134134395 faulted in atrous's init_pipe).
553 if(IS_NULL_PTR(piece->data)) return;
554 for(int k = 0; k < 0x10000; k++) d->ctable[k] = d->ltable[k] = 100.0f * k / 0x10000; // identity
555}
556
558{
559 dt_free_align(piece->data);
560 piece->data = NULL;
561}
562
564{
565 const int program = 6; // gaussian.cl, from programs.conf
568 module->data = gd;
569 gd->kernel_lowpass_mix = dt_opencl_create_kernel(program, "lowpass_mix");
570}
571
573{
575
576 dt_gui_presets_add_generic(_("local contrast mask"), self->op, self->version(),
577 &(dt_iop_lowpass_params_t){ 0, 50.0f, -1.0f, 0.0f, 0.0f, LOWPASS_ALGO_GAUSSIAN, 1 },
578 sizeof(dt_iop_lowpass_params_t), 1);
579
581}
582
589
590void gui_init(struct dt_iop_module_t *self)
591{
593
594 g->radius = dt_bauhaus_slider_from_params(self, N_("radius"));
595 g->lowpass_algo = dt_bauhaus_combobox_from_params(self, "lowpass_algo");
596 g->contrast = dt_bauhaus_slider_from_params(self, N_("contrast"));
597 g->brightness = dt_bauhaus_slider_from_params(self, N_("brightness"));
598 g->saturation = dt_bauhaus_slider_from_params(self, N_("saturation"));
599
600 gtk_widget_set_tooltip_text(g->radius, _("radius of gaussian/bilateral blur"));
601 gtk_widget_set_tooltip_text(g->contrast, _("contrast of lowpass filter"));
602 gtk_widget_set_tooltip_text(g->brightness, _("brightness adjustment of lowpass filter"));
603 gtk_widget_set_tooltip_text(g->saturation, _("color saturation of lowpass filter"));
604 gtk_widget_set_tooltip_text(g->lowpass_algo, _("which filter to use for blurring"));
605
606#if 0 // gaussian order not user selectable
607 g_signal_connect (G_OBJECT (g->order), "changed",
608 G_CALLBACK (order_changed), self);
609#endif
610}
611
612// clang-format off
613// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
614// vim: shiftwidth=2 expandtab tabstop=2 cindent
615// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
616// 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_bilateral_free(dt_bilateral_t *b)
Definition bilateral.c:432
__DT_CLONE_TARGETS__ void dt_bilateral_splat(const dt_bilateral_t *b, const float *const in)
Definition bilateral.c:183
size_t dt_bilateral_memory_use(const int width, const int height, const float sigma_s, const float sigma_r)
Definition bilateral.c:80
dt_bilateral_t * dt_bilateral_init(const int width, const int height, const float sigma_s, const float sigma_r)
Definition bilateral.c:157
size_t dt_bilateral_singlebuffer_size(const int width, const int height, const float sigma_s, const float sigma_r)
Definition bilateral.c:108
__DT_CLONE_TARGETS__ void dt_bilateral_slice(const dt_bilateral_t *const b, const float *const in, float *out, const float detail)
Definition bilateral.c:356
void dt_bilateral_blur(const dt_bilateral_t *b)
Definition bilateral.c:341
float sigma_s
Definition bilateral.h:3
float sigma_r
Definition bilateral.h:3
void dt_bilateral_free_cl(dt_bilateral_cl_t *b)
Definition bilateralcl.c:60
cl_int dt_bilateral_slice_cl(dt_bilateral_cl_t *b, cl_mem in, cl_mem out, const float detail)
dt_bilateral_cl_t * dt_bilateral_init_cl(const int devid, const int width, const int height, const float sigma_s, const float sigma_r)
Definition bilateralcl.c:91
cl_int dt_bilateral_blur_cl(dt_bilateral_cl_t *b)
cl_int dt_bilateral_splat_cl(dt_bilateral_cl_t *b, cl_mem in)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
@ IOP_CS_LAB
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
const dt_colormatrix_t dt_aligned_pixel_t out
#define dt_database_start_transaction()
Definition database.h:290
#define dt_database_release_transaction()
Definition database.h:291
#define dt_dev_add_history_item(dev, module, enable, redraw)
void dt_iop_params_t
Definition dev_history.h:43
void dt_gaussian_free(dt_gaussian_t *g)
Definition gaussian.c:335
void dt_gaussian_free_cl(dt_gaussian_cl_t *g)
Definition gaussian.c:365
size_t dt_gaussian_memory_use_cl(const int width, const int height, const int channels)
Definition gaussian.c:105
size_t dt_gaussian_singlebuffer_size(const int width, const int height, const int channels)
Definition gaussian.c:113
cl_int dt_gaussian_blur_cl(dt_gaussian_cl_t *g, cl_mem dev_in, cl_mem dev_out)
Definition gaussian.c:453
void dt_gaussian_blur_4c(dt_gaussian_t *g, const float *const in, float *const out)
Definition gaussian.c:330
dt_gaussian_cl_t * dt_gaussian_init_cl(const int devid, const int width, const int height, const int channels, const float *max, const float *min, const float sigma, const int order)
Definition gaussian.c:376
dt_gaussian_t * dt_gaussian_init(const int width, const int height, const int channels, const float *max, const float *min, const float sigma, const int order)
Definition gaussian.c:127
size_t dt_gaussian_memory_use(const int width, const int height, const int channels)
Definition gaussian.c:97
dt_gaussian_order_t
Definition gaussian.h:33
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_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)
GtkWidget * dt_bauhaus_combobox_from_params(dt_iop_module_t *self, const char *param)
#define IOP_GUI_ALLOC(module)
Definition imageop_gui.h:93
void *const ovoid
static void dt_iop_estimate_exp(const float *const x, const float *const y, const int num, float *coeff)
static float dt_iop_eval_exp(const float *const coeff, const float x)
@ 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.
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 lowpass.c:477
const char ** description(struct dt_iop_module_t *self)
Definition lowpass.c:158
int default_group()
Definition lowpass.c:172
__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 lowpass.c:395
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition lowpass.c:543
const char * name()
Definition lowpass.c:153
void gui_init(struct dt_iop_module_t *self)
Definition lowpass.c:590
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 lowpass.c:354
void cleanup_global(dt_iop_module_so_t *module)
Definition lowpass.c:583
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition lowpass.c:177
int flags()
Definition lowpass.c:167
dt_iop_lowpass_algo_t
Definition lowpass.c:77
@ LOWPASS_ALGO_BILATERAL
Definition lowpass.c:79
@ LOWPASS_ALGO_GAUSSIAN
Definition lowpass.c:78
void init_presets(dt_iop_module_so_t *self)
Definition lowpass.c:572
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition lowpass.c:557
void init_global(dt_iop_module_so_t *module)
Definition lowpass.c:563
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 lowpass.c:232
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 lowpass.c:182
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 CLAMPF(a, mn, mx)
Definition math.h:91
#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
void * dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
Definition opencl.c:2894
int dt_opencl_create_kernel(const int prog, const char *name)
Definition opencl.c:2448
void * dt_opencl_copy_host_to_device_constant(const int devid, const size_t size, void *host)
Definition opencl.c:2750
int dt_opencl_enqueue_copy_image(const int devid, cl_mem src, cl_mem dst, size_t *orig_src, size_t *orig_dst, size_t *region)
Definition opencl.c:2679
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
void * dt_opencl_copy_host_to_device(const int devid, void *host, const int width, const int height, const int bpp)
Definition opencl.c:2765
void dt_opencl_release_mem_object(cl_mem mem)
Definition opencl.c:2805
int dt_opencl_avoid_atomics(const int devid)
Definition opencl.c:219
#define ROUNDUPDHT(a, b)
Definition opencl.h:86
#define ROUNDUPDWD(a, b)
Definition opencl.h:85
#define __OMP_PARALLEL_FOR__(...)
Definition openmp.h:95
const float sigma
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
unsigned int channels
Definition format.h:83
float ctable[0x10000]
Definition lowpass.c:141
dt_gaussian_order_t order
Definition lowpass.c:134
float ltable[0x10000]
Definition lowpass.c:143
dt_iop_lowpass_algo_t lowpass_algo
Definition lowpass.c:139
float lunbounded_coeffs[3]
Definition lowpass.c:144
float cunbounded_coeffs[3]
Definition lowpass.c:142
GtkWidget * lowpass_algo
Definition lowpass.c:129
dt_gaussian_order_t order
Definition lowpass.c:85
dt_gaussian_order_t order
Definition lowpass.c:93
dt_gaussian_order_t order
Definition lowpass.c:102
dt_iop_lowpass_algo_t lowpass_algo
Definition lowpass.c:117
dt_gaussian_order_t order
Definition lowpass.c:112
dt_dev_operation_t op
Definition imageop.h:235
dt_iop_global_data_t * data
Definition imageop.h:238
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
#define __DT_CLONE_TARGETS__
gboolean dt_gui_widgets_suppressed(void)