Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
hotpixels.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011 Antony Dovgal.
4 Copyright (C) 2011 Bruce Guenter.
5 Copyright (C) 2011-2012 Henrik Andersson.
6 Copyright (C) 2011-2013, 2016 johannes hanika.
7 Copyright (C) 2011 Olivier Tribout.
8 Copyright (C) 2011 Robert Bieber.
9 Copyright (C) 2011 Rostyslav Pidgornyi.
10 Copyright (C) 2011-2016, 2019 Tobias Ellinghaus.
11 Copyright (C) 2012-2013 Pascal de Bruijn.
12 Copyright (C) 2012 Richard Wonka.
13 Copyright (C) 2012, 2014 Ulrich Pegelow.
14 Copyright (C) 2013, 2020 Aldric Renaudin.
15 Copyright (C) 2014, 2016 Dan Torop.
16 Copyright (C) 2014-2016 Roman Lebedev.
17 Copyright (C) 2015-2016 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 Edgardo Hoszowski.
21 Copyright (C) 2018 Maurizio Paglia.
22 Copyright (C) 2018, 2020, 2022 Pascal Obry.
23 Copyright (C) 2018 rawfiner.
24 Copyright (C) 2018 Stéphane Gourichon.
25 Copyright (C) 2019 Andreas Schneider.
26 Copyright (C) 2019-2020, 2022 Diederik Ter Rahe.
27 Copyright (C) 2019, 2022 Hanno Schwalm.
28 Copyright (C) 2020 Hubert Kowalski.
29 Copyright (C) 2020 Ralf Brown.
30 Copyright (C) 2022 Martin Bařinka.
31 Copyright (C) 2022 Philipp Lutz.
32
33 darktable is free software: you can redistribute it and/or modify
34 it under the terms of the GNU General Public License as published by
35 the Free Software Foundation, either version 3 of the License, or
36 (at your option) any later version.
37
38 darktable is distributed in the hope that it will be useful,
39 but WITHOUT ANY WARRANTY; without even the implied warranty of
40 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 GNU General Public License for more details.
42
43 You should have received a copy of the GNU General Public License
44 along with darktable. If not, see <http://www.gnu.org/licenses/>.
45*/
46
47#ifdef HAVE_CONFIG_H
48#include "system/macros.h"
49#include "system/mem_alloc.h"
51#include "system/openmp.h"
53#include "config.h"
54#endif
55#include "widgets/bauhaus.h"
56#include "common/imagebuf.h"
57#include "develop/imageop.h"
59#include "develop/imageop_gui.h"
60#include "develop/develop.h"
61
62#include "iop/iop_api.h"
63
64#ifdef HAVE_OPENCL
65#include "common/opencl.h"
66#endif
67
68#include <gtk/gtk.h>
69#include <stdlib.h>
70#include "widgets/label.h"
71
73
75{
76 float strength; // $MIN: 0.0 $MAX: 1.0 $DEFAULT: 0.25
77 float threshold; // $MIN: 0.0 $MAX: 1.0 $DEFAULT: 0.05
78 gboolean markfixed; // $DEFAULT: FALSE $DESCRIPTION: "mark fixed pixels"
79 gboolean permissive; // $DEFAULT: FALSE $DESCRIPTION: "detect by 3 neighbors"
81
87
95
101
102
103const char *name()
104{
105 return _("hot pixels");
106}
107
108const char **description(struct dt_iop_module_t *self)
109{
110 return dt_iop_set_description(self, _("remove abnormally bright pixels by dampening them with neighbours"),
111 _("corrective"),
112 _("linear, raw, scene-referred"),
113 _("reconstruction, raw"),
114 _("linear, raw, scene-referred"));
115}
116
117
119{
120 return IOP_GROUP_REPAIR;
121}
122
127
129{
130 return IOP_CS_RAW;
131}
132
135{
136 default_input_format(self, pipe, piece, dsc);
137 dsc->channels = 1;
139}
140
141static inline void hotpixels_testone(const float *const in, const float mid, const int offset,
142 int *const count, float *const maxin)
143{
144 const float other = in[offset];
145 if(mid > other)
146 {
147 (*count)++;
148 if(other > *maxin) *maxin = other;
149 }
150}
151
152/* Detect hot sensor pixels based on the 4 surrounding sites. Pixels
153 * having 3 or 4 (depending on permissive setting) surrounding pixels that
154 * than value*multiplier are considered "hot", and are replaced by the maximum of
155 * the neighbour pixels. The permissive variant allows for
156 * correcting pairs of hot pixels in adjacent sites. Replacement using
157 * the maximum produces fewer artifacts when inadvertently replacing
158 * non-hot pixels.
159 * This is the Bayer sensor variant. */
162 const void *const ivoid, void *const ovoid,
163 const dt_iop_roi_t *const roi_out)
164{
165 const float threshold = data->threshold;
166 const float multiplier = data->multiplier;
167 const int min_neighbours = data->permissive ? 3 : 4;
168 const int width = roi_out->width;
169 const int widthx2 = width * 2;
171 for(int row = 2; row < roi_out->height - 2; row++)
172 {
173 const float *in = (float *)ivoid + (size_t)width * row + 2;
174 float *out = (float *)ovoid + (size_t)width * row + 2;
175 for(int col = 2; col < width - 2; col++, in++, out++)
176 {
177 float mid = *in * multiplier;
178 if(*in > threshold)
179 {
180 int count = 0;
181 float maxin = 0.0;
182 hotpixels_testone(in, mid, -2, &count, &maxin);
183 hotpixels_testone(in, mid, -widthx2, &count, &maxin);
184 hotpixels_testone(in, mid, +2, &count, &maxin);
185 hotpixels_testone(in, mid, +widthx2, &count, &maxin);
186 if(count >= min_neighbours)
187 {
188 *out = maxin;
189 }
190 }
191 }
192 }
193}
194
195/* X-Trans sensor equivalent of process_bayer(). */
198 const void *const ivoid, void *const ovoid,
199 const dt_iop_roi_t *const roi_out, const uint8_t (*const xtrans)[6])
200{
201 // for each cell of sensor array, pre-calculate, a list of the x/y
202 // offsets of the four radially nearest pixels of the same color
203 int offsets[6][6][4][2];
204 // increasing offsets from pixel to find nearest like-colored pixels
205 const int search[20][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 }, { -1, -1 }, { -1, 1 }, { 1, -1 },
206 { 1, 1 }, { -2, 0 }, { 2, 0 }, { 0, -2 }, { 0, 2 }, { -2, -1 }, { -2, 1 },
207 { 2, -1 }, { 2, 1 }, { -1, -2 }, { 1, -2 }, { -1, 2 }, { 1, 2 } };
208
209 for(int j = 0; j < 6; ++j)
210 {
211 for(int i = 0; i < 6; ++i)
212 {
213 const uint8_t c = FCxtrans(j, i, roi_out, xtrans);
214 for(int s = 0, found = 0; s < 20 && found < 4; ++s)
215 {
216 if(c == FCxtrans(j + search[s][1], i + search[s][0], roi_out, xtrans))
217 {
218 offsets[j][i][found][0] = search[s][0];
219 offsets[j][i][found][1] = search[s][1];
220 ++found;
221 }
222 }
223 }
224 }
225
226 const float threshold = data->threshold;
227 const float multiplier = data->multiplier;
228 const int min_neighbours = data->permissive ? 3 : 4;
229 const int width = roi_out->width;
231 for(int row = 2; row < roi_out->height - 2; row++)
232 {
233 const float *in = (float *)ivoid + (size_t)width * row + 2;
234 float *out = (float *)ovoid + (size_t)width * row + 2;
235 for(int col = 2; col < width - 2; col++, in++, out++)
236 {
237 float mid = *in * multiplier;
238 if(*in > threshold)
239 {
240 int count = 0;
241 float maxin = 0.0;
242 for(int n = 0; n < 4; ++n)
243 {
244 int xx = offsets[row % 6][col % 6][n][0];
245 int yy = offsets[row % 6][col % 6][n][1];
246 float other = *(in + xx + yy * (size_t)width);
247 if(mid > other)
248 {
249 count++;
250 if(other > maxin) maxin = other;
251 }
252 }
253 // NOTE: it seems that detecting by 2 neighbors would help for extreme cases
254 if(count >= min_neighbours)
255 {
256 *out = maxin;
257 }
258 }
259 }
260 }
261}
262
263int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
264 void *const ovoid)
265{
266 const dt_iop_roi_t *const roi_out = &piece->roi_out;
268
269 // The processing loop should output only a few pixels, so just copy everything first
270 dt_iop_image_copy_by_size(ovoid, ivoid, roi_out->width, roi_out->height, 1);
271
272 if(piece->dsc_in.filters == 9u)
273 {
274 process_xtrans(data, ivoid, ovoid, roi_out, (const uint8_t(*const)[6])piece->dsc_in.xtrans);
275 }
276 else
277 {
278 process_bayer(data, ivoid, ovoid, roi_out);
279 }
280
281 return 0;
282}
283
284#ifdef HAVE_OPENCL
285int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe,
286 const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
287{
288 const dt_iop_roi_t *const roi_out = &piece->roi_out;
289 const dt_iop_hotpixels_data_t *const data = (dt_iop_hotpixels_data_t *)piece->data;
291
292 const int devid = pipe->devid;
293 const int min_neighbours = data->permissive ? 3 : 4;
294 const int width = roi_out->width;
295 const int height = roi_out->height;
296 const uint32_t filters = piece->dsc_in.filters;
297 cl_mem dev_xtrans = NULL;
298 cl_int err = 0;
299 int kernel = filters == 9u ? gd->kernel_hotpixels_xtrans : gd->kernel_hotpixels_bayer;
300
301 if(filters == 9u)
302 {
303 dev_xtrans = dt_opencl_copy_host_to_device_constant(devid, sizeof(piece->dsc_in.xtrans), (void *)piece->dsc_in.xtrans);
304 if(IS_NULL_PTR(dev_xtrans)) goto error;
305 }
306
307 size_t sizes[3] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
308 dt_opencl_set_kernel_arg(devid, kernel, 0, sizeof(cl_mem), (void *)&dev_in);
309 dt_opencl_set_kernel_arg(devid, kernel, 1, sizeof(cl_mem), (void *)&dev_out);
310 dt_opencl_set_kernel_arg(devid, kernel, 2, sizeof(int), (void *)&width);
311 dt_opencl_set_kernel_arg(devid, kernel, 3, sizeof(int), (void *)&height);
312 dt_opencl_set_kernel_arg(devid, kernel, 4, sizeof(float), (void *)&data->threshold);
313 dt_opencl_set_kernel_arg(devid, kernel, 5, sizeof(float), (void *)&data->multiplier);
314 dt_opencl_set_kernel_arg(devid, kernel, 6, sizeof(int), (void *)&min_neighbours);
315
316 if(filters == 9u)
317 {
318 const int rx = roi_out->x;
319 const int ry = roi_out->y;
320 dt_opencl_set_kernel_arg(devid, kernel, 7, sizeof(int), (void *)&rx);
321 dt_opencl_set_kernel_arg(devid, kernel, 8, sizeof(int), (void *)&ry);
322 dt_opencl_set_kernel_arg(devid, kernel, 9, sizeof(cl_mem), (void *)&dev_xtrans);
323 }
324
325 err = dt_opencl_enqueue_kernel_2d(devid, kernel, sizes);
326 if(err != CL_SUCCESS) goto error;
327
329 return TRUE;
330
331error:
333 return FALSE;
334}
335
337{
338 const int program = 2; // basic.cl
340 module->data = gd;
341 gd->kernel_hotpixels_bayer = dt_opencl_create_kernel(program, "hotpixels_bayer");
342 gd->kernel_hotpixels_xtrans = dt_opencl_create_kernel(program, "hotpixels_xtrans");
343}
344
352#endif
353
354/* Single source of truth: hot-pixel detection works on the raw CFA mosaic, so it requires a
355 * mosaiced buffer (needs_demosaic), NOT merely the RAW flag — an already-demosaiced raw
356 * (sRAW / linear DNG) has no CFA to analyse. Shared by reload_defaults() and force_enable(). */
357static gboolean _hotpixels_supported(const dt_image_t *img)
358{
360}
361
363{
364 const dt_image_t *img = &module->dev->image_storage;
365 const gboolean enabled = _hotpixels_supported(img);
366 // can't be switched on for non-mosaiced images:
367 module->hide_enable_button = !enabled;
368 dt_iop_fmt_log(module, "reload_defaults: class=%s needs_demosaic=%d mono=%d -> hide_enable=%d",
371}
372
373gboolean force_enable(struct dt_iop_module_t *self, const gboolean current_state)
374{
375 // History sanitization: a hotpixels entry pasted onto a non-mosaic/monochrome image is forced
376 // off here. The runtime-only "strength == 0" no-op shortcut stays in commit_params().
377 const gboolean active = _hotpixels_supported(&self->dev->image_storage);
378 const gboolean state = current_state && active;
379 dt_iop_fmt_log(self, "force_enable: class=%s supported=%d current=%d -> %d",
381 active, current_state, state);
382 return state;
383}
384
387{
390 d->filters = pipe->dev->image_storage.dsc.filters;
391 d->multiplier = p->strength / 2.0;
392 d->threshold = p->threshold;
393 d->permissive = p->permissive;
394
395 // Image-type gating is handled at history level (force_enable/reload_defaults). Only the
396 // runtime, param-driven no-op shortcut remains here: a zero strength does nothing.
397 if(p->strength == 0.0) piece->enabled = 0;
398 dt_iop_fmt_log(self, "commit: class=%s filters=%u strength=%.3f -> enabled=%d",
400 d->filters, p->strength, piece->enabled);
401}
402
404{
406 piece->data_size = sizeof(dt_iop_hotpixels_data_t);
407}
408
410{
411 dt_free_align(piece->data);
412 piece->data = NULL;
413}
414
415
417{
420 gtk_toggle_button_set_active(g->permissive, p->permissive);
421
422 const dt_image_t *img = &self->dev->image_storage;
423 const gboolean enabled = _hotpixels_supported(img);
424 // can't be switched on for non-mosaiced images:
426
427 gtk_stack_set_visible_child_name(GTK_STACK(self->gui->widget), self->hide_enable_button ? "non_raw" : "raw");
428}
429
431{
433
434 GtkWidget *box_raw = self->gui->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
435
436 g->threshold = dt_bauhaus_slider_from_params(self, N_("threshold"));
437 dt_bauhaus_slider_set_digits(g->threshold, 4);
438 gtk_widget_set_tooltip_text(g->threshold, _("lower threshold for hot pixel"));
439
440 g->strength = dt_bauhaus_slider_from_params(self, N_("strength"));
441 dt_bauhaus_slider_set_digits(g->strength, 4);
442 gtk_widget_set_tooltip_text(g->strength, _("strength of hot pixel correction"));
443
444 // 3 neighbours
445 g->permissive = GTK_TOGGLE_BUTTON(dt_bauhaus_toggle_from_params(self, "permissive"));
446
447 // start building top level widget
448 self->gui->widget = gtk_stack_new();
449 gtk_stack_set_homogeneous(GTK_STACK(self->gui->widget), FALSE);
450
451 GtkWidget *label_non_raw = dt_ui_label_new(_("hot pixel correction\nonly works for raw images."));
452
453 gtk_stack_add_named(GTK_STACK(self->gui->widget), label_non_raw, "non_raw");
454 gtk_stack_add_named(GTK_STACK(self->gui->widget), box_raw, "raw");
455}
456
457// clang-format off
458// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
459// vim: shiftwidth=2 expandtab tabstop=2 cindent
460// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
461// 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
@ IOP_CS_RAW
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
const float threshold
const dt_colormatrix_t dt_aligned_pixel_t out
static const int row
dt_image_pipe_class_t dt_image_pipe_class(const dt_image_t *img)
const char * dt_image_pipe_class_name(const dt_image_pipe_class_t klass)
gboolean dt_image_is_monochrome(const dt_image_t *img)
gboolean dt_image_needs_demosaic(const dt_image_t *img)
static int FCxtrans(const int row, const int col, global const unsigned char(*const xtrans)[6])
void dt_iop_params_t
Definition dev_history.h:43
void default_input_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
gboolean enabled
–doc was passed on the command line
const char ** description(struct dt_iop_module_t *self)
Definition hotpixels.c:108
int default_group()
Definition hotpixels.c:118
void reload_defaults(dt_iop_module_t *module)
Definition hotpixels.c:362
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 hotpixels.c:385
void gui_update(dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
Definition hotpixels.c:416
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition hotpixels.c:403
const char * name()
Definition hotpixels.c:103
static void hotpixels_testone(const float *const in, const float mid, const int offset, int *const count, float *const maxin)
Definition hotpixels.c:141
void gui_init(dt_iop_module_t *self)
Definition hotpixels.c:430
static __DT_CLONE_TARGETS__ void process_bayer(const dt_iop_hotpixels_data_t *data, const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_out)
Definition hotpixels.c:161
void cleanup_global(dt_iop_module_so_t *module)
Definition hotpixels.c:345
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition hotpixels.c:128
void input_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
Definition hotpixels.c:133
int flags()
Definition hotpixels.c:123
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 hotpixels.c:263
gboolean force_enable(struct dt_iop_module_t *self, const gboolean current_state)
Definition hotpixels.c:373
static __DT_CLONE_TARGETS__ void process_xtrans(const dt_iop_hotpixels_data_t *data, const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_out, const uint8_t(*const xtrans)[6])
Definition hotpixels.c:197
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition hotpixels.c:409
void init_global(dt_iop_module_so_t *module)
Definition hotpixels.c:336
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 hotpixels.c:285
static gboolean _hotpixels_supported(const dt_image_t *img)
Definition hotpixels.c:357
static void dt_iop_image_copy_by_size(float *const __restrict__ out, const float *const __restrict__ in, const size_t width, const size_t height, const size_t ch)
Definition imagebuf.h:91
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
#define dt_iop_fmt_log(module, fmt,...)
Debug helper to trace a module's input-format-driven decisions on the -d pipe channel (DT_DEBUG_PIPE)...
Definition imageop.h:535
@ IOP_FLAGS_SUPPORTS_BLENDING
Definition imageop.h:186
@ IOP_FLAGS_ONE_INSTANCE
Definition imageop.h:191
@ IOP_GROUP_REPAIR
Definition imageop.h:159
GtkWidget * dt_bauhaus_toggle_from_params(dt_iop_module_t *self, const char *param)
GtkWidget * dt_bauhaus_slider_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 float kernel(const float *x, const float *y)
GtkWidget * dt_ui_label_new(const gchar *str)
Definition label.c:125
#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.
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
Definition opencl.c:2554
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
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_release_mem_object(cl_mem mem)
Definition opencl.c:2805
#define ROUNDUPDHT(a, b)
Definition opencl.h:86
#define ROUNDUPDWD(a, b)
Definition opencl.h:85
#define __OMP_PARALLEL_FOR__(...)
Definition openmp.h:95
void dt_iop_buffer_dsc_update_bpp(dt_iop_buffer_dsc_t *dsc)
const float uint32_t state[4]
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
struct dt_develop_t * dev
dt_image_t image_storage
Definition develop.h:225
dt_iop_buffer_dsc_t dsc
Definition image.h:419
uint32_t filters
Definition format.h:89
unsigned int channels
Definition format.h:83
uint8_t xtrans[6][6]
Definition format.h:99
GtkToggleButton * permissive
Definition hotpixels.c:85
GtkWidget * widget
Definition imageop_gui.h:47
dt_iop_global_data_t * data
Definition imageop.h:238
int32_t hide_enable_button
Definition imageop.h:270
struct dt_iop_module_gui_t * gui
Definition imageop.h:346
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
int width
Definition format.h:50
int height
Definition format.h:50
#define __DT_CLONE_TARGETS__
#define DT_GUI_BOX_SPACING