Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
nlmeans.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2011 Bruce Guenter.
4 Copyright (C) 2010-2013, 2016 johannes hanika.
5 Copyright (C) 2011 Henrik Andersson.
6 Copyright (C) 2011 Kanstantsin Shautsou.
7 Copyright (C) 2011 Pascal de Bruijn.
8 Copyright (C) 2011 Robert Bieber.
9 Copyright (C) 2011-2014, 2016, 2019 Tobias Ellinghaus.
10 Copyright (C) 2011-2014, 2016-2017 Ulrich Pegelow.
11 Copyright (C) 2012 Richard Wonka.
12 Copyright (C) 2013 Edouard Gomez.
13 Copyright (C) 2014-2016 Roman Lebedev.
14 Copyright (C) 2015 Pedro Côrte-Real.
15 Copyright (C) 2017 Heiko Bauke.
16 Copyright (C) 2018, 2020, 2023, 2025-2026 Aurélien PIERRE.
17 Copyright (C) 2018 Edgardo Hoszowski.
18 Copyright (C) 2018 Maurizio Paglia.
19 Copyright (C) 2018, 2020, 2022 Pascal Obry.
20 Copyright (C) 2018-2019 rawfiner.
21 Copyright (C) 2019 Andreas Schneider.
22 Copyright (C) 2019 Diederik ter Rahe.
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 "system/macros.h"
46#include "system/mem_alloc.h"
48#include "common/logging.h"
49#include "system/simd.h"
50#include "config.h"
51#endif
52#include "widgets/bauhaus.h"
53#include "pixel/nlmeans_core.h"
54#include "common/opencl.h"
55#include "develop/imageop.h"
57#include "develop/imageop_gui.h"
58#include "develop/tiling.h"
59
60#include "iop/iop_api.h"
61#include <gtk/gtk.h>
62#include <stdlib.h>
63
64// which version of the non-local means code should be used? 0=old (this file), 1=new (src/common/nlmeans_core.c)
65#define USE_NEW_IMPL_CL 0
66
67// number of intermediate buffers used by OpenCL code path. Needs to match value in src/common/nlmeans_core.c
68// to correctly compute tiling
69#define NUM_BUCKETS 4
70
71// this is the version of the modules parameters,
72// and includes version information about compile-time dt
74
80
82{
83 // these are stored in db.
84 float radius; // $MIN: 0.0 $MAX: 10.0 $DEFAULT: 2.0 $DESCRIPTION: "patch size"
85 float strength; // $MIN: 0.0 $MAX: 100000.0 $DEFAULT: 50.0
86 float luma; // $MIN: 0.0 $MAX: 1.0 $DEFAULT: 0.5
87 float chroma; // $MIN: 0.0 $MAX: 1.0 $DEFAULT: 1.0
89
97
99
109
110
111const char *name()
112{
113 return _("astrophoto denoise");
114}
115
116const char *aliases()
117{
118 return _("denoise (non-local means)");
119}
120
121const char **description(struct dt_iop_module_t *self)
122{
123 return dt_iop_set_description(self, _("apply a poisson noise removal best suited for astrophotography"),
124 _("corrective"),
125 _("non-linear, Lab, display-referred"),
126 _("non-linear, Lab"),
127 _("non-linear, Lab, display-referred"));
128}
129
131{
132 return IOP_CS_LAB;
133}
134
135int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version,
136 void *new_params, const int new_version)
137{
138 if(old_version == 1 && new_version == 2)
139 {
142 n->luma = o->luma;
143 n->chroma = o->chroma;
144 n->strength = 100.0f;
145 n->radius = 3;
146 return 0;
147 }
148 return 1;
149}
150
152{
153 return IOP_GROUP_REPAIR;
154}
155
160
161#if defined(HAVE_OPENCL) && !USE_NEW_IMPL_CL
162static int bucket_next(unsigned int *state, unsigned int max)
163{
164 unsigned int current = *state;
165 unsigned int next = (current >= max - 1 ? 0 : current + 1);
166
167 *state = next;
168
169 return next;
170}
171
172int 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)
173{
174 const dt_iop_roi_t *const roi_in = &piece->roi_in;
177#if USE_NEW_IMPL_CL
178 const int width = roi_in->width;
179 const int height = roi_in->height;
180
181 const float scale = fminf(roi_in->scale, 2.0f);
182 const int P = ceilf(d->radius * scale); // pixel filter size
183 const int K = ceilf(7 * scale); // nbhood
184 const float sharpness = 3000.0f / (1.0f + d->strength);
185
186 // adjust to Lab, make L more important
187 const float max_L = 120.0f, max_C = 512.0f;
188 const float nL = 1.0f / max_L, nC = 1.0f / max_C;
189 const float norm2[4] = { nL, nC }; //luma and chroma scaling factors
190
191 // allocate a buffer to receive the denoised image
192 const int devid = pipe->devid;
193 cl_mem dev_U2 = dt_opencl_alloc_device_buffer(devid, sizeof(float) * 4 * width * height);
194 if(IS_NULL_PTR(dev_U2))
195 {
196 dt_print(DT_DEBUG_OPENCL, "[opencl_nlmeans] couldn't allocate GPU buffer\n");
197 return FALSE;
198 }
199
200 const dt_nlmeans_param_t params =
201 {
202 .scattering = 0,
203 .scale = scale,
204 .luma = d->luma,
205 .chroma = d->chroma,
206 .center_weight = -1,
207 .sharpness = sharpness,
208 .patch_radius = P,
209 .search_radius = K,
210 .decimate = 0,
211 .norm = norm2,
212 .pipetype = pipe->type,
213 .kernel_init = gd->kernel_nlmeans_init,
214 .kernel_dist = gd->kernel_nlmeans_dist,
215 .kernel_horiz = gd->kernel_nlmeans_horiz,
216 .kernel_vert = gd->kernel_nlmeans_vert,
217 .kernel_accu = gd->kernel_nlmeans_accu
218 };
219 cl_int err = nlmeans_denoise_cl(&params, devid, dev_in, dev_U2, roi_in);
220 if (err == CL_SUCCESS)
221 {
222 // normalize and blend
223 size_t sizes[] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
224 const float weight[4] = { d->luma, d->chroma, d->chroma, 1.0f };
225 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_finish, 0, sizeof(cl_mem), (void *)&dev_in);
226 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_finish, 1, sizeof(cl_mem), (void *)&dev_U2);
227 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_finish, 2, sizeof(cl_mem), (void *)&dev_out);
228 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_finish, 3, sizeof(int), (void *)&width);
229 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_finish, 4, sizeof(int), (void *)&height);
230 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_finish, 5, 4 * sizeof(float), (void *)&weight);
231 err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_nlmeans_finish, sizes);
232 }
233 // clean up and check whether all kernels ran successfully
235 if (err == CL_SUCCESS)
236 return TRUE;
237 dt_print(DT_DEBUG_OPENCL, "[opencl_nlmeans] couldn't enqueue kernel! %d\n", err);
238 return FALSE;
239
240#else // old code
241 const int width = roi_in->width;
242 const int height = roi_in->height;
243
244 cl_int err = -999;
245
246 const float scale = fminf(roi_in->scale, 2.0f);
247 const int P = ceilf(d->radius * scale); // pixel filter size
248 const int K = ceilf(7 * scale); // nbhood
249 const float sharpness = 3000.0f / (1.0f + d->strength);
250
251 // adjust to Lab, make L more important
252 const float max_L = 120.0f, max_C = 512.0f;
253 const float nL = 1.0f / max_L, nC = 1.0f / max_C;
254 const float nL2 = nL * nL, nC2 = nC * nC;
255 const dt_aligned_pixel_t weight = { d->luma, d->chroma, d->chroma, 1.0f };
256
257 const int devid = pipe->devid;
258 cl_mem dev_U2 = dt_opencl_alloc_device_buffer(devid, sizeof(float) * 4 * width * height);
259 if(IS_NULL_PTR(dev_U2)) goto error;
260
261 cl_mem buckets[NUM_BUCKETS] = { NULL };
262 unsigned int state = 0;
263 for(int k = 0; k < NUM_BUCKETS; k++)
264 {
265 buckets[k] = dt_opencl_alloc_device_buffer(devid, sizeof(float) * width * height);
266 if(buckets[k] == NULL) goto error;
267 }
268
269 int hblocksize;
271 = (dt_opencl_local_buffer_t){ .xoffset = 2 * P, .xfactor = 1, .yoffset = 0, .yfactor = 1,
272 .cellsize = sizeof(float), .overhead = 0,
273 .sizex = 1 << 16, .sizey = 1 };
274
275 if(dt_opencl_local_buffer_opt(devid, gd->kernel_nlmeans_horiz, &hlocopt))
276 hblocksize = hlocopt.sizex;
277 else
278 hblocksize = 1;
279
280 int vblocksize;
282 = (dt_opencl_local_buffer_t){ .xoffset = 1, .xfactor = 1, .yoffset = 2 * P, .yfactor = 1,
283 .cellsize = sizeof(float), .overhead = 0,
284 .sizex = 1, .sizey = 1 << 16 };
285
286 if(dt_opencl_local_buffer_opt(devid, gd->kernel_nlmeans_vert, &vlocopt))
287 vblocksize = vlocopt.sizey;
288 else
289 vblocksize = 1;
290
291
292 size_t sizesl[3];
293 size_t local[3];
294 size_t sizes[] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
295
296 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_init, 0, sizeof(cl_mem), (void *)&dev_U2);
297 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_init, 1, sizeof(int), (void *)&width);
298 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_init, 2, sizeof(int), (void *)&height);
299 err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_nlmeans_init, sizes);
300 if(err != CL_SUCCESS) goto error;
301
302
303 const size_t bwidth = ROUNDUP(width, hblocksize);
304 const size_t bheight = ROUNDUP(height, vblocksize);
305
306 for(int j = -K; j <= 0; j++)
307 for(int i = -K; i <= K; i++)
308 {
309 int q[2] = { i, j };
310
311 cl_mem dev_U4 = buckets[bucket_next(&state, NUM_BUCKETS)];
312 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_dist, 0, sizeof(cl_mem), (void *)&dev_in);
313 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_dist, 1, sizeof(cl_mem), (void *)&dev_U4);
314 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_dist, 2, sizeof(int), (void *)&width);
315 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_dist, 3, sizeof(int), (void *)&height);
316 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_dist, 4, 2 * sizeof(int), (void *)&q);
317 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_dist, 5, sizeof(float), (void *)&nL2);
318 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_dist, 6, sizeof(float), (void *)&nC2);
319 err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_nlmeans_dist, sizes);
320 if(err != CL_SUCCESS) goto error;
321
322 sizesl[0] = bwidth;
323 sizesl[1] = ROUNDUPDHT(height, devid);
324 sizesl[2] = 1;
325 local[0] = hblocksize;
326 local[1] = 1;
327 local[2] = 1;
328 cl_mem dev_U4_t = buckets[bucket_next(&state, NUM_BUCKETS)];
329 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_horiz, 0, sizeof(cl_mem), (void *)&dev_U4);
330 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_horiz, 1, sizeof(cl_mem), (void *)&dev_U4_t);
331 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_horiz, 2, sizeof(int), (void *)&width);
332 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_horiz, 3, sizeof(int), (void *)&height);
333 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_horiz, 4, 2 * sizeof(int), (void *)&q);
334 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_horiz, 5, sizeof(int), (void *)&P);
335 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_horiz, 6, (hblocksize + 2 * P) * sizeof(float), NULL);
336 err = dt_opencl_enqueue_kernel_2d_with_local(devid, gd->kernel_nlmeans_horiz, sizesl, local);
337 if(err != CL_SUCCESS) goto error;
338
339
340 sizesl[0] = ROUNDUPDWD(width, devid);
341 sizesl[1] = bheight;
342 sizesl[2] = 1;
343 local[0] = 1;
344 local[1] = vblocksize;
345 local[2] = 1;
346 cl_mem dev_U4_tt = buckets[bucket_next(&state, NUM_BUCKETS)];
347 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_vert, 0, sizeof(cl_mem), (void *)&dev_U4_t);
348 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_vert, 1, sizeof(cl_mem), (void *)&dev_U4_tt);
349 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_vert, 2, sizeof(int), (void *)&width);
350 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_vert, 3, sizeof(int), (void *)&height);
351 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_vert, 4, 2 * sizeof(int), (void *)&q);
352 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_vert, 5, sizeof(int), (void *)&P);
353 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_vert, 6, sizeof(float), (void *)&sharpness);
354 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_vert, 7, (vblocksize + 2 * P) * sizeof(float), NULL);
355 err = dt_opencl_enqueue_kernel_2d_with_local(devid, gd->kernel_nlmeans_vert, sizesl, local);
356 if(err != CL_SUCCESS) goto error;
357
358
359 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_accu, 0, sizeof(cl_mem), (void *)&dev_in);
360 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_accu, 1, sizeof(cl_mem), (void *)&dev_U2);
361 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_accu, 2, sizeof(cl_mem), (void *)&dev_U4_tt);
362 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_accu, 3, sizeof(int), (void *)&width);
363 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_accu, 4, sizeof(int), (void *)&height);
364 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_accu, 5, 2 * sizeof(int), (void *)&q);
365 err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_nlmeans_accu, sizes);
366 if(err != CL_SUCCESS) goto error;
367 }
368
369 // normalize and blend
370 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_finish, 0, sizeof(cl_mem), (void *)&dev_in);
371 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_finish, 1, sizeof(cl_mem), (void *)&dev_U2);
372 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_finish, 2, sizeof(cl_mem), (void *)&dev_out);
373 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_finish, 3, sizeof(int), (void *)&width);
374 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_finish, 4, sizeof(int), (void *)&height);
375 dt_opencl_set_kernel_arg(devid, gd->kernel_nlmeans_finish, 5, 4 * sizeof(float), (void *)&weight);
376 err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_nlmeans_finish, sizes);
377 if(err != CL_SUCCESS) goto error;
378
380 for(int k = 0; k < NUM_BUCKETS; k++)
381 {
383 }
384 return TRUE;
385
386error:
388 for(int k = 0; k < NUM_BUCKETS; k++)
389 {
391 }
392
393 dt_print(DT_DEBUG_OPENCL, "[opencl_nlmeans] couldn't enqueue kernel! %d\n", err);
394 return FALSE;
395#endif /* USE_NEW_IMPL_CL */
396}
397#endif
398
399
400void 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)
401{
402 const dt_iop_roi_t *const roi_in = &piece->roi_in;
404 const int P = ceilf(d->radius * fmin(roi_in->scale, 2.0f)); // pixel filter size
405 const int K = ceilf(7 * fmin(roi_in->scale, 2.0f)); // nbhood
406
407 tiling->factor = 2.0f + 1.0f + 0.25 * NUM_BUCKETS; // in + out + tmp
408 tiling->maxbuf = 1.0f;
409 tiling->overhead = 0;
410 tiling->overlap = P + K;
411 tiling->xalign = 1;
412 tiling->yalign = 1;
413 return;
414}
415
416static inline __attribute__((always_inline)) void process_cpu(const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece,
417 const void *const ivoid,
418 void *const ovoid, const dt_iop_roi_t *const roi_in,
419 const dt_iop_roi_t *const roi_out,
420 void (*denoiser)(const float *const inbuf, float *const outbuf,
421 const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out,
422 const dt_nlmeans_param_t *const params))
423{
424 // this is called for preview and full pipe separately, each with its own pixelpipe piece.
425 // get our data struct:
426 const dt_iop_nlmeans_params_t *const d = (dt_iop_nlmeans_params_t *)piece->data;
427
428 // adjust to zoom size:
429 const float scale = fmin(roi_in->scale, 2.0f);
430 const int P = ceilf(d->radius * scale); // pixel filter size
431 const int K = ceilf(7 * scale); // nbhood
432 const float sharpness = 3000.0f / (1.0f + d->strength);
433
434 // adjust to Lab, make L more important
435 float max_L = 120.0f, max_C = 512.0f;
436 float nL = 1.0f / max_L, nC = 1.0f / max_C;
437 const dt_aligned_pixel_t norm2 = { nL * nL, nC * nC, nC * nC, 1.0f };
438
439 // faster but less accurate processing by skipping half the patches on previews and thumbnails
440 const int decimate = (pipe->type == DT_DEV_PIXELPIPE_THUMBNAIL
441 || dt_dev_pixelpipe_has_preview_output(piece->module->dev, pipe, roi_out));
442
443 const dt_nlmeans_param_t params = { .scattering = 0,
444 .scale = scale,
445 .luma = d->luma,
446 .chroma = d->chroma,
447 .center_weight = -1,
448 .sharpness = sharpness,
449 .patch_radius = P,
450 .search_radius = K,
451 .decimate = decimate,
452 .norm = norm2 };
453 denoiser(ivoid,ovoid,roi_in,roi_out,&params);
455 dt_iop_alpha_copy(ivoid, ovoid, roi_out->width, roi_out->height);
456}
457
458int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
459 void *const ovoid)
460{
461 const dt_iop_roi_t *const roi_in = &piece->roi_in;
462 const dt_iop_roi_t *const roi_out = &piece->roi_out;
463 process_cpu(pipe, piece, ivoid, ovoid, roi_in, roi_out, nlmeans_denoise);
464 return 0;
465}
466
468{
469 const int program = 5; // nlmeans.cl, from programs.conf
472 module->data = gd;
473 gd->kernel_nlmeans_init = dt_opencl_create_kernel(program, "nlmeans_init");
474 gd->kernel_nlmeans_dist = dt_opencl_create_kernel(program, "nlmeans_dist");
475 gd->kernel_nlmeans_horiz = dt_opencl_create_kernel(program, "nlmeans_horiz");
476 gd->kernel_nlmeans_vert = dt_opencl_create_kernel(program, "nlmeans_vert");
477 gd->kernel_nlmeans_accu = dt_opencl_create_kernel(program, "nlmeans_accu");
478 gd->kernel_nlmeans_finish = dt_opencl_create_kernel(program, "nlmeans_finish");
479}
480
492
496{
499 memcpy(d, p, sizeof(*d));
500 d->luma = MAX(0.0001f, p->luma);
501 d->chroma = MAX(0.0001f, p->chroma);
502}
503
505{
507 piece->data_size = sizeof(dt_iop_nlmeans_data_t);
508}
509
511{
512 dt_free_align(piece->data);
513 piece->data = NULL;
514}
515
517{
519
520 g->radius = dt_bauhaus_slider_from_params(self, "radius");
521 dt_bauhaus_slider_set_soft_max(g->radius, 4.0f);
523 gtk_widget_set_tooltip_text(g->radius, _("radius of the patches to match"));
524 g->strength = dt_bauhaus_slider_from_params(self, N_("strength"));
525 dt_bauhaus_slider_set_soft_max(g->strength, 100.0f);
526 dt_bauhaus_slider_set_digits(g->strength, 0);
527 dt_bauhaus_slider_set_format(g->strength, "%");
528 gtk_widget_set_tooltip_text(g->strength, _("strength of the effect"));
529 g->luma = dt_bauhaus_slider_from_params(self, N_("luma"));
531 gtk_widget_set_tooltip_text(g->luma, _("how much to smooth brightness"));
532 g->chroma = dt_bauhaus_slider_from_params(self, N_("chroma"));
533 dt_bauhaus_slider_set_format(g->chroma, "%");
534 gtk_widget_set_tooltip_text(g->chroma, _("how much to smooth colors"));
535}
536
537// clang-format off
538// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
539// vim: shiftwidth=2 expandtab tabstop=2 cindent
540// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
541// 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_bauhaus_slider_set_digits(GtkWidget *widget, int val)
Definition bauhaus.c:3343
void dt_bauhaus_slider_set_soft_max(GtkWidget *widget, float val)
Definition bauhaus.c:1474
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3407
@ IOP_CS_LAB
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
const float max
#define P(V, params)
void dt_iop_params_t
Definition dev_history.h:43
gboolean dt_dev_pixelpipe_has_preview_output(const dt_develop_t *dev, const dt_dev_pixelpipe_t *pipe, const dt_iop_roi_t *roi)
Definition develop.c:402
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
Definition develop.h:123
static void weight(const float *c1, const float *c2, const float sharpen, dt_aligned_pixel_t weight)
Definition eaw.c:29
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_SUPPORTS_BLENDING
Definition imageop.h:186
@ IOP_FLAGS_ALLOW_TILING
Definition imageop.h:188
@ IOP_GROUP_REPAIR
Definition imageop.h:159
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
@ 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
#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 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.
static int bucket_next(unsigned int *state, unsigned int max)
Definition nlmeans.c:162
#define NUM_BUCKETS
Definition nlmeans.c:69
const char ** description(struct dt_iop_module_t *self)
Definition nlmeans.c:121
int default_group()
Definition nlmeans.c:151
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *params, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition nlmeans.c:494
const char * aliases()
Definition nlmeans.c:116
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition nlmeans.c:504
const char * name()
Definition nlmeans.c:111
void gui_init(dt_iop_module_t *self)
Definition nlmeans.c:516
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 nlmeans.c:400
void cleanup_global(dt_iop_module_so_t *module)
Definition nlmeans.c:481
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition nlmeans.c:130
int flags()
Definition nlmeans.c:156
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 nlmeans.c:458
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition nlmeans.c:510
void init_global(dt_iop_module_so_t *module)
Definition nlmeans.c:467
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 nlmeans.c:172
dt_iop_nlmeans_params_t dt_iop_nlmeans_data_t
Definition nlmeans.c:98
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 nlmeans.c:135
__DT_CLONE_TARGETS__ void nlmeans_denoise(const float *const inbuf, float *const outbuf, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out, const dt_nlmeans_param_t *const params)
int nlmeans_denoise_cl(const dt_nlmeans_param_t *const params, const int devid, cl_mem dev_in, cl_mem dev_out, const dt_iop_roi_t *const roi_in)
int dt_opencl_local_buffer_opt(const int devid, const int kernel, dt_opencl_local_buffer_t *factors)
Definition opencl.c:3713
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_buffer(const int devid, const size_t size)
Definition opencl.c:2970
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
int dt_opencl_enqueue_kernel_2d_with_local(const int dev, const int kernel, const size_t *sizes, const size_t *local)
Definition opencl.c:2560
void dt_opencl_release_mem_object(cl_mem mem)
Definition opencl.c:2805
#define ROUNDUP(a, n)
Definition opencl.h:82
#define ROUNDUPDHT(a, b)
Definition opencl.h:86
#define ROUNDUPDWD(a, b)
Definition opencl.h:85
@ DT_DEV_PIXELPIPE_THUMBNAIL
Definition pixelpipe.h:45
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
Definition simd.h:53
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
Definition simd.h:55
const float uint32_t state[4]
struct dt_iop_module_t *void * data
dt_dev_pixelpipe_type_t type
dt_iop_global_data_t * data
Definition imageop.h:238
dt_iop_global_data_t * global_data
Definition imageop.h:337
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 MAX(a, b)
Definition thinplate.c:29