Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
shadhi.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-2017 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-2012, 2014-2017 Ulrich Pegelow.
10 Copyright (C) 2012 Pascal de Bruijn.
11 Copyright (C) 2012 Richard Wonka.
12 Copyright (C) 2013-2016 Roman Lebedev.
13 Copyright (C) 2015 Pedro Côrte-Real.
14 Copyright (C) 2017 Heiko Bauke.
15 Copyright (C) 2018, 2020, 2022-2023, 2025-2026 Aurélien PIERRE.
16 Copyright (C) 2018 Edgardo Hoszowski.
17 Copyright (C) 2018 Maurizio Paglia.
18 Copyright (C) 2018, 2020, 2022 Pascal Obry.
19 Copyright (C) 2018 rawfiner.
20 Copyright (C) 2019 Andreas Schneider.
21 Copyright (C) 2020 Aldric Renaudin.
22 Copyright (C) 2020-2021 Chris Elston.
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#ifdef HAVE_CONFIG_H
44#include "config.h"
45#endif
46#include "widgets/bauhaus.h"
47#include "pixel/bilateral.h"
48#include "pixel/gaussian.h"
49#include "develop/develop.h"
50#include "system/macros.h"
51#include "system/openmp.h"
53#include "system/mem_alloc.h"
54#include "system/simd.h"
56#include "develop/imageop.h"
58#include "develop/imageop_gui.h"
59#include "develop/tiling.h"
60
61#include "iop/iop_api.h"
62#include <assert.h>
63#include <math.h>
64#include <stdlib.h>
65#include <string.h>
66
67#include <gtk/gtk.h>
68#include <inttypes.h>
69
70#define UNBOUND_L 1
71#define UNBOUND_A 2
72#define UNBOUND_B 4
73#define UNBOUND_SHADOWS_L UNBOUND_L
74#define UNBOUND_SHADOWS_A UNBOUND_A
75#define UNBOUND_SHADOWS_B UNBOUND_B
76#define UNBOUND_HIGHLIGHTS_L (UNBOUND_L << 3) /* 8 */
77#define UNBOUND_HIGHLIGHTS_A (UNBOUND_A << 3) /* 16 */
78#define UNBOUND_HIGHLIGHTS_B (UNBOUND_B << 3) /* 32 */
79#define UNBOUND_GAUSSIAN 64
80#define UNBOUND_BILATERAL 128 /* not implemented yet */
81#define UNBOUND_DEFAULT \
82 (UNBOUND_SHADOWS_L | UNBOUND_SHADOWS_A | UNBOUND_SHADOWS_B | UNBOUND_HIGHLIGHTS_L | UNBOUND_HIGHLIGHTS_A \
83 | UNBOUND_HIGHLIGHTS_B | UNBOUND_GAUSSIAN)
84
86
88{
89 SHADHI_ALGO_GAUSSIAN, // $DESCRIPTION: "gaussian"
90 SHADHI_ALGO_BILATERAL // $DESCRIPTION: "bilateral filter"
92
93/* legacy version 1 params */
104
105/* legacy version 2 params */
118
132
147
149{
150 dt_gaussian_order_t order; // $DEFAULT: DT_IOP_GAUSSIAN_ZERO
151 float radius; // $MIN: 0.1 $MAX: 500.0 $DEFAULT: 100.0
152 float shadows; // $MIN: -100.0 $MAX: 100.0 $DEFAULT: 50.0
153 float whitepoint; // $MIN: -10.0 $MAX: 10.0 $DEFAULT: 0.0 $DESCRIPTION: "white point adjustment"
154 float highlights; // $MIN: -100.0 $MAX: 100.0 $DEFAULT: -50.0
156 float compress; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 50.0
157 float shadows_ccorrect; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 100.0 $DESCRIPTION: "shadows color adjustment"
158 float highlights_ccorrect; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 50.0 $DESCRIPTION: "highlights color adjustment"
159 unsigned int flags; // $DEFAULT: UNBOUND_DEFAULT
160 float low_approximation; // $DEFAULT: 0.000001
161 dt_iop_shadhi_algo_t shadhi_algo; // $DEFAULT: SHADHI_ALGO_GAUSSIAN $DESCRIPTION: "soften with" $DEFAULT: 0
163
175
190
191const char *name()
192{
193 return _("shadows and highlights");
194}
195
200
202{
203 return IOP_GROUP_TONES;
204}
205
207{
208 return IOP_CS_LAB;
209}
210
211const char **description(struct dt_iop_module_t *self)
212{
213 return dt_iop_set_description(self, _("modify the tonal range of the shadows and highlights\n"
214 "of an image by enhancing local contrast."),
215 _("corrective and creative"),
216 _("linear or non-linear, Lab, display-referred"),
217 _("non-linear, Lab"),
218 _("non-linear, Lab, display-referred"));
219}
220
221int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version,
222 void *new_params, const int new_version)
223{
224 if(old_version == 1 && new_version == 5)
225 {
226 const dt_iop_shadhi_params1_t *old = old_params;
227 dt_iop_shadhi_params_t *new = new_params;
228 new->order = old->order;
229 new->radius = fabs(old->radius);
230 new->shadows = 0.5f * old->shadows;
231 new->whitepoint = old->reserved1;
232 new->reserved2 = old->reserved2;
233 new->highlights = -0.5f * old->highlights;
234 new->flags = 0;
235 new->compress = old->compress;
236 new->shadows_ccorrect = 100.0f;
237 new->highlights_ccorrect = 0.0f;
238 new->low_approximation = 0.01f;
239 new->shadhi_algo = old->radius < 0.0f ? SHADHI_ALGO_BILATERAL : SHADHI_ALGO_GAUSSIAN;
240 return 0;
241 }
242 else if(old_version == 2 && new_version == 5)
243 {
244 const dt_iop_shadhi_params2_t *old = old_params;
245 dt_iop_shadhi_params_t *new = new_params;
246 new->order = old->order;
247 new->radius = fabs(old->radius);
248 new->shadows = old->shadows;
249 new->whitepoint = old->reserved1;
250 new->reserved2 = old->reserved2;
251 new->highlights = old->highlights;
252 new->compress = old->compress;
253 new->shadows_ccorrect = old->shadows_ccorrect;
254 new->highlights_ccorrect = old->highlights_ccorrect;
255 new->flags = 0;
256 new->low_approximation = 0.01f;
257 new->shadhi_algo = old->radius < 0.0f ? SHADHI_ALGO_BILATERAL : SHADHI_ALGO_GAUSSIAN;
258 return 0;
259 }
260 else if(old_version == 3 && new_version == 5)
261 {
262 const dt_iop_shadhi_params3_t *old = old_params;
263 dt_iop_shadhi_params_t *new = new_params;
264 new->order = old->order;
265 new->radius = fabs(old->radius);
266 new->shadows = old->shadows;
267 new->whitepoint = old->reserved1;
268 new->reserved2 = old->reserved2;
269 new->highlights = old->highlights;
270 new->compress = old->compress;
271 new->shadows_ccorrect = old->shadows_ccorrect;
272 new->highlights_ccorrect = old->highlights_ccorrect;
273 new->flags = old->flags;
274 new->low_approximation = 0.01f;
275 new->shadhi_algo = old->radius < 0.0f ? SHADHI_ALGO_BILATERAL : SHADHI_ALGO_GAUSSIAN;
276 return 0;
277 }
278 else if(old_version == 4 && new_version == 5)
279 {
280 const dt_iop_shadhi_params4_t *old = old_params;
281 dt_iop_shadhi_params_t *new = new_params;
282 new->order = old->order;
283 new->radius = fabs(old->radius);
284 new->shadows = old->shadows;
285 new->whitepoint = old->whitepoint;
286 new->reserved2 = old->reserved2;
287 new->highlights = old->highlights;
288 new->compress = old->compress;
289 new->shadows_ccorrect = old->shadows_ccorrect;
290 new->highlights_ccorrect = old->highlights_ccorrect;
291 new->flags = old->flags;
292 new->low_approximation = old->low_approximation;
293 new->shadhi_algo = old->radius < 0.0f ? SHADHI_ALGO_BILATERAL : SHADHI_ALGO_GAUSSIAN;
294 return 0;
295 }
296 return 1;
297}
298
299
300static inline void _Lab_scale(const float *i, float *o)
301{
302 o[0] = i[0] / 100.0f;
303 o[1] = i[1] / 128.0f;
304 o[2] = i[2] / 128.0f;
305}
306
307
308static inline void _Lab_rescale(const float *i, float *o)
309{
310 o[0] = i[0] * 100.0f;
311 o[1] = i[1] * 128.0f;
312 o[2] = i[2] * 128.0f;
313}
314
315static inline float sign(float x)
316{
317 return (x < 0 ? -1.0f : 1.0f);
318}
320int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
321 void *const ovoid)
322{
323 const dt_iop_roi_t *const roi_in = &piece->roi_in;
324 const dt_iop_roi_t *const roi_out = &piece->roi_out;
325 const dt_iop_shadhi_data_t *const restrict data = (dt_iop_shadhi_data_t *)piece->data;
326 const float *const restrict in = (float *)ivoid;
327 float *const restrict out = (float *)ovoid;
328 const int width = roi_out->width;
329 const int height = roi_out->height;
330 const int ch = piece->dsc_in.channels;
331
332 const int order = data->order;
333 const float radius = fmaxf(0.1f, data->radius);
334 const float sigma = radius * roi_in->scale;
335 const float shadows = 2.0f * fmin(fmax(-1.0, (data->shadows / 100.0f)), 1.0f);
336 const float highlights = 2.0f * fmin(fmax(-1.0, (data->highlights / 100.0f)), 1.0f);
337 const float whitepoint = fmax(1.0f - data->whitepoint / 100.0f, 0.01f);
338 const float compress
339 = fmin(fmax(0, (data->compress / 100.0f)), 0.99f); // upper limit 0.99f to avoid division by zero later
340 const float shadows_ccorrect = (fmin(fmax(0.0f, (data->shadows_ccorrect / 100.0f)), 1.0f) - 0.5f)
341 * sign(shadows) + 0.5f;
342 const float highlights_ccorrect = (fmin(fmax(0.0f, (data->highlights_ccorrect / 100.0f)), 1.0f) - 0.5f)
343 * sign(-highlights) + 0.5f;
344 const unsigned int flags = data->flags;
345 const int unbound_mask = ((data->shadhi_algo == SHADHI_ALGO_BILATERAL) && (flags & UNBOUND_BILATERAL))
346 || ((data->shadhi_algo == SHADHI_ALGO_GAUSSIAN) && (flags & UNBOUND_GAUSSIAN));
347 const float low_approximation = data->low_approximation;
348
349 if(data->shadhi_algo == SHADHI_ALGO_GAUSSIAN)
350 {
351 dt_aligned_pixel_t Labmax = { 100.0f, 128.0f, 128.0f, 1.0f };
352 dt_aligned_pixel_t Labmin = { 0.0f, -128.0f, -128.0f, 0.0f };
353
354 if(unbound_mask)
355 {
356 for(int k = 0; k < 4; k++) Labmax[k] = INFINITY;
357 for(int k = 0; k < 4; k++) Labmin[k] = -INFINITY;
358 }
359
360 dt_gaussian_t *g = dt_gaussian_init(width, height, ch, Labmax, Labmin, sigma, order);
361 if(IS_NULL_PTR(g)) return 1;
364 }
365 else
366 {
367 const float sigma_r = 100.0f; // d->sigma_r; // does not depend on scale
368 const float sigma_s = sigma;
369 const float detail = -1.0f; // we want the bilateral base layer
370
372 if(IS_NULL_PTR(b)) return 1;
373 dt_bilateral_splat(b, in);
375 dt_bilateral_slice(b, in, out, detail);
377 }
378
379 const dt_aligned_pixel_t max = { 1.0f, 1.0f, 1.0f, 1.0f };
380 const dt_aligned_pixel_t min = { 0.0f, -1.0f, -1.0f, 0.0f };
381 const float lmin = 0.0f;
382 const float lmax = max[0] + fabsf(min[0]);
383 const float halfmax = lmax / 2.0;
384 const float doublemax = lmax * 2.0;
386 for(size_t j = 0; j < (size_t)width * height * ch; j += ch)
387 {
388 dt_aligned_pixel_t ta, tb;
389 _Lab_scale(&in[j], ta);
390 // invert and desaturate the blurred output pixel
391 out[j + 0] = 100.0f - out[j + 0];
392 out[j + 1] = 0.0f;
393 out[j + 2] = 0.0f;
394 _Lab_scale(&out[j], tb);
395
396 ta[0] = ta[0] > 0.0f ? ta[0] / whitepoint : ta[0];
397 tb[0] = tb[0] > 0.0f ? tb[0] / whitepoint : tb[0];
398
399 // overlay highlights
400 float highlights2 = highlights * highlights;
401 const float highlights_xform = CLAMP(1.0f - tb[0] / (1.0f - compress), 0.0f, 1.0f);
402
403 while(highlights2 > 0.0f)
404 {
405 const float la = (flags & UNBOUND_HIGHLIGHTS_L) ? ta[0] : CLAMP(ta[0], lmin, lmax);
406 float lb = (tb[0] - halfmax) * sign(-highlights) * sign(lmax - la) + halfmax;
407 lb = unbound_mask ? lb : CLAMP(lb, lmin, lmax);
408 const float lref = copysignf(fabsf(la) > low_approximation ? 1.0f / fabsf(la) : 1.0f / low_approximation, la);
409 const float href = copysignf(
410 fabsf(1.0f - la) > low_approximation ? 1.0f / fabsf(1.0f - la) : 1.0f / low_approximation, 1.0f - la);
411
412 const float chunk = highlights2 > 1.0f ? 1.0f : highlights2;
413 const float optrans = chunk * highlights_xform;
414 highlights2 -= 1.0f;
415
416 ta[0] = la * (1.0 - optrans)
417 + (la > halfmax ? lmax - (lmax - doublemax * (la - halfmax)) * (lmax - lb) : doublemax * la
418 * lb) * optrans;
419
420 ta[0] = (flags & UNBOUND_HIGHLIGHTS_L) ? ta[0] : CLAMP(ta[0], lmin, lmax);
421
422 const float chroma_factor = (ta[0] * lref * (1.0f - highlights_ccorrect)
423 + (1.0f - ta[0]) * href * highlights_ccorrect);
424 ta[1] = ta[1] * (1.0f - optrans) + (ta[1] + tb[1]) * chroma_factor * optrans;
425 ta[1] = (flags & UNBOUND_HIGHLIGHTS_A) ? ta[1] : CLAMP(ta[1], min[1], max[1]);
426
427 ta[2] = ta[2] * (1.0f - optrans) + (ta[2] + tb[2]) * chroma_factor * optrans;
428 ta[2] = (flags & UNBOUND_HIGHLIGHTS_B) ? ta[2] : CLAMP(ta[2], min[2], max[2]);
429 }
430
431 // overlay shadows
432 float shadows2 = shadows * shadows;
433 const float shadows_xform = CLAMP(tb[0] / (1.0f - compress) - compress / (1.0f - compress), 0.0f, 1.0f);
434
435 while(shadows2 > 0.0f)
436 {
437 const float la = (flags & UNBOUND_HIGHLIGHTS_L) ? ta[0] : CLAMP(ta[0], lmin, lmax);
438 float lb = (tb[0] - halfmax) * sign(shadows) * sign(lmax - la) + halfmax;
439 lb = unbound_mask ? lb : CLAMP(lb, lmin, lmax);
440 const float lref = copysignf(fabsf(la) > low_approximation ? 1.0f / fabsf(la) : 1.0f / low_approximation, la);
441 const float href = copysignf(
442 fabsf(1.0f - la) > low_approximation ? 1.0f / fabsf(1.0f - la) : 1.0f / low_approximation, 1.0f - la);
443
444
445 const float chunk = shadows2 > 1.0f ? 1.0f : shadows2;
446 const float optrans = chunk * shadows_xform;
447 shadows2 -= 1.0f;
448
449 ta[0] = la * (1.0 - optrans)
450 + (la > halfmax ? lmax - (lmax - doublemax * (la - halfmax)) * (lmax - lb) : doublemax * la
451 * lb) * optrans;
452
453 ta[0] = (flags & UNBOUND_SHADOWS_L) ? ta[0] : CLAMP(ta[0], lmin, lmax);
454
455 const float chroma_factor = (ta[0] * lref * shadows_ccorrect
456 + (1.0f - ta[0]) * href * (1.0f - shadows_ccorrect));
457 ta[1] = ta[1] * (1.0f - optrans) + (ta[1] + tb[1]) * chroma_factor * optrans;
458 ta[1] = (flags & UNBOUND_SHADOWS_A) ? ta[1] : CLAMP(ta[1], min[1], max[1]);
459
460 ta[2] = ta[2] * (1.0f - optrans) + (ta[2] + tb[2]) * chroma_factor * optrans;
461 ta[2] = (flags & UNBOUND_SHADOWS_B) ? ta[2] : CLAMP(ta[2], min[2], max[2]);
462 }
463
464 _Lab_rescale(ta, &out[j]);
465 }
466
467 if(pipe->mask_display & DT_DEV_PIXELPIPE_DISPLAY_MASK) dt_iop_alpha_copy(ivoid, ovoid, roi_out->width, roi_out->height);
468 return 0;
469}
470
471
472void 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)
473{
474 (void)self;
475 (void)pipe;
476 const dt_iop_roi_t *const roi_in = &piece->roi_in;
478
479 const int width = roi_in->width;
480 const int height = roi_in->height;
481 const int channels = piece->dsc_in.channels;
482
483 const float radius = fmax(0.1f, d->radius);
484 const float sigma = radius * roi_in->scale;
485 const float sigma_r = 100.0f; // does not depend on scale
486 const float sigma_s = sigma;
487
488 const size_t basebuffer = sizeof(float) * channels * width * height;
489
490 if(d->shadhi_algo == SHADHI_ALGO_BILATERAL)
491 {
492 // bilateral filter
493 tiling->factor = 2.0f + fmax(1.0f, (float)dt_bilateral_memory_use(width, height, sigma_s, sigma_r) / basebuffer);
494 tiling->maxbuf
495 = fmax(1.0f, (float)dt_bilateral_singlebuffer_size(width, height, sigma_s, sigma_r) / basebuffer);
496 }
497 else
498 {
499 // gaussian blur
500 tiling->factor = 2.0f + fmax(1.0f, (float)dt_gaussian_memory_use(width, height, channels) / basebuffer);
501 tiling->maxbuf = fmax(1.0f, (float)dt_gaussian_singlebuffer_size(width, height, channels) / basebuffer);
502 }
503
504 tiling->overhead = 0;
505 tiling->overlap = ceilf(4 * sigma);
506 tiling->xalign = 1;
507 tiling->yalign = 1;
508 return;
509}
510
513{
516
517 d->order = p->order;
518 d->radius = p->radius;
519 d->shadows = p->shadows;
520 d->highlights = p->highlights;
521 d->whitepoint = p->whitepoint;
522 d->compress = p->compress;
523 d->shadows_ccorrect = p->shadows_ccorrect;
524 d->highlights_ccorrect = p->highlights_ccorrect;
525 d->flags = p->flags;
526 d->low_approximation = p->low_approximation;
527 d->shadhi_algo = p->shadhi_algo;
528}
529
531{
532 piece->data = dt_calloc_align(sizeof(dt_iop_shadhi_data_t));
533 piece->data_size = sizeof(dt_iop_shadhi_data_t);
534}
535
537{
538 dt_free_align(piece->data);
539 piece->data = NULL;
540}
541
542void gui_init(struct dt_iop_module_t *self)
543{
545
546 g->shadows = dt_bauhaus_slider_from_params(self, N_("shadows"));
547 g->highlights = dt_bauhaus_slider_from_params(self, N_("highlights"));
548 g->whitepoint = dt_bauhaus_slider_from_params(self, "whitepoint");
549 g->shadhi_algo = dt_bauhaus_combobox_from_params(self, "shadhi_algo");
550 g->radius = dt_bauhaus_slider_from_params(self, N_("radius"));
551 g->compress = dt_bauhaus_slider_from_params(self, N_("compress"));
552 dt_bauhaus_slider_set_format(g->compress, "%");
553 g->shadows_ccorrect = dt_bauhaus_slider_from_params(self, "shadows_ccorrect");
554 dt_bauhaus_slider_set_format(g->shadows_ccorrect, "%");
555 g->highlights_ccorrect = dt_bauhaus_slider_from_params(self, "highlights_ccorrect");
556 dt_bauhaus_slider_set_format(g->highlights_ccorrect, "%");
557
558 gtk_widget_set_tooltip_text(g->shadows, _("correct shadows"));
559 gtk_widget_set_tooltip_text(g->highlights, _("correct highlights"));
560 gtk_widget_set_tooltip_text(g->whitepoint, _("shift white point"));
561 gtk_widget_set_tooltip_text(g->radius, _("spatial extent"));
562 gtk_widget_set_tooltip_text(g->shadhi_algo, _("filter to use for softening. bilateral avoids halos"));
563 gtk_widget_set_tooltip_text(g->compress, _("compress the effect on shadows/highlights and\npreserve mid-tones"));
564 gtk_widget_set_tooltip_text(g->shadows_ccorrect, _("adjust saturation of shadows"));
565 gtk_widget_set_tooltip_text(g->highlights_ccorrect, _("adjust saturation of highlights"));
566}
567
568// clang-format off
569// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
570// vim: shiftwidth=2 expandtab tabstop=2 cindent
571// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
572// clang-format on
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3407
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
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
@ IOP_CS_LAB
static const float x
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
static const float const float const float min
const float max
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_iop_params_t
Definition dev_history.h:43
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
Definition develop.h:123
void dt_gaussian_free(dt_gaussian_t *g)
Definition gaussian.c:335
size_t dt_gaussian_singlebuffer_size(const int width, const int height, const int channels)
Definition gaussian.c:113
void dt_gaussian_blur_4c(dt_gaussian_t *g, const float *const in, float *const out)
Definition gaussian.c:330
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
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_TONES
Definition imageop.h:156
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
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 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
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.
#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 shadhi.c:511
#define UNBOUND_SHADOWS_L
Definition shadhi.c:73
const char ** description(struct dt_iop_module_t *self)
Definition shadhi.c:211
int default_group()
Definition shadhi.c:201
__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 shadhi.c:320
#define UNBOUND_GAUSSIAN
Definition shadhi.c:79
#define UNBOUND_HIGHLIGHTS_L
Definition shadhi.c:76
#define UNBOUND_HIGHLIGHTS_A
Definition shadhi.c:77
#define UNBOUND_SHADOWS_A
Definition shadhi.c:74
#define UNBOUND_SHADOWS_B
Definition shadhi.c:75
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition shadhi.c:530
const char * name()
Definition shadhi.c:191
void gui_init(struct dt_iop_module_t *self)
Definition shadhi.c:542
static void _Lab_rescale(const float *i, float *o)
Definition shadhi.c:308
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 shadhi.c:472
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition shadhi.c:206
int flags()
Definition shadhi.c:196
#define UNBOUND_BILATERAL
Definition shadhi.c:80
#define UNBOUND_HIGHLIGHTS_B
Definition shadhi.c:78
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition shadhi.c:536
dt_iop_shadhi_algo_t
Definition shadhi.c:88
@ SHADHI_ALGO_BILATERAL
Definition shadhi.c:90
@ SHADHI_ALGO_GAUSSIAN
Definition shadhi.c:89
static void _Lab_scale(const float *i, float *o)
Definition shadhi.c:300
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 shadhi.c:221
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
Definition simd.h:53
static const dt_aligned_pixel_simd_t sign
Definition simd.h:118
const float sigma
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
unsigned int channels
Definition format.h:83
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
dt_gaussian_order_t order
Definition shadhi.c:178
float highlights_ccorrect
Definition shadhi.c:185
float low_approximation
Definition shadhi.c:187
dt_iop_shadhi_algo_t shadhi_algo
Definition shadhi.c:188
unsigned int flags
Definition shadhi.c:186
GtkWidget * highlights_ccorrect
Definition shadhi.c:172
GtkWidget * whitepoint
Definition shadhi.c:168
GtkWidget * compress
Definition shadhi.c:170
GtkWidget * shadows_ccorrect
Definition shadhi.c:171
GtkWidget * shadhi_algo
Definition shadhi.c:173
GtkWidget * highlights
Definition shadhi.c:167
GtkWidget * shadows
Definition shadhi.c:166
dt_gaussian_order_t order
Definition shadhi.c:96
dt_gaussian_order_t order
Definition shadhi.c:108
unsigned int flags
Definition shadhi.c:130
dt_gaussian_order_t order
Definition shadhi.c:121
unsigned int flags
Definition shadhi.c:144
dt_gaussian_order_t order
Definition shadhi.c:135
dt_gaussian_order_t order
Definition shadhi.c:150
unsigned int flags
Definition shadhi.c:159
dt_iop_shadhi_algo_t shadhi_algo
Definition shadhi.c:161
#define __DT_CLONE_TARGETS__