Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
profile_gamma.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 Alexandre Prokoudine.
5 Copyright (C) 2010 Bruce Guenter.
6 Copyright (C) 2010-2011 Henrik Andersson.
7 Copyright (C) 2010 José Carlos García Sogo.
8 Copyright (C) 2010 Pascal de Bruijn.
9 Copyright (C) 2011 Jérémy Rosen.
10 Copyright (C) 2011 Olivier Tribout.
11 Copyright (C) 2011 Robert Bieber.
12 Copyright (C) 2011-2014, 2016, 2019 Tobias Ellinghaus.
13 Copyright (C) 2012 Richard Wonka.
14 Copyright (C) 2013, 2020 Aldric Renaudin.
15 Copyright (C) 2014-2016 Roman Lebedev.
16 Copyright (C) 2014, 2016-2017 Ulrich Pegelow.
17 Copyright (C) 2015 Pedro Côrte-Real.
18 Copyright (C) 2017 Heiko Bauke.
19 Copyright (C) 2018-2020, 2023, 2025-2026 Aurélien PIERRE.
20 Copyright (C) 2018-2019 Edgardo Hoszowski.
21 Copyright (C) 2018 Matthieu Moy.
22 Copyright (C) 2018 Maurizio Paglia.
23 Copyright (C) 2018-2022 Pascal Obry.
24 Copyright (C) 2018 rawfiner.
25 Copyright (C) 2019 Andreas Schneider.
26 Copyright (C) 2019-2020, 2022 Diederik Ter Rahe.
27 Copyright (C) 2019 Diederik ter Rahe.
28 Copyright (C) 2020-2021 Chris Elston.
29 Copyright (C) 2020 Ralf Brown.
30 Copyright (C) 2021 Dan Torop.
31 Copyright (C) 2022 Hanno Schwalm.
32 Copyright (C) 2022 Martin Bařinka.
33 Copyright (C) 2022 Philipp Lutz.
34
35 darktable is free software: you can redistribute it and/or modify
36 it under the terms of the GNU General Public License as published by
37 the Free Software Foundation, either version 3 of the License, or
38 (at your option) any later version.
39
40 darktable is distributed in the hope that it will be useful,
41 but WITHOUT ANY WARRANTY; without even the implied warranty of
42 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 GNU General Public License for more details.
44
45 You should have received a copy of the GNU General Public License
46 along with darktable. If not, see <http://www.gnu.org/licenses/>.
47*/
48#ifdef HAVE_CONFIG_H
49#include "config.h"
50#endif
51#include "widgets/bauhaus.h"
52#include "system/openmp.h"
54#include "system/mem_alloc.h"
56#include "math/math.h"
57#include "develop/develop.h"
59#include "develop/imageop_gui.h"
60
61#include "gui/presets.h"
63#include "iop/iop_api.h"
64#include <assert.h>
65#include <math.h>
66#include <stdlib.h>
67#include <string.h>
68#include "widgets/label.h"
69
71
73{
74 PROFILEGAMMA_LOG = 0, // $DESCRIPTION: "logarithmic"
75 PROFILEGAMMA_GAMMA = 1 // $DESCRIPTION: "gamma"
77
79{
80 dt_iop_profilegamma_mode_t mode; // $DEFAULT: PROFILEGAMMA_LOG
81 float linear; // $MIN: 0.0 $MAX: 1.0 $DEFAULT: 0.1
82 float gamma; // $MIN: 0.0 $MAX: 1.0 $DEFAULT: 0.45
83 float dynamic_range; // $MIN: 0.01 $MAX: 32.0 $DEFAULT: 10.0 $DESCRIPTION: "dynamic range"
84 float grey_point; // $MIN: 0.1 $MAX: 100.0 $DEFAULT: 18.0 $DESCRIPTION: "middle gray luma"
85 float shadows_range; // $MIN: -16.0 $MAX: 16.0 $DEFAULT: -5.0 $DESCRIPTION: "black relative exposure"
86 float security_factor; // $MIN: -100.0 $MAX: 100.0 $DEFAULT: 0.0 $DESCRIPTION: "safety factor"
88
101
103{
105 float linear;
106 float gamma;
107 float table[0x10000]; // precomputed look-up table
108 float unbounded_coeffs[3]; // approximation for extrapolation of curve
114
115const char *name()
116{
117 return _("unbreak input profile");
118}
119
120const char **description(struct dt_iop_module_t *self)
121{
122 return dt_iop_set_description(self, _("correct input color profiles meant to be applied on non-linear RGB"),
123 _("corrective"),
124 _("linear, RGB, display-referred"),
125 _("non-linear, RGB"),
126 _("non-linear, RGB, display-referred"));
127}
128
130{
131 return IOP_GROUP_TECHNICAL;
132}
133
139
141{
142 return IOP_CS_RGB;
143}
144
146{
148 memset(&p, 0, sizeof(p));
149
150 p.mode = PROFILEGAMMA_LOG;
151 p.grey_point = 18.00f;
152 p.security_factor = 0.0f;
153
154 // 16 EV preset
155 p.dynamic_range = 16.0f;
156 p.shadows_range = -12.0f;
157 dt_gui_presets_add_generic(_("16 EV dynamic range (generic)"), self->op,
158 self->version(), &p, sizeof(p), 1);
159
160 // 14 EV preset
161 p.dynamic_range = 14.0f;
162 p.shadows_range = -10.50f;
163 dt_gui_presets_add_generic(_("14 EV dynamic range (generic)"), self->op,
164 self->version(), &p, sizeof(p), 1);
165
166 // 12 EV preset
167 p.dynamic_range = 12.0f;
168 p.shadows_range = -9.0f;
169 dt_gui_presets_add_generic(_("12 EV dynamic range (generic)"), self->op,
170 self->version(), &p, sizeof(p), 1);
171
172 // 10 EV preset
173 p.dynamic_range = 10.0f;
174 p.shadows_range = -7.50f;
175 dt_gui_presets_add_generic(_("10 EV dynamic range (generic)"), self->op,
176 self->version(), &p, sizeof(p), 1);
177
178 // 08 EV preset
179 p.dynamic_range = 8.0f;
180 p.shadows_range = -6.0f;
181 dt_gui_presets_add_generic(_("08 EV dynamic range (generic)"), self->op,
182 self->version(), &p, sizeof(p), 1);
183}
184
185
186int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params,
187 const int new_version)
188{
189 if(old_version == 1 && new_version == 2)
190 {
191 typedef struct dt_iop_profilegamma_params_v1_t
192 {
193 float linear;
194 float gamma;
195 } dt_iop_profilegamma_params_v1_t;
196
197 dt_iop_profilegamma_params_v1_t *o = (dt_iop_profilegamma_params_v1_t *)old_params;
200
201 *n = *d; // start with a fresh copy of default parameters
202
203 n->linear = o->linear;
204 n->gamma = o->gamma;
205 n->mode = PROFILEGAMMA_GAMMA;
206 return 0;
207 }
208 return 1;
209}
210
213 const void *const ivoid, void *const ovoid)
214{
215 const dt_iop_roi_t *const roi_out = &piece->roi_out;
217
218 const int ch = piece->dsc_in.channels;
219
220 switch(data->mode)
221 {
222 case PROFILEGAMMA_LOG:
223 {
224 const float grey = data->grey_point / 100.0f;
225
233 const float noise = powf(2.0f, -16.0f);
235 for(size_t k = 0; k < (size_t)ch * roi_out->width * roi_out->height; k++)
236 {
237 float tmp = ((const float *)ivoid)[k] / grey;
238 if (tmp < noise) tmp = noise;
239 tmp = (fastlog2(tmp) - data->shadows_range) / (data->dynamic_range);
240
241 if (tmp < noise)
242 {
243 ((float *)ovoid)[k] = noise;
244 }
245 else
246 {
247 ((float *)ovoid)[k] = tmp;
248 }
249 }
250 break;
251 }
252
254 {
256 for(int k = 0; k < roi_out->height; k++)
257 {
258 const float *in = ((float *)ivoid) + (size_t)ch * k * roi_out->width;
259 float *out = ((float *)ovoid) + (size_t)ch * k * roi_out->width;
260
261 for(int j = 0; j < roi_out->width; j++, in += ch, out += ch)
262 {
263 for(int i = 0; i < 3; i++)
264 {
265 // use base curve for values < 1, else use extrapolation.
266 if(in[i] < 1.0f)
267 out[i] = data->table[CLAMP((int)(in[i] * 0x10000ul), 0, 0xffff)];
268 else
269 out[i] = dt_iop_eval_exp(data->unbounded_coeffs, in[i]);
270 }
271 }
272 }
273 break;
274 }
275 }
276
278 dt_iop_alpha_copy(ivoid, ovoid, roi_out->width, roi_out->height);
279 return 0;
280}
281
283{
284 if(dt_gui_widgets_suppressed()) return;
287
288 float grey = fmax(fmax(self->picked_color[0], self->picked_color[1]), self->picked_color[2]);
289 p->grey_point = 100.f * grey;
290
292 dt_bauhaus_slider_set(g->grey_point, p->grey_point);
294
295 dt_dev_add_history_item(self->dev, self, TRUE, TRUE);
296}
297
299{
300 if(dt_gui_widgets_suppressed()) return;
303
304 float noise = powf(2.0f, -16.0f);
305
306 // Black
307 float black = fmax(fmax(self->picked_color_min[0], self->picked_color_min[1]), self->picked_color_min[2]);
308 float EVmin = Log2Thres(black / (p->grey_point / 100.0f), noise);
309 EVmin *= (1.0f + p->security_factor / 100.0f);
310
311 p->shadows_range = EVmin;
312
314 dt_bauhaus_slider_set(g->shadows_range, p->shadows_range);
316
317 dt_dev_add_history_item(self->dev, self, TRUE, TRUE);
318}
319
321{
322 if(dt_gui_widgets_suppressed()) return;
325
326 float noise = powf(2.0f, -16.0f);
327
328 // Black
329 float EVmin = p->shadows_range;
330
331 // White
332 float white = fmax(fmax(self->picked_color_max[0], self->picked_color_max[1]), self->picked_color_max[2]);
333 float EVmax = Log2Thres(white / (p->grey_point / 100.0f), noise);
334 EVmax *= (1.0f + p->security_factor / 100.0f);
335
336 p->dynamic_range = EVmax - EVmin;
337
339 dt_bauhaus_slider_set(g->dynamic_range, p->dynamic_range);
341
342 dt_dev_add_history_item(self->dev, self, TRUE, TRUE);
343}
344
346{
349
350 float noise = powf(2.0f, -16.0f);
351
352 // Grey
353 float grey = fmax(fmax(self->picked_color[0], self->picked_color[1]), self->picked_color[2]);
354 p->grey_point = 100.f * grey;
355
356 // Black
357 float black = fmax(fmax(self->picked_color_min[0], self->picked_color_min[1]), self->picked_color_min[2]);
358 float EVmin = Log2Thres(black / (p->grey_point / 100.0f), noise);
359 EVmin *= (1.0f + p->security_factor / 100.0f);
360
361 // White
362 float white = fmax(fmax(self->picked_color_max[0], self->picked_color_max[1]), self->picked_color_max[2]);
363 float EVmax = Log2Thres(white / (p->grey_point / 100.0f), noise);
364 EVmax *= (1.0f + p->security_factor / 100.0f);
365
366 p->shadows_range = EVmin;
367 p->dynamic_range = EVmax - EVmin;
368
370 dt_bauhaus_slider_set(g->grey_point, p->grey_point);
371 dt_bauhaus_slider_set(g->shadows_range, p->shadows_range);
372 dt_bauhaus_slider_set(g->dynamic_range, p->dynamic_range);
374
375 dt_dev_add_history_item(self->dev, self, TRUE, TRUE);
376}
377
378
379void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
380{
383
384 if(w == g->mode)
385 {
386 /* grey_point/shadows_range/dynamic_range/auto_button live on the "log" stack
387 page. Switching mode can hide that page while a picker stays active,
388 sampling/drawing on the image for a control the user can no longer see or
389 turn off from this widget. */
391
392 if(p->mode == PROFILEGAMMA_LOG)
393 {
394 gtk_stack_set_visible_child_name(GTK_STACK(g->mode_stack), "log");
395 }
396 else
397 {
398 gtk_stack_set_visible_child_name(GTK_STACK(g->mode_stack), "gamma");
399 }
400 }
401 else if(w == g->security_factor)
402 {
403 float prev = *(float *)previous;
404 float ratio = (p->security_factor - prev) / (prev + 100.0f);
405
406 float EVmin = p->shadows_range;
407 EVmin = EVmin + ratio * EVmin;
408
409 float EVmax = p->dynamic_range + p->shadows_range;
410 EVmax = EVmax + ratio * EVmax;
411
412 p->dynamic_range = EVmax - EVmin;
413 p->shadows_range = EVmin;
414
416 dt_bauhaus_slider_set(g->dynamic_range, p->dynamic_range);
417 dt_bauhaus_slider_set(g->shadows_range, p->shadows_range);
419 }
420}
421
423{
425 if (picker == g->grey_point)
426 apply_auto_grey(self);
427 else if(picker == g->shadows_range)
428 apply_auto_black(self);
429 else if(picker == g->dynamic_range)
431 else if(picker == g->auto_button)
432 apply_autotune(self);
433 else
434 fprintf(stderr, "[profile_gamma] unknown color picker\n");
435}
436
439{
442
443 const float linear = p->linear;
444 const float gamma = p->gamma;
445
446 d->linear = p->linear;
447 d->gamma = p->gamma;
448
449 float a, b, c, g;
450 if(gamma == 1.0)
451 {
453 for(int k = 0; k < 0x10000; k++) d->table[k] = 1.0 * k / 0x10000;
454 }
455 else
456 {
457 if(linear == 0.0)
458 {
460 for(int k = 0; k < 0x10000; k++) d->table[k] = powf(1.00 * k / 0x10000, gamma);
461 }
462 else
463 {
464 if(linear < 1.0)
465 {
466 g = gamma * (1.0 - linear) / (1.0 - gamma * linear);
467 a = 1.0 / (1.0 + linear * (g - 1));
468 b = linear * (g - 1) * a;
469 c = powf(a * linear + b, g) / linear;
470 }
471 else
472 {
473 a = b = g = 0.0;
474 c = 1.0;
475 }
477 for(int k = 0; k < 0x10000; k++)
478 {
479 float tmp;
480 if(k < 0x10000 * linear)
481 tmp = c * k / 0x10000;
482 else
483 tmp = powf(a * k / 0x10000 + b, g);
484 d->table[k] = tmp;
485 }
486 }
487 }
488
489 // now the extrapolation stuff:
490 const float x[4] = { 0.7f, 0.8f, 0.9f, 1.0f };
491 const float y[4]
492 = { d->table[CLAMP((int)(x[0] * 0x10000ul), 0, 0xffff)],
493 d->table[CLAMP((int)(x[1] * 0x10000ul), 0, 0xffff)],
494 d->table[CLAMP((int)(x[2] * 0x10000ul), 0, 0xffff)],
495 d->table[CLAMP((int)(x[3] * 0x10000ul), 0, 0xffff)] };
496 dt_iop_estimate_exp(x, y, 4, d->unbounded_coeffs);
497
498 d->dynamic_range = p->dynamic_range;
499 d->grey_point = p->grey_point;
500 d->shadows_range = p->shadows_range;
501 d->security_factor = p->security_factor;
502 d->mode = p->mode;
503
504 //piece->process_cl_ready = 1;
505
506 // no OpenCL for log yet.
507 //if(d->mode == PROFILEGAMMA_LOG) piece->process_cl_ready = 0;
508}
509
515
517{
518 dt_free_align(piece->data);
519 piece->data = NULL;
520}
521
523{
525}
526
535
537{
539
540 // prepare the modes widgets stack
541 g->mode_stack = gtk_stack_new();
542 gtk_stack_set_homogeneous(GTK_STACK(g->mode_stack), FALSE);
543
544 /**** GAMMA MODE ***/
545
546 GtkWidget *vbox_gamma = self->gui->widget = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING));
547
548 g->linear = dt_bauhaus_slider_from_params(self, N_("linear"));
550 gtk_widget_set_tooltip_text(g->linear, _("linear part"));
551
552 g->gamma = dt_bauhaus_slider_from_params(self, N_("gamma"));
554 gtk_widget_set_tooltip_text(g->gamma, _("gamma exponential factor"));
555
556 gtk_stack_add_named(GTK_STACK(g->mode_stack), vbox_gamma, "gamma");
557
558 /**** LOG MODE ****/
559
560 GtkWidget *vbox_log = self->gui->widget = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING));
561
562 g->grey_point
564 dt_bauhaus_slider_set_format(g->grey_point, "%");
565 gtk_widget_set_tooltip_text(g->grey_point, _("adjust to match the average luma of the subject"));
566
567 g->shadows_range
569 dt_bauhaus_slider_set_soft_max(g->shadows_range, 0.0);
570 dt_bauhaus_slider_set_format(g->shadows_range, _(" EV"));
571 gtk_widget_set_tooltip_text(g->shadows_range, _("number of stops between middle gray and pure black\nthis is a reading a posemeter would give you on the scene"));
572
573 g->dynamic_range
575 dt_bauhaus_slider_set_soft_range(g->dynamic_range, 0.5, 16.0);
576 dt_bauhaus_slider_set_format(g->dynamic_range, _(" EV"));
577 gtk_widget_set_tooltip_text(g->dynamic_range, _("number of stops between pure black and pure white\nthis is a reading a posemeter would give you on the scene"));
578
579 gtk_box_pack_start(GTK_BOX(vbox_log), dt_ui_section_label_new(_("optimize automatically")), FALSE, FALSE, 0);
580
581 g->security_factor = dt_bauhaus_slider_from_params(self, "security_factor");
582 dt_bauhaus_slider_set_format(g->security_factor, "%");
583 gtk_widget_set_tooltip_text(g->security_factor, _("enlarge or shrink the computed dynamic range\nthis is useful when noise perturbates the measurements"));
584
586 dt_bauhaus_widget_set_label(g->auto_button, N_("auto tune levels"));
587 gtk_widget_set_tooltip_text(g->auto_button, _("make an optimization with some guessing"));
588 gtk_box_pack_start(GTK_BOX(vbox_log), g->auto_button, TRUE, TRUE, 0);
589
590 gtk_stack_add_named(GTK_STACK(g->mode_stack), vbox_log, "log");
591
592 // start building top level widget
593 self->gui->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
594
595 g->mode = dt_bauhaus_combobox_from_params(self, N_("mode"));
596 gtk_widget_set_tooltip_text(g->mode, _("tone mapping method"));
597
598 gtk_box_pack_start(GTK_BOX(self->gui->widget), g->mode_stack, TRUE, TRUE, 0);
599}
600
601
602// clang-format off
603// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
604// vim: shiftwidth=2 expandtab tabstop=2 cindent
605// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
606// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
void dt_bauhaus_slider_set_soft_range(GtkWidget *widget, float soft_min, float soft_max)
Definition bauhaus.c:1498
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(GtkWidget *widget, float pos)
Definition bauhaus.c:3331
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
Definition bauhaus.c:1504
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
Definition bauhaus.c:1698
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3407
@ IOP_CS_RGB
void dt_iop_color_picker_reset(dt_iop_module_t *module, gboolean keep)
GtkWidget * dt_color_picker_new(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w)
@ DT_COLOR_PICKER_AREA
static const float x
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
const dt_colormatrix_t dt_aligned_pixel_t out
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
Definition darktable.c:646
#define dt_dev_add_history_item(dev, module, enable, redraw)
void dt_iop_params_t
Definition dev_history.h:43
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
Definition develop.h:123
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)
#define DT_GUI_MODULE(x)
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_SUPPORTS_BLENDING
Definition imageop.h:186
@ IOP_FLAGS_ALLOW_TILING
Definition imageop.h:188
@ IOP_FLAGS_ONE_INSTANCE
Definition imageop.h:191
@ IOP_GROUP_TECHNICAL
Definition imageop.h:162
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)
static dt_iop_gui_data_t * dt_iop_gui_data(const struct dt_iop_module_t *m)
The module's GUI data blob, NULL-safe for headless callers: IOP process() implementations read it for...
Definition imageop_gui.h:81
#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)
GtkWidget * dt_ui_section_label_new(const gchar *str)
Definition label.c:114
@ linear
Definition lightroom.c:369
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
static float fastlog2(float x)
Definition math.h:124
static float Log2Thres(float x, float Thres)
Definition math.h:118
#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
#define __OMP_FOR_SIMD__(...)
Definition openmp.h:97
const char ** description(struct dt_iop_module_t *self)
int default_group()
void gui_reset(dt_iop_module_t *self)
void gui_update(dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
__DT_CLONE_TARGETS__ int process(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)
static void apply_autotune(dt_iop_module_t *self)
const char * name()
void gui_init(dt_iop_module_t *self)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
static void apply_auto_dynamic_range(dt_iop_module_t *self)
void commit_params(dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void cleanup_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
int flags()
void init_presets(dt_iop_module_so_t *self)
void init_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
dt_iop_profilegamma_mode_t
@ PROFILEGAMMA_LOG
@ PROFILEGAMMA_GAMMA
static void apply_auto_black(dt_iop_module_t *self)
static void apply_auto_grey(dt_iop_module_t *self)
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
const float noise
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
unsigned int channels
Definition format.h:83
GtkWidget * widget
Definition imageop_gui.h:47
dt_dev_operation_t op
Definition imageop.h:235
dt_iop_params_t * default_params
Definition imageop.h:333
struct dt_iop_module_gui_t * gui
Definition imageop.h:346
struct dt_develop_t * dev
Definition imageop.h:311
dt_aligned_pixel_t picked_color_min
Definition imageop.h:287
dt_aligned_pixel_t picked_color_max
Definition imageop.h:287
dt_aligned_pixel_t picked_color
Definition imageop.h:287
dt_iop_params_t * params
Definition imageop.h:333
dt_iop_profilegamma_mode_t mode
dt_iop_profilegamma_mode_t mode
Region of interest passed through the pixelpipe.
Definition format.h:49
int width
Definition format.h:50
int height
Definition format.h:50
#define __DT_CLONE_TARGETS__
gboolean dt_gui_widgets_suppressed(void)
#define dt_gui_freeze_begin()
#define dt_gui_freeze_end()
#define DT_GUI_BOX_SPACING