Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
rawprepare.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2014-2017, 2020 Roman Lebedev.
4 Copyright (C) 2016 Dan Torop.
5 Copyright (C) 2016, 2018 johannes hanika.
6 Copyright (C) 2016, 2018-2019 Tobias Ellinghaus.
7 Copyright (C) 2016 Ulrich Pegelow.
8 Copyright (C) 2018 Edgardo Hoszowski.
9 Copyright (C) 2018 Maurizio Paglia.
10 Copyright (C) 2018, 2020-2022 Pascal Obry.
11 Copyright (C) 2018 rawfiner.
12 Copyright (C) 2019 Andreas Schneider.
13 Copyright (C) 2019-2022 Hanno Schwalm.
14 Copyright (C) 2020 Aldric Renaudin.
15 Copyright (C) 2020-2021, 2023, 2025-2026 Aurélien PIERRE.
16 Copyright (C) 2020, 2022 Diederik Ter Rahe.
17 Copyright (C) 2020 Hubert Kowalski.
18 Copyright (C) 2020, 2022 Ralf Brown.
19 Copyright (C) 2021 luzpaz.
20 Copyright (C) 2022 Martin Bařinka.
21 Copyright (C) 2022 paolodepetrillo.
22 Copyright (C) 2022 Philipp Lutz.
23
24 darktable is free software: you can redistribute it and/or modify
25 it under the terms of the GNU General Public License as published by
26 the Free Software Foundation, either version 3 of the License, or
27 (at your option) any later version.
28
29 darktable is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
33
34 You should have received a copy of the GNU General Public License
35 along with darktable. If not, see <http://www.gnu.org/licenses/>.
36*/
37#ifdef HAVE_CONFIG_H
38#include "common/darktable.h"
39#include "config.h"
40#endif
41#include "bauhaus/bauhaus.h"
42#include "common/imageio_rawspeed.h" // for dt_rawspeed_crop_dcraw_filters
43#include "common/opencl.h"
44#include "common/imagebuf.h"
45#include "common/image.h"
46#include "develop/imageop.h"
47#include "develop/imageop_gui.h"
48#include "develop/tiling.h"
49#include "common/image_cache.h"
50
51#include "gui/gtk.h"
52#include "gui/presets.h"
53#include "iop/iop_api.h"
54#include "common/dng_opcode.h"
55
56#include <gtk/gtk.h>
57#include <stdint.h>
58#include <stdlib.h>
59
61
63{
64 FLAT_FIELD_OFF = 0, // $DESCRIPTION: "disabled"
65 FLAT_FIELD_EMBEDDED = 1 // $DESCRIPTION: "embedded GainMap"
67
69{
70 int32_t x; // $MIN: 0 $MAX: UINT16_MAX $DESCRIPTION: "crop left"
71 int32_t y; // $MIN: 0 $MAX: UINT16_MAX $DESCRIPTION: "crop top"
72 int32_t width; // $MIN: 0 $MAX: UINT16_MAX $DESCRIPTION: "crop right"
73 int32_t height; // $MIN: 0 $MAX: UINT16_MAX $DESCRIPTION: "crop bottom"
74 uint16_t raw_black_level_separate[4]; // $MIN: 0 $MAX: UINT16_MAX $DESCRIPTION: "black level"
75 uint16_t raw_white_point; // $MIN: 0 $MAX: UINT16_MAX $DESCRIPTION: "white point"
76 dt_iop_rawprepare_flat_field_t flat_field; // $DEFAULT: FLAT_FIELD_OFF $DESCRIPTION: "flat field correction"
78
86
88{
89 int32_t x, y, width, height; // crop, now unused, for future expansion
90 float sub[4];
91 float div[4];
92
93 // cached for dt_iop_buffer_dsc_t::rawprepare
94 struct
95 {
99
100 // image contains GainMaps that should be applied
102 // GainMap for each filter of RGGB Bayer pattern
105
114
115
116const char *name()
117{
118 return C_("modulename", "Raw settings");
119}
120
122{
123 return IOP_TAG_DISTORT;
124}
125
131
133{
134 return IOP_GROUP_TECHNICAL;
135}
136
138{
139 if(piece && piece->dsc_in.cst != IOP_CS_RAW)
140 return IOP_CS_RGB;
141 return IOP_CS_RAW;
142}
143
144int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version,
145 void *new_params, const int new_version)
146{
148 typedef struct dt_iop_rawprepare_params_v1_t
149 {
150 int32_t x;
151 int32_t y;
152 int32_t width;
153 int32_t height;
154 uint16_t raw_black_level_separate[4];
155 uint16_t raw_white_point;
156 } dt_iop_rawprepare_params_v1_t;
157
158 if(old_version == 1 && new_version == 2)
159 {
160 dt_iop_rawprepare_params_v1_t *o = (dt_iop_rawprepare_params_v1_t *)old_params;
161 dt_iop_rawprepare_params_v2_t *n = (dt_iop_rawprepare_params_v2_t *)new_params;
162 memcpy(n, o, sizeof *o);
163 n->flat_field = FLAT_FIELD_OFF;
164 return 0;
165 }
166
167 return 1;
168}
169
170const char **description(struct dt_iop_module_t *self)
171{
172 return dt_iop_set_description(self, _("sets technical specificities of the raw sensor.\n"
173 "touch with great care!"),
174 _("mandatory"),
175 _("linear, raw, scene-referred"),
176 _("linear, raw"),
177 _("linear, raw, scene-referred"));
178}
179
181{
183
184 dt_gui_presets_add_generic(_("passthrough"), self->op, self->version(),
186 .y = 0,
187 .width = 0,
188 .height = 0,
189 .raw_black_level_separate[0] = 0,
190 .raw_black_level_separate[1] = 0,
191 .raw_black_level_separate[2] = 0,
192 .raw_black_level_separate[3] = 0,
193 .raw_white_point = UINT16_MAX },
195
197}
198
199static inline __attribute__((always_inline)) int compute_proper_crop(const dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *const roi_in, int value)
200{
201 const double scale = roi_in->scale;
202 return (int)roundf((double)value * scale);
203}
204
206 const dt_dev_pixelpipe_iop_t *piece,
207 const dt_iop_roi_t *const roi_in,
209{
210 if(IS_NULL_PTR(pipe) || IS_NULL_PTR(piece) || IS_NULL_PTR(roi_in) || IS_NULL_PTR(dsc)) return;
211
212 dsc->filters = pipe->dev->image_storage.dsc.filters;
213 memcpy(dsc->xtrans, pipe->dev->image_storage.dsc.xtrans, sizeof(dsc->xtrans));
214
215 if(!pipe->dev->image_storage.dsc.filters) return;
216
217 /* Rawprepare is the stage that converts the immutable sensor-aligned RAW descriptor
218 * attached to the input image into the runtime descriptor seen by downstream RAW
219 * modules. Rebuild that contract from the pipe image each time instead of chaining
220 * shifts from `piece->dsc_in`, otherwise repeated ROI planning can compound the
221 * Bayer/X-Trans phase offset.
222 *
223 * Only the fixed sensor border trim (d->x/d->y) is folded in here: that offset is
224 * constant for a given image, regardless of how the user pans/zooms/crops downstream.
225 * The dynamic, ROI-dependent part of the phase shift is applied downstream, fresh on
226 * every process()/process_cl() call, from the module's own current roi_in (see the
227 * matching comment at the top of demosaic.c's process()) — not here, and not from any
228 * ROI callback, since piece->dsc_in is not guaranteed to be populated yet at that point. */
229
231 const uint32_t crop_x = compute_proper_crop(piece, roi_in, d->x);
232 const uint32_t crop_y = compute_proper_crop(piece, roi_in, d->y);
233
234 dsc->filters = dt_rawspeed_crop_dcraw_filters(pipe->dev->image_storage.dsc.filters, crop_x, crop_y);
235
237 "[rawprepare] pipe %p (%s) thread %lu piece %p dsc %p roi_in=(%d,%d) scale=%f d->x,y=(%d,%d) -> crop=(%u,%u) filters=0x%x -> 0x%x\n",
238 (void *)pipe, pipe->type == DT_DEV_PIXELPIPE_FULL ? "full" :
239 pipe->type == DT_DEV_PIXELPIPE_PREVIEW ? "preview" :
240 pipe->type == DT_DEV_PIXELPIPE_EXPORT ? "export" :
241 pipe->type == DT_DEV_PIXELPIPE_THUMBNAIL ? "thumbnail" : "none",
242 (unsigned long)pthread_self(), (void *)piece, (void *)dsc,
243 roi_in->x, roi_in->y, roi_in->scale, d->x, d->y, crop_x, crop_y,
244 pipe->dev->image_storage.dsc.filters, dsc->filters);
245
246 if(pipe->dev->image_storage.dsc.filters != 9u) return;
247
256 for(int i = 0; i < 6; ++i)
257 {
258 for(int j = 0; j < 6; ++j)
259 {
260 dsc->xtrans[j][i] = pipe->dev->image_storage.dsc.xtrans[(j + crop_y) % 6][(i + crop_x) % 6];
261 }
262 }
263}
264
266 float *const restrict points, size_t points_count)
267{
268 (void)self;
269 (void)pipe;
271
272 // nothing to be done if parameters are set to neutral values (no top/left crop)
273 if (d->x == 0 && d->y == 0) return 1;
274
275 const double scale = piece->buf_in.scale;
276 const double x = (double)d->x * scale;
277 const double y = (double)d->y * scale;
278 __OMP_PARALLEL_FOR_SIMD__(aligned(points:64) if(points_count > 100))
279 for(size_t i = 0; i < points_count * 2; i += 2)
280 {
281 points[i] -= x;
282 points[i + 1] -= y;
283 }
284
285
286 return 1;
287}
288
290 float *const restrict points, size_t points_count)
291{
292 (void)self;
293 (void)pipe;
295
296 // nothing to be done if parameters are set to neutral values (no top/left crop)
297 if (d->x == 0 && d->y == 0) return 1;
298
299 const double scale = piece->buf_in.scale;
300 const double x = (double)d->x * scale;
301 const double y = (double)d->y * scale;
302 __OMP_PARALLEL_FOR_SIMD__(aligned(points:64) if(points_count > 100))
303 for(size_t i = 0; i < points_count * 2; i += 2)
304 {
305 points[i] += x;
306 points[i + 1] += y;
307 }
308
309
310 return 1;
311}
312
313void distort_mask(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe,
314 struct dt_dev_pixelpipe_iop_t *piece, const float *const in, float *const out,
315 const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
316{
317 (void)self;
318 (void)pipe;
319 (void)piece;
320 dt_iop_copy_image_roi(out, in, 1, roi_in, roi_out, TRUE);
321}
322
323// we're not scaling here (bayer input), so just crop borders
324// see ../../doc/resizing-scaling.md for details
326 dt_iop_roi_t *roi_out,
327 const dt_iop_roi_t *const roi_in)
328{
329 *roi_out = *roi_in;
331
332 roi_out->x = roi_out->y = 0;
333
334 const double x = d->x + d->width;
335 const double y = d->y + d->height;
336 const double scale = roi_in->scale;
337 roi_out->width = (int)round((double)roi_out->width - x * scale);
338 roi_out->height = (int)round((double)roi_out->height - y * scale);
339
340 /* Rawprepare changes the CFA phase according to the effective crop on the current ROI scale.
341 * That contract cannot be authored at history resync time because `piece->roi_in` is not known yet.
342 * Bind the crop-dependent descriptor fields here, when ROI planning has provided the real input ROI. */
343 _update_output_cfa_descriptor(pipe, piece, roi_in, &piece->dsc_out);
344}
345
346// see ../../doc/resizing-scaling.md for details
348 const dt_iop_roi_t *const roi_out,
349 dt_iop_roi_t *roi_in)
350{
351 *roi_in = *roi_out;
353
354 const double x = d->x + d->width;
355 const double y = d->y + d->height;
356 const double scale = roi_in->scale;
357 roi_in->width = (int)round((double)roi_in->width + x * scale);
358 roi_in->height = (int)round((double)roi_in->height + y * scale);
359
360 /* Same reasoning as in modify_roi_out(): the CFA/X-Trans descriptor depends on the input ROI scale,
361 * so finalize it here once the upstream ROI has been computed. */
362 _update_output_cfa_descriptor(pipe, piece, roi_in, &piece->dsc_out);
363}
364
367{
368 default_output_format(self, pipe, piece, dsc);
369 _update_output_cfa_descriptor(pipe, piece, &piece->roi_in, &piece->dsc_out);
370}
371
372
375{
376 memcpy(dsc, &pipe->dev->image_storage.dsc, sizeof(dt_iop_buffer_dsc_t));
377}
378
379
380static inline __attribute__((always_inline)) int BL(const dt_iop_roi_t *const roi_out,
381 const int row, const int col,
382 const int32_t x, const int32_t y)
383{
384 return ((((row + roi_out->y + y) & 1) << 1) + ((col + roi_out->x + x) & 1));
385}
386
399void autoset(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe,
400 const struct dt_dev_pixelpipe_iop_t *piece, const void *input)
401{
403 const dt_iop_roi_t *const roi_out = &piece->roi_out;
404 const dt_iop_roi_t *const roi_in = &piece->roi_in;
405 const int csx = compute_proper_crop(piece, roi_in, p->x);
406 const int csy = compute_proper_crop(piece, roi_in, p->y);
407
408 if(piece->dsc_in.filters && piece->dsc_in.channels == 1 && piece->dsc_in.datatype == TYPE_UINT16)
409 {
410 const uint16_t *const restrict in = (const uint16_t *const restrict)input;
411 // 4 channels : R, G sampled on R rows, G sampled on B rows, B.
412 int max_RGB[4] = { 0 };
413
414 __OMP_PARALLEL_FOR__(reduction(max: max_RGB[:4]) collapse(2))
415 for(int i = 0; i < roi_out->height; i++)
416 for(int j = 0; j < roi_out->width; j++)
417 {
418 const size_t channel = BL(roi_out, i, j, p->x, p->y);
419 const size_t pin = roi_in->width * (i + csy) + j + csx;
420 const int pixel = in[pin];
421 max_RGB[channel] = MAX(max_RGB[channel], pixel);
422 }
423
424 p->raw_white_point = MAX(MAX(max_RGB[0], MAX(max_RGB[1], MAX(max_RGB[2], max_RGB[3]))), pipe->dev->image_storage.raw_white_point);
425 }
426 // Do we need to handle float mosaiced images and non-mosaiced (sRAW) images too ?
427}
428
429/* Some comments about the cpu code path; tests with gcc 10.x show a clear performance gain for the
430 compile generated code vs SSE specific code. This depends slightly on the cpu but it's 1.2 to 3-fold
431 better for all tested cases.
432*/
434int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece,
435 const void *const ivoid, void *const ovoid)
436{
437 const dt_iop_roi_t *const roi_in = &piece->roi_in;
438 const dt_iop_roi_t *const roi_out = &piece->roi_out;
440 const int width = roi_out->width;
441 const int height = roi_out->height;
442 const int input_width = roi_in->width;
443 const int roi_x = roi_out->x;
444 const int roi_y = roi_out->y;
445 const int cfa_x = roi_x + d->x;
446 const int cfa_y = roi_y + d->y;
447 // fprintf(stderr, "roi in %d %d %d %d\n", roi_in->x, roi_in->y, roi_in->width, roi_in->height);
448 // fprintf(stderr, "roi out %d %d %d %d\n", roi_out->x, roi_out->y, roi_out->width, roi_out->height);
449
450 const int csx = compute_proper_crop(piece, roi_in, d->x);
451 const int csy = compute_proper_crop(piece, roi_in, d->y);
452
453 if(piece->dsc_in.filters && piece->dsc_in.channels == 1
454 && piece->dsc_in.datatype == TYPE_UINT16)
455 { // raw mosaic
456
457 const uint16_t *const in = (const uint16_t *const)ivoid;
458 float *const out = (float *const)ovoid;
459 const int x_phase = cfa_x & 1;
460 float inv_div[4];
461 for(int k = 0; k < 4; k++) inv_div[k] = 1.0f / d->div[k];
463 for(int j = 0; j < height; j++)
464 {
465 /* Keep the 2-sensel Bayer period explicit per row, but use scalar
466 normalization so the compiler can choose its own vectorization. */
467 const size_t pin = (size_t)input_width * (j + csy) + csx;
468 const size_t pout = (size_t)j * width;
469 const int row_phase = ((j + cfa_y) & 1) << 1;
470 const int id0 = row_phase + x_phase;
471 const int id1 = row_phase + (x_phase ^ 1);
472 const float sub0 = d->sub[id0];
473 const float sub1 = d->sub[id1];
474 const float inv0 = inv_div[id0];
475 const float inv1 = inv_div[id1];
476 int i = 0;
477
478 for(; i + 1 < width; i += 2)
479 {
480 out[pout + i + 0] = ((float)in[pin + i + 0] - sub0) * inv0;
481 out[pout + i + 1] = ((float)in[pin + i + 1] - sub1) * inv1;
482 }
483
484 for(; i < width; i++)
485 {
486 const int id = row_phase + ((x_phase + i) & 1);
487 out[pout + i] = ((float)in[pin + i] - d->sub[id]) * inv_div[id];
488 }
489 }
490
491 }
492 else if(piece->dsc_in.filters && piece->dsc_in.channels == 1
493 && piece->dsc_in.datatype == TYPE_FLOAT)
494 { // raw mosaic, fp, unnormalized
495
496 const float *const in = (const float *const)ivoid;
497 float *const out = (float *const)ovoid;
498 const int x_phase = cfa_x & 1;
499 float inv_div[4];
500 for(int k = 0; k < 4; k++) inv_div[k] = 1.0f / d->div[k];
501
503 for(int j = 0; j < height; j++)
504 {
505 /* Keep the 2-sensel Bayer period explicit per row, but use scalar
506 normalization so the compiler can choose its own vectorization. */
507 const size_t pin = (size_t)input_width * (j + csy) + csx;
508 const size_t pout = (size_t)j * width;
509 const int row_phase = ((j + cfa_y) & 1) << 1;
510 const int id0 = row_phase + x_phase;
511 const int id1 = row_phase + (x_phase ^ 1);
512 const float sub0 = d->sub[id0];
513 const float sub1 = d->sub[id1];
514 const float inv0 = inv_div[id0];
515 const float inv1 = inv_div[id1];
516 int i = 0;
517
518 for(; i + 1 < width; i += 2)
519 {
520 out[pout + i + 0] = (in[pin + i + 0] - sub0) * inv0;
521 out[pout + i + 1] = (in[pin + i + 1] - sub1) * inv1;
522 }
523
524 for(; i < width; i++)
525 {
526 const int id = row_phase + ((x_phase + i) & 1);
527 out[pout + i] = (in[pin + i] - d->sub[id]) * inv_div[id];
528 }
529 }
530
531 }
532 else
533 { // pre-downsampled buffer that needs black/white scaling
534
535 const float *const in = (const float *const)ivoid;
536 float *const out = (float *const)ovoid;
537
538 const float sub = d->sub[0];
539 const float div = d->div[0];
540
541 const int ch = piece->dsc_in.channels;
542 __OMP_PARALLEL_FOR__(collapse(3))
543 for(int j = 0; j < height; j++)
544 {
545 for(int i = 0; i < width; i++)
546 {
547 for(int c = 0; c < ch; c++)
548 {
549 const size_t pin = (size_t)ch * (input_width * (j + csy) + csx + i) + c;
550 const size_t pout = (size_t)ch * (j * width + i) + c;
551
552 out[pout] = (in[pin] - sub) / div;
553 }
554 }
555 }
556
557 }
558
559 if(piece->dsc_in.filters && piece->dsc_in.channels == 1 && d->apply_gainmaps)
560 {
561 const uint32_t map_w = d->gainmaps[0]->map_points_h;
562 const uint32_t map_h = d->gainmaps[0]->map_points_v;
563 const float im_to_rel_x = 1.0f / piece->buf_in.width;
564 const float im_to_rel_y = 1.0f / piece->buf_in.height;
565 const float rel_to_map_x = 1.0f / d->gainmaps[0]->map_spacing_h;
566 const float rel_to_map_y = 1.0f / d->gainmaps[0]->map_spacing_v;
567 const float map_origin_h = d->gainmaps[0]->map_origin_h;
568 const float map_origin_v = d->gainmaps[0]->map_origin_v;
569 float *const out = (float *const)ovoid;
571 for(int j = 0; j < height; j++)
572 {
573 const float y_map = CLAMP(((roi_y + csy + j) * im_to_rel_y - map_origin_v) * rel_to_map_y, 0, map_h);
574 const uint32_t y_i0 = MIN(y_map, map_h - 1);
575 const uint32_t y_i1 = MIN(y_i0 + 1, map_h - 1);
576 const float y_frac = y_map - y_i0;
577 const float * restrict map_row0[4];
578 const float * restrict map_row1[4];
579 for(int f = 0; f < 4; f++)
580 {
581 map_row0[f] = &d->gainmaps[f]->map_gain[y_i0 * map_w];
582 map_row1[f] = &d->gainmaps[f]->map_gain[y_i1 * map_w];
583 }
584 for(int i = 0; i < width; i++)
585 {
586 const int id = BL(roi_out, j, i, d->x, d->y);
587 const float x_map = CLAMP(((roi_x + csx + i) * im_to_rel_x - map_origin_h) * rel_to_map_x, 0, map_w);
588 const uint32_t x_i0 = MIN(x_map, map_w - 1);
589 const uint32_t x_i1 = MIN(x_i0 + 1, map_w - 1);
590 const float x_frac = x_map - x_i0;
591 const float gain_top = (1.0f - x_frac) * map_row0[id][x_i0] + x_frac * map_row0[id][x_i1];
592 const float gain_bottom = (1.0f - x_frac) * map_row1[id][x_i0] + x_frac * map_row1[id][x_i1];
593 out[j * width + i] *= (1.0f - y_frac) * gain_top + y_frac * gain_bottom;
594 }
595 }
596
597 }
598
599 return 0;
600}
601
602#ifdef HAVE_OPENCL
604 cl_mem dev_in, cl_mem dev_out)
605{
606 const dt_iop_roi_t *const roi_in = &piece->roi_in;
607 const dt_iop_roi_t *const roi_out = &piece->roi_out;
610
611 // Scanner DNGs and already-demosaiced files have no CFA; OpenCL path assumes CFA.
612 if(piece->dsc_in.filters == 0) return FALSE;
613
614 const int devid = pipe->devid;
615 cl_mem dev_sub = NULL;
616 cl_mem dev_div = NULL;
617 cl_mem dev_gainmap[4] = {0};
618 cl_int err = -999;
619
620 int kernel = -1;
621 gboolean gainmap_args = FALSE;
622
623 // Monochrome raws (no CFA) also come in as 1 channel; use the 1f kernels regardless of filters.
624 if(piece->dsc_in.channels == 1 && piece->dsc_in.datatype == TYPE_UINT16)
625 {
626 if(d->apply_gainmaps)
627 {
629 gainmap_args = TRUE;
630 }
631 else
632 {
634 }
635 }
636 else if(piece->dsc_in.channels == 1 && piece->dsc_in.datatype == TYPE_FLOAT)
637 {
638 if(d->apply_gainmaps)
639 {
641 gainmap_args = TRUE;
642 }
643 else
644 {
646 }
647 }
648 else
649 {
651 }
652
653 const int csx = compute_proper_crop(piece, roi_in, d->x), csy = compute_proper_crop(piece, roi_in, d->y);
654
655 dev_sub = dt_opencl_copy_host_to_device_constant(devid, sizeof(float) * 4, d->sub);
656 if(IS_NULL_PTR(dev_sub)) goto error;
657
658 dev_div = dt_opencl_copy_host_to_device_constant(devid, sizeof(float) * 4, d->div);
659 if(IS_NULL_PTR(dev_div)) goto error;
660
661 const int width = roi_out->width;
662 const int height = roi_out->height;
663
664 size_t sizes[] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
665 dt_opencl_set_kernel_arg(devid, kernel, 0, sizeof(cl_mem), (void *)&dev_in);
666 dt_opencl_set_kernel_arg(devid, kernel, 1, sizeof(cl_mem), (void *)&dev_out);
667 dt_opencl_set_kernel_arg(devid, kernel, 2, sizeof(int), (void *)&(width));
668 dt_opencl_set_kernel_arg(devid, kernel, 3, sizeof(int), (void *)&(height));
669 dt_opencl_set_kernel_arg(devid, kernel, 4, sizeof(int), (void *)&csx);
670 dt_opencl_set_kernel_arg(devid, kernel, 5, sizeof(int), (void *)&csy);
671 dt_opencl_set_kernel_arg(devid, kernel, 6, sizeof(cl_mem), (void *)&dev_sub);
672 dt_opencl_set_kernel_arg(devid, kernel, 7, sizeof(cl_mem), (void *)&dev_div);
673 dt_opencl_set_kernel_arg(devid, kernel, 8, sizeof(uint32_t), (void *)&roi_out->x);
674 dt_opencl_set_kernel_arg(devid, kernel, 9, sizeof(uint32_t), (void *)&roi_out->y);
675 if(gainmap_args)
676 {
677 const int map_size[2] = { d->gainmaps[0]->map_points_h, d->gainmaps[0]->map_points_v };
678 const float im_to_rel[2] = { 1.0 / piece->buf_in.width, 1.0 / piece->buf_in.height };
679 const float rel_to_map[2] = { 1.0 / d->gainmaps[0]->map_spacing_h, 1.0 / d->gainmaps[0]->map_spacing_v };
680 const float map_origin[2] = { d->gainmaps[0]->map_origin_h, d->gainmaps[0]->map_origin_v };
681
682 for(int i = 0; i < 4; i++)
683 {
684 dev_gainmap[i] = dt_opencl_alloc_device(devid, map_size[0], map_size[1], sizeof(float));
685 if(dev_gainmap[i] == NULL) goto error;
686 err = dt_opencl_write_host_to_device(devid, d->gainmaps[i]->map_gain, dev_gainmap[i],
687 map_size[0], map_size[1], sizeof(float));
688 if(err != CL_SUCCESS) goto error;
689 }
690
691 dt_opencl_set_kernel_arg(devid, kernel, 10, sizeof(cl_mem), &dev_gainmap[0]);
692 dt_opencl_set_kernel_arg(devid, kernel, 11, sizeof(cl_mem), &dev_gainmap[1]);
693 dt_opencl_set_kernel_arg(devid, kernel, 12, sizeof(cl_mem), &dev_gainmap[2]);
694 dt_opencl_set_kernel_arg(devid, kernel, 13, sizeof(cl_mem), &dev_gainmap[3]);
695 dt_opencl_set_kernel_arg(devid, kernel, 14, 2 * sizeof(int), &map_size);
696 dt_opencl_set_kernel_arg(devid, kernel, 15, 2 * sizeof(float), &im_to_rel);
697 dt_opencl_set_kernel_arg(devid, kernel, 16, 2 * sizeof(float), &rel_to_map);
698 dt_opencl_set_kernel_arg(devid, kernel, 17, 2 * sizeof(float), &map_origin);
699 }
700 err = dt_opencl_enqueue_kernel_2d(devid, kernel, sizes);
701 if(err != CL_SUCCESS) goto error;
702
705 for(int i = 0; i < 4; i++) dt_opencl_release_mem_object(dev_gainmap[i]);
706
707 return TRUE;
708
709error:
712 for(int i = 0; i < 4; i++) dt_opencl_release_mem_object(dev_gainmap[i]);
713 dt_print(DT_DEBUG_OPENCL, "[opencl_rawprepare] couldn't enqueue kernel! %d\n", err);
714 return FALSE;
715}
716#endif
717
718static int image_is_normalized(const dt_image_t *const image)
719{
720 // if raw with floating-point data, if not special magic whitelevel, then it needs normalization
721 if(dt_image_is_hdr(image))
722 {
723 union {
724 float f;
725 uint32_t u;
726 } normalized;
727 normalized.f = 1.0f;
728
729 // dng spec is just broken here.
730 return image->raw_white_point == normalized.u;
731 }
732
733 // else, assume normalized
734 return image->dsc.channels == 1 && image->dsc.datatype == TYPE_FLOAT;
735}
736
737static gboolean image_set_rawcrops(const int32_t imgid, int dx, int dy)
738{
739 if(imgid <= 0) return FALSE;
740
741 dt_image_t *img = NULL;
742 img = dt_image_cache_get(darktable.image_cache, imgid, 'r');
743 if(IS_NULL_PTR(img)) return FALSE;
744 const gboolean test = (img->p_width == img->width - dx)
745 && (img->p_height == img->height - dy);
746
748 if(test) return FALSE;
749
750 img = dt_image_cache_get(darktable.image_cache, imgid, 'w');
751 if(IS_NULL_PTR(img)) return FALSE;
752 img->p_width = img->width - dx;
753 img->p_height = img->height - dy;
755 return TRUE;
756}
757
758// check if image contains GainMaps of the exact type that we can apply here
759// we may reject some GainMaps that are valid according to Adobe DNG spec but we do not support
760gboolean check_gain_maps(dt_iop_module_t *self, dt_dng_gain_map_t **gainmaps_out)
761{
762 const dt_image_t *const image = &(self->dev->image_storage);
763 dt_dng_gain_map_t *gainmaps[4] = {0};
764
765 if(g_list_length(image->dng_gain_maps) != 4)
766 return FALSE;
767
768 for(int i = 0; i < 4; i++)
769 {
770 // check that each GainMap applies to one filter of a Bayer image,
771 // covers the entire image, and is not a 1x1 no-op
772 dt_dng_gain_map_t *g = (dt_dng_gain_map_t *)g_list_nth_data(image->dng_gain_maps, i);
773 if(IS_NULL_PTR(g) ||
774 g->plane != 0 || g->planes != 1 || g->map_planes != 1 ||
775 g->row_pitch != 2 || g->col_pitch != 2 ||
776 g->map_points_v < 2 || g->map_points_h < 2 ||
777 g->top > 1 || g->left > 1 ||
778 g->bottom != image->height || g->right != image->width)
779 return FALSE;
780 uint32_t filter = ((g->top & 1) << 1) + (g->left & 1);
781 gainmaps[filter] = g;
782 }
783
784 // check that there is a GainMap for each filter of the Bayer pattern
785 if(gainmaps[0] == NULL || gainmaps[1] == NULL || gainmaps[2] == NULL || gainmaps[3] == NULL)
786 return FALSE;
787
788 // check that each GainMap has the same shape
789 for(int i = 1; i < 4; i++)
790 {
791 if(gainmaps[i]->map_points_h != gainmaps[0]->map_points_h ||
792 gainmaps[i]->map_points_v != gainmaps[0]->map_points_v ||
793 gainmaps[i]->map_spacing_h != gainmaps[0]->map_spacing_h ||
794 gainmaps[i]->map_spacing_v != gainmaps[0]->map_spacing_v ||
795 gainmaps[i]->map_origin_h != gainmaps[0]->map_origin_h ||
796 gainmaps[i]->map_origin_v != gainmaps[0]->map_origin_v)
797 return FALSE;
798 }
799
800 if(gainmaps_out)
801 memcpy(gainmaps_out, gainmaps, sizeof(gainmaps));
802
803 return TRUE;
804}
805
806// Free the pipe-owned deep copies of the GainMaps held in piece->data (see commit_params).
808{
809 for(int i = 0; i < 4; i++)
810 {
811 g_free(d->gainmaps[i]);
812 d->gainmaps[i] = NULL;
813 }
814}
815
816// Build pipe-owned deep copies of the image's GainMaps into d->gainmaps[]. The pointers from
817// check_gain_maps() borrow image_storage.dng_gain_maps, which is a shallow copy of cache-owned
818// memory with the cache lock already dropped (see _dt_dev_refresh_image_storage): it can be
819// freed/rebuilt (e.g. eviction under thumbnail-generation pressure) before process() reads it
820// -> use-after-free (Sentry #129880848). Owning a private copy decouples us from the cache.
821// Caller must have freed/NULLed d->gainmaps[] first. Returns TRUE only if all four were copied.
823{
824 dt_dng_gain_map_t *src[4] = { 0 };
825 if(!check_gain_maps(self, src))
826 return FALSE;
827
828 for(int i = 0; i < 4; i++)
829 {
830 // map_planes == 1 is enforced by check_gain_maps(), so the gain payload is
831 // map_points_h * map_points_v floats -- exactly what process() indexes.
832 const size_t sz = sizeof(dt_dng_gain_map_t)
833 + (size_t)src[i]->map_points_h * src[i]->map_points_v * sizeof(float);
834 d->gainmaps[i] = g_malloc(sz);
835 if(IS_NULL_PTR(d->gainmaps[i]))
836 {
837 _free_owned_gainmaps(d); // partial copy (OOM): drop everything, don't apply
838 return FALSE;
839 }
840 memcpy(d->gainmaps[i], src[i], sz);
841 }
842 return TRUE;
843}
844
847{
850 const dt_image_t *const img = &pipe->dev->image_storage;
851
852 d->x = p->x;
853 d->y = p->y;
854 d->width = p->width;
855 d->height = p->height;
856
857 if(img->dsc.filters)
858 {
859 const float white = (float)p->raw_white_point;
860
861 for(int i = 0; i < 4; i++)
862 {
863 d->sub[i] = (float)p->raw_black_level_separate[i];
864 d->div[i] = (white - d->sub[i]);
865 }
866 }
867 else
868 {
869 const float normalizer
870 = dt_image_is_hdr(&pipe->dev->image_storage) ? 1.0f : (float)UINT16_MAX;
871 const float white = (float)p->raw_white_point / normalizer;
872 float black = 0;
873 for(int i = 0; i < 4; i++)
874 {
875 black += p->raw_black_level_separate[i] / normalizer;
876 }
877 black /= 4.0f;
878
879 for(int i = 0; i < 4; i++)
880 {
881 d->sub[i] = black;
882 d->div[i] = (white - black);
883 }
884 }
885
886 float black = 0.0f;
887 for(uint8_t i = 0; i < 4; i++)
888 {
889 black += (float)p->raw_black_level_separate[i];
890 }
891 d->rawprepare.raw_black_level = (uint16_t)(black / 4.0f);
892 d->rawprepare.raw_white_point = p->raw_white_point;
893 piece->dsc_out.rawprepare.raw_black_level = d->rawprepare.raw_black_level;
894 piece->dsc_out.rawprepare.raw_white_point = d->rawprepare.raw_white_point;
895 for(int k = 0; k < 4; k++) piece->dsc_out.processed_maximum[k] = 1.0f;
896
897 // Refresh our private, pipe-owned copy of the GainMaps (see _own_gainmaps() for why we must own
898 // them rather than borrow image_storage.dng_gain_maps). Free the previous copy in all cases.
900 d->apply_gainmaps = (p->flat_field == FLAT_FIELD_EMBEDDED) && _own_gainmaps(self, d);
901
902 if(image_set_rawcrops(pipe->dev->image_storage.id, d->x + d->width, d->y + d->height))
904
905 // Image-type gating (needs_rawprepare && !normalized) is handled at history level by
906 // enable()/force_enable()/reload_defaults(); it is no longer duplicated here.
907
908 // OpenCL path only for RAW, single-channel, CFA images (runtime/format decision).
909 const gboolean cl_ok = (img->dsc.cst == IOP_CS_RAW && img->dsc.channels == 1 && img->dsc.filters);
910 if(!cl_ok) piece->process_cl_ready = FALSE;
911
912 dt_iop_fmt_log(self, "commit: class=%s needs_rawprepare=%d normalized=%d cl_ok=%d -> enabled=%d",
914 dt_image_needs_rawprepare(img), image_is_normalized(img), cl_ok, piece->enabled);
915}
916
922
930
931
932static gboolean enable(const dt_image_t *image)
933{
934 // rawprepare (black/white normalization) applies to any raw colorimetry: mosaiced raw and
935 // already-demosaiced sRAW / linear DNG alike, unless the buffer is already normalized.
936 return dt_image_needs_rawprepare(image)
937 && !image_is_normalized(image);
938}
939
940gboolean force_enable(struct dt_iop_module_t *self, const gboolean current_state)
941{
942 // History sanitization: rawprepare must be off for non-raw or already-normalized buffers,
943 // decided here from image metadata using the same enable() rule as reload_defaults().
944 const gboolean active = enable(&self->dev->image_storage);
945 const gboolean state = active && current_state;
946 dt_iop_fmt_log(self, "force_enable: class=%s supported=%d current=%d -> %d",
948 active, current_state, state);
949 return state;
950}
951
953{
955 const dt_image_t *const image = &(self->dev->image_storage);
956
957 // if there are embedded GainMaps, they should be applied by default to avoid uneven color cast
958 gboolean has_gainmaps = check_gain_maps(self, NULL);
959
960 *d = (dt_iop_rawprepare_params_t){.x = image->crop_x,
961 .y = image->crop_y,
962 .width = image->crop_width,
963 .height = image->crop_height,
964 .raw_black_level_separate[0] = image->raw_black_level_separate[0],
965 .raw_black_level_separate[1] = image->raw_black_level_separate[1],
966 .raw_black_level_separate[2] = image->raw_black_level_separate[2],
967 .raw_black_level_separate[3] = image->raw_black_level_separate[3],
968 .raw_white_point = image->raw_white_point,
969 .flat_field = has_gainmaps ? FLAT_FIELD_EMBEDDED : FLAT_FIELD_OFF };
970
971 self->hide_enable_button = 1;
972 self->default_enabled = enable(image);
973
974 dt_image_print_debug_info(image, "rawprepare.reload_defaults");
975 // Stack visibility (raw vs non_raw) is applied from default_enabled in gui_update(), on the GUI
976 // thread when the widget exists; reload_defaults() stays params-only.
977}
978
980{
981 const int program = 2; // basic.cl, from programs.conf
982 self->data = malloc(sizeof(dt_iop_rawprepare_global_data_t));
983
985 gd->kernel_rawprepare_1f = dt_opencl_create_kernel(program, "rawprepare_1f");
986 gd->kernel_rawprepare_1f_gainmap = dt_opencl_create_kernel(program, "rawprepare_1f_gainmap");
987 gd->kernel_rawprepare_1f_unnormalized = dt_opencl_create_kernel(program, "rawprepare_1f_unnormalized");
988 gd->kernel_rawprepare_1f_unnormalized_gainmap = dt_opencl_create_kernel(program, "rawprepare_1f_unnormalized_gainmap");
989 gd->kernel_rawprepare_4f = dt_opencl_create_kernel(program, "rawprepare_4f");
990}
991
1000
1002{
1005
1006 const gboolean is_monochrome = (self->dev->image_storage.flags & (DT_IMAGE_MONOCHROME | DT_IMAGE_MONOCHROME_BAYER)) != 0;
1007 if(is_monochrome)
1008 {
1009 // we might have to deal with old edits, so get average first
1010 int av = 2; // for rounding
1011 for(int i = 0; i < 4; i++)
1012 av += p->raw_black_level_separate[i];
1013
1014 for(int i = 0; i < 4; i++)
1015 dt_bauhaus_slider_set(g->black_level_separate[i], av / 4);
1016 }
1017
1018 // don't show upper three black levels for monochromes
1019 for(int i = 1; i < 4; i++)
1020 gtk_widget_set_visible(g->black_level_separate[i], !is_monochrome);
1021
1022 gtk_widget_set_visible(g->flat_field, check_gain_maps(self, NULL));
1023 dt_bauhaus_combobox_set(g->flat_field, p->flat_field);
1024
1025 // raw vs non_raw page, from the per-image default computed by reload_defaults()
1026 gtk_stack_set_visible_child_name(GTK_STACK(self->widget), self->default_enabled ? "raw" : "non_raw");
1027}
1028
1029void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
1030{
1033
1034 const gboolean is_monochrome = (self->dev->image_storage.flags & (DT_IMAGE_MONOCHROME | DT_IMAGE_MONOCHROME_BAYER)) != 0;
1035 if(is_monochrome)
1036 {
1037 if(w == g->black_level_separate[0])
1038 {
1039 const int val = p->raw_black_level_separate[0];
1040 for(int i = 1; i < 4; i++)
1041 dt_bauhaus_slider_set(g->black_level_separate[i], val);
1042 }
1043 }
1044}
1045
1046const gchar *black_label[]
1047 = { N_("black level 0"),
1048 N_("black level 1"),
1049 N_("black level 2"),
1050 N_("black level 3") };
1051
1053{
1055
1056 GtkWidget *box_raw = self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
1057
1058 for(int i = 0; i < 4; i++)
1059 {
1060 gchar *par = g_strdup_printf("raw_black_level_separate[%i]", i);
1061
1062 g->black_level_separate[i] = dt_bauhaus_slider_from_params(self, par);
1063 dt_bauhaus_widget_set_label(g->black_level_separate[i], black_label[i]);
1064 gtk_widget_set_tooltip_text(g->black_level_separate[i], _(black_label[i]));
1065 dt_bauhaus_slider_set_soft_max(g->black_level_separate[i], 16384);
1066
1067 dt_free(par);
1068 }
1069
1070 g->white_point = dt_bauhaus_slider_from_params(self, "raw_white_point");
1071 gtk_widget_set_tooltip_text(g->white_point, _("white point"));
1072 dt_bauhaus_slider_set_soft_max(g->white_point, 16384);
1073
1074 g->flat_field = dt_bauhaus_combobox_from_params(self, "flat_field");
1075 gtk_widget_set_tooltip_text(g->flat_field, _("flat field correction to compensate for lens shading"));
1076
1077 gtk_box_pack_start(GTK_BOX(self->widget),
1078 dt_ui_section_label_new(_("In-camera crop")), FALSE, FALSE, 0);
1079
1080 g->x = dt_bauhaus_slider_from_params(self, "x");
1081 gtk_widget_set_tooltip_text(g->x, _("crop from left border"));
1083
1084 g->y = dt_bauhaus_slider_from_params(self, "y");
1085 gtk_widget_set_tooltip_text(g->y, _("crop from top"));
1087
1088 g->width = dt_bauhaus_slider_from_params(self, "width");
1089 gtk_widget_set_tooltip_text(g->width, _("crop from right border"));
1090 dt_bauhaus_slider_set_soft_max(g->width, 256);
1091
1092 g->height = dt_bauhaus_slider_from_params(self, "height");
1093 gtk_widget_set_tooltip_text(g->height, _("crop from bottom"));
1094 dt_bauhaus_slider_set_soft_max(g->height, 256);
1095
1096 // start building top level widget
1097 self->widget = gtk_stack_new();
1098 gtk_stack_set_homogeneous(GTK_STACK(self->widget), FALSE);
1099
1100 GtkWidget *label_non_raw = dt_ui_label_new(_("raw black/white point correction\nonly works for the sensors that need it."));
1101
1102 gtk_stack_add_named(GTK_STACK(self->widget), label_non_raw, "non_raw");
1103 gtk_stack_add_named(GTK_STACK(self->widget), box_raw, "raw");
1104}
1105
1106// clang-format off
1107// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1108// vim: shiftwidth=2 expandtab tabstop=2 cindent
1109// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1110// 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_soft_max(GtkWidget *widget, float val)
Definition bauhaus.c:1626
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
Definition bauhaus.c:3537
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
Definition bauhaus.c:2304
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
Definition bauhaus.c:1656
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
@ DEVELOP_BLEND_CS_NONE
Definition blend.h:56
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
@ IOP_CS_RAW
@ IOP_CS_RGB
const dt_aligned_pixel_t f
const float max
const dt_colormatrix_t dt_aligned_pixel_t out
static const int row
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
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_hdr(const dt_image_t *img)
void dt_image_print_debug_info(const dt_image_t *img, const char *context)
gboolean dt_image_needs_rawprepare(const dt_image_t *img)
darktable_t darktable
Definition darktable.c:183
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1600
#define dt_free_align(ptr)
Definition darktable.h:503
static void * dt_calloc_align(size_t size)
Definition darktable.h:510
@ DT_DEBUG_OPENCL
Definition darktable.h:744
@ DT_DEBUG_DEMOSAIC
Definition darktable.h:759
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Enable aggressive floating-point arithmetic optimizations, in denormals handling. Set through user pr...
Definition darktable.h:546
#define dt_free(ptr)
Definition darktable.h:478
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
Definition darktable.h:151
#define __DT_CLONE_TARGETS__
Definition darktable.h:379
#define __OMP_PARALLEL_FOR__(...)
Definition darktable.h:270
static const dt_aligned_pixel_simd_t value
Definition darktable.h:599
#define __OMP_PARALLEL_FOR_SIMD__(...)
Definition darktable.h:271
#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 darktable.h:293
#define dt_database_start_transaction(db)
Definition database.h:77
#define dt_database_release_transaction(db)
Definition database.h:78
void dt_iop_params_t
Definition dev_history.h:42
void default_output_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
Definition format.c:75
@ TYPE_FLOAT
Definition format.h:46
@ TYPE_UINT16
Definition format.h:47
static GtkWidget * dt_ui_section_label_new(const gchar *str)
Definition gtk.h:469
#define DT_GUI_BOX_SPACING
Definition gtk.h:109
static GtkWidget * dt_ui_label_new(const gchar *str)
Definition gtk.h:479
void dt_gui_presets_add_generic(const char *name, dt_dev_operation_t op, const int32_t version, const void *params, const int32_t params_size, const int32_t enabled, const dt_develop_blend_colorspace_t blend_cst)
@ DT_IMAGE_MONOCHROME_BAYER
Definition image.h:138
@ DT_IMAGE_MONOCHROME
Definition image.h:129
void dt_image_cache_read_release(dt_image_cache_t *cache, const dt_image_t *img)
dt_image_t * dt_image_cache_get(dt_image_cache_t *cache, const int32_t imgid, char mode)
void dt_image_cache_write_release(dt_image_cache_t *cache, dt_image_t *img, dt_image_cache_write_mode_t mode)
@ DT_IMAGE_CACHE_RELAXED
Definition image_cache.h:51
void dt_iop_copy_image_roi(float *const __restrict__ out, const float *const __restrict__ in, const size_t ch, const dt_iop_roi_t *const __restrict__ roi_in, const dt_iop_roi_t *const __restrict__ roi_out, const int zero_pad)
Definition imagebuf.c:159
uint32_t dt_rawspeed_crop_dcraw_filters(uint32_t filters, uint32_t crop_x, uint32_t crop_y)
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:3220
#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:490
@ IOP_FLAGS_ALLOW_TILING
Definition imageop.h:199
@ IOP_FLAGS_UNSAFE_COPY
Definition imageop.h:207
@ IOP_FLAGS_ONE_INSTANCE
Definition imageop.h:202
@ IOP_FLAGS_TILING_FULL_ROI
Definition imageop.h:201
@ IOP_GROUP_TECHNICAL
Definition imageop.h:173
#define IOP_GUI_ALLOC(module)
Definition imageop.h:638
@ IOP_TAG_DISTORT
Definition imageop.h:181
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
Definition imageop_gui.c:77
GtkWidget * dt_bauhaus_combobox_from_params(dt_iop_module_t *self, const char *param)
void *const ovoid
static float kernel(const float *x, const float *y)
static const float x
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
Definition opencl.c:2164
void * dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
Definition opencl.c:2504
int dt_opencl_create_kernel(const int prog, const char *name)
Definition opencl.c:2058
void * dt_opencl_copy_host_to_device_constant(const int devid, const size_t size, void *host)
Definition opencl.c:2360
void dt_opencl_free_kernel(const int kernel)
Definition opencl.c:2101
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:2155
void dt_opencl_release_mem_object(cl_mem mem)
Definition opencl.c:2415
int dt_opencl_write_host_to_device(const int devid, void *host, void *device, const int width, const int height, const int bpp)
Definition opencl.c:2244
#define ROUNDUPDHT(a, b)
Definition opencl.h:82
#define ROUNDUPDWD(a, b)
Definition opencl.h:81
@ DT_DEV_PIXELPIPE_THUMBNAIL
Definition pixelpipe.h:41
@ DT_DEV_PIXELPIPE_EXPORT
Definition pixelpipe.h:38
@ DT_DEV_PIXELPIPE_PREVIEW
Definition pixelpipe.h:40
@ DT_DEV_PIXELPIPE_FULL
Definition pixelpipe.h:39
int operation_tags()
Definition rawprepare.c:121
void distort_mask(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, const float *const in, float *const out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
Definition rawprepare.c:313
const char ** description(struct dt_iop_module_t *self)
Definition rawprepare.c:170
void modify_roi_out(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t *roi_out, const dt_iop_roi_t *const roi_in)
Definition rawprepare.c:325
int default_group()
Definition rawprepare.c:132
int distort_backtransform(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, float *const restrict points, size_t points_count)
Definition rawprepare.c:289
__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 rawprepare.c:434
int distort_transform(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, float *const restrict points, size_t points_count)
Definition rawprepare.c:265
void gui_update(dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
static void _free_owned_gainmaps(dt_iop_rawprepare_data_t *d)
Definition rawprepare.c:807
dt_iop_rawprepare_flat_field_t
Definition rawprepare.c:63
@ FLAT_FIELD_OFF
Definition rawprepare.c:64
@ FLAT_FIELD_EMBEDDED
Definition rawprepare.c:65
void modify_roi_in(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *const roi_out, dt_iop_roi_t *roi_in)
Definition rawprepare.c:347
static gboolean enable(const dt_image_t *image)
Definition rawprepare.c:932
int process_cl(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 rawprepare.c:603
const char * name()
Definition rawprepare.c:116
void output_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
Definition rawprepare.c:365
void cleanup_global(dt_iop_module_so_t *self)
Definition rawprepare.c:992
void gui_init(dt_iop_module_t *self)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
void reload_defaults(dt_iop_module_t *self)
Definition rawprepare.c:952
void cleanup_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition rawprepare.c:923
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition rawprepare.c:137
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 rawprepare.c:373
int flags()
Definition rawprepare.c:126
void autoset(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, const void *input)
RawSpeed tends to under-evaluate the white point of RAW images, which leads to RGB values > 1 after n...
Definition rawprepare.c:399
void init_presets(dt_iop_module_so_t *self)
Definition rawprepare.c:180
gboolean check_gain_maps(dt_iop_module_t *self, dt_dng_gain_map_t **gainmaps_out)
Definition rawprepare.c:760
void commit_params(dt_iop_module_t *self, dt_iop_params_t *params, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition rawprepare.c:845
static gboolean _own_gainmaps(dt_iop_module_t *self, dt_iop_rawprepare_data_t *d)
Definition rawprepare.c:822
gboolean force_enable(struct dt_iop_module_t *self, const gboolean current_state)
Definition rawprepare.c:940
void init_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition rawprepare.c:917
static void _update_output_cfa_descriptor(const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *const roi_in, dt_iop_buffer_dsc_t *dsc)
Definition rawprepare.c:205
static gboolean image_set_rawcrops(const int32_t imgid, int dx, int dy)
Definition rawprepare.c:737
static int image_is_normalized(const dt_image_t *const image)
Definition rawprepare.c:718
const gchar * black_label[]
void init_global(dt_iop_module_so_t *self)
Definition rawprepare.c:979
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 rawprepare.c:144
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
Definition signal.h:366
@ DT_SIGNAL_METADATA_UPDATE
Definition signal.h:305
struct _GtkWidget GtkWidget
Definition splash.h:29
const float uint32_t state[4]
const struct dt_database_t * db
Definition darktable.h:807
struct dt_control_signal_t * signals
Definition darktable.h:802
struct dt_image_cache_t * image_cache
Definition darktable.h:805
dt_iop_buffer_dsc_t dsc_out
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_dev_pixelpipe_type_t type
struct dt_develop_t * dev
dt_image_t image_storage
Definition develop.h:259
uint32_t map_points_v
Definition dng_opcode.h:54
uint32_t map_points_h
Definition dng_opcode.h:55
int32_t height
Definition image.h:315
GList * dng_gain_maps
Definition image.h:368
uint32_t raw_white_point
Definition image.h:352
int32_t crop_height
Definition image.h:316
int32_t flags
Definition image.h:319
int32_t width
Definition image.h:315
int32_t crop_y
Definition image.h:316
int32_t crop_x
Definition image.h:316
int32_t p_height
Definition image.h:315
dt_iop_buffer_dsc_t dsc
Definition image.h:337
int32_t p_width
Definition image.h:315
int32_t crop_width
Definition image.h:316
int32_t id
Definition image.h:319
uint16_t raw_black_level_separate[4]
Definition image.h:351
uint32_t filters
Definition format.h:60
uint16_t raw_black_level
Definition format.h:74
unsigned int channels
Definition format.h:54
uint8_t xtrans[6][6]
Definition format.h:70
struct dt_iop_buffer_dsc_t::@32 rawprepare
dt_iop_buffer_type_t datatype
Definition format.h:56
dt_aligned_pixel_t processed_maximum
Definition format.h:85
uint16_t raw_white_point
Definition format.h:75
GModule *dt_dev_operation_t op
Definition imageop.h:260
dt_iop_global_data_t * data
Definition imageop.h:263
int32_t hide_enable_button
Definition imageop.h:292
dt_iop_params_t * default_params
Definition imageop.h:344
GtkWidget * widget
Definition imageop.h:374
struct dt_develop_t * dev
Definition imageop.h:333
dt_iop_gui_data_t * gui_data
Definition imageop.h:348
gboolean default_enabled
Definition imageop.h:340
dt_iop_global_data_t * global_data
Definition imageop.h:351
dt_iop_params_t * params
Definition imageop.h:344
dt_dng_gain_map_t * gainmaps[4]
Definition rawprepare.c:103
struct dt_iop_rawprepare_data_t::@61 rawprepare
GtkWidget * black_level_separate[4]
Definition rawprepare.c:81
uint16_t raw_black_level_separate[4]
Definition rawprepare.c:74
dt_iop_rawprepare_flat_field_t flat_field
Definition rawprepare.c:76
Region of interest passed through the pixelpipe.
Definition imageop.h:72
double scale
Definition imageop.h:74
typedef double((*spd)(unsigned long int wavelength, double TempK))
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29