Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
gamma.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2012 johannes hanika.
4 Copyright (C) 2010-2011 Bruce Guenter.
5 Copyright (C) 2010-2011 Henrik Andersson.
6 Copyright (C) 2010 José Carlos García Sogo.
7 Copyright (C) 2010 Pascal de Bruijn.
8 Copyright (C) 2011 Robert Bieber.
9 Copyright (C) 2012 Richard Wonka.
10 Copyright (C) 2012, 2014, 2017 Ulrich Pegelow.
11 Copyright (C) 2013, 2020 Aldric Renaudin.
12 Copyright (C) 2013-2014, 2016-2017, 2019 Tobias Ellinghaus.
13 Copyright (C) 2014-2016 Roman Lebedev.
14 Copyright (C) 2015 Pedro Côrte-Real.
15 Copyright (C) 2018, 2020, 2023, 2025-2026 Aurélien PIERRE.
16 Copyright (C) 2018-2019 Edgardo Hoszowski.
17 Copyright (C) 2019 Andreas Schneider.
18 Copyright (C) 2020 Diederik Ter Rahe.
19 Copyright (C) 2020 Harold le Clément de Saint-Marcq.
20 Copyright (C) 2020-2021 Pascal Obry.
21 Copyright (C) 2021 Ralf Brown.
22 Copyright (C) 2022 Martin Bařinka.
23 Copyright (C) 2022 Philipp Lutz.
24
25 darktable is free software: you can redistribute it and/or modify
26 it under the terms of the GNU General Public License as published by
27 the Free Software Foundation, either version 3 of the License, or
28 (at your option) any later version.
29
30 darktable is distributed in the hope that it will be useful,
31 but WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 GNU General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with darktable. If not, see <http://www.gnu.org/licenses/>.
37*/
38#ifdef HAVE_CONFIG_H
39#include "system/mem_alloc.h"
40#include "common/conf.h"
42#include "common/logging.h"
43#include "system/openmp.h"
44#include "system/simd.h"
46#include "config.h"
47#endif
48#include "develop/imageop_gui.h"
49#include <assert.h>
50#include <math.h>
51#include <stdlib.h>
52#include <string.h>
53
55#include "common/opencl.h"
56#include "develop/develop.h"
57
58#include "iop/iop_api.h"
60
69
70
75
76#ifdef HAVE_OPENCL
81
89
103#endif
104
105const char *name()
106{
107 return C_("modulename", "display encoding");
108}
109
111{
112 return IOP_GROUP_TECHNICAL;
113}
114
119
124
132
135{
136 dsc->channels = 4;
137 dsc->datatype = TYPE_UINT8;
138 dsc->cst = self->default_colorspace(self, pipe, piece);
139}
140
141
157
186
191static inline void _write_pixel(const float *const restrict in, uint8_t *const restrict out,
193 const size_t pixel_index, const float alpha)
194{
195 // Blend the image with the checker in linear RGB, then encode the result once.
196 const size_t y = pixel_index / preview->width;
197 const size_t x = pixel_index - y * preview->width;
198 const gboolean first_x = x % preview->checker_1 < x % preview->checker_2;
199 const gboolean first_y = y % preview->checker_1 < y % preview->checker_2;
200 const float *const checker_color
201 = first_x == first_y ? preview->checker_color_2 : preview->checker_color_1;
202 dt_aligned_pixel_t pixel;
203 for(size_t c = 0; c < 3; c++)
204 {
205 const float value = in[c] * (1.0f - alpha) + checker_color[c] * alpha;
206 pixel[c] = value <= 0.0031308f ? 12.92f * value
207 : (1.0f + 0.055f) * powf(value, 1.0f / 2.4f) - 0.055f;
208 }
209
210 // the output of this module is BGR(A) instead of RGBA; can't use for_each_channel here due to the index swap
211 for(size_t c = 0; c < 3; c++)
212 {
213 const float value = roundf(255.0f * pixel[c]);
214 out[2 - c] = (uint8_t)(fminf(fmaxf(value, 0.0f), 255.0f));
215 }
216}
217__OMP_DECLARE_SIMD__(aligned(pixel: 16) uniform(norm))
218static inline __attribute__((always_inline)) void _normalize_color(float *const restrict pixel, const float norm)
219{
220 // color may not be black!
221 const float factor = norm / fmaxf(pixel[0], fmaxf(pixel[1], pixel[2]));
223 pixel[x] *= factor;
224}
225
226__OMP_DECLARE_SIMD__(aligned(XYZ, sRGB: 16) uniform(norm))
227static inline void _XYZ_to_REC_709_normalized(const float *const restrict XYZ, float *const restrict sRGB,
228 const float norm)
229{
231 _normalize_color(sRGB, norm);
232}
234static void _channel_display_monochrome(const float *const restrict in, uint8_t *const restrict out,
235 const size_t buffsize, const float alpha,
237{
238 // Render each selected channel value as a neutral image over the shared mask checkerboard.
239 __OMP_PARALLEL_FOR_SIMD__(aligned(in, out: 64))
240 for(size_t j = 0; j < buffsize; j += 4)
241 {
242 dt_aligned_pixel_t pixel = { in[j + 1], in[j + 1], in[j + 1], in[j + 1] };
243 _write_pixel(pixel, out + j, preview, j / 4, in[j + 3] * alpha);
244 }
245}
247static void _channel_display_false_color(const float *const restrict in, uint8_t *const restrict out,
248 const size_t buffsize, const float alpha,
251{
253 {
255 __OMP_PARALLEL_FOR_SIMD__(aligned(in, out: 64))
256 for(size_t j = 0; j < buffsize; j += 4)
257 {
259 dt_aligned_pixel_t pixel;
260 // colors with "a" exceeding the range [-56,56] range will yield colors not representable in sRGB
261 const float value = fminf(fmaxf(in[j + 1] * 256.0f - 128.0f, -56.0f), 56.0f);
262 const dt_aligned_pixel_t lab = { 79.0f - value * (11.0f / 56.0f), value, 0.0f, 0.0f };
263 dt_Lab_to_XYZ(lab, xyz);
264 _XYZ_to_REC_709_normalized(xyz, pixel, 0.75f);
265 _write_pixel(pixel, out + j, preview, j / 4, in[j + 3] * alpha);
266 }
267 break;
269 __OMP_PARALLEL_FOR_SIMD__(aligned(in, out: 64))
270 for(size_t j = 0; j < buffsize; j += 4)
271 {
272 dt_aligned_pixel_t xyz, pixel;
273 // colors with "b" exceeding the range [-65,65] range will yield colors not representable in sRGB
274 const float value = fminf(fmaxf(in[j + 1] * 256.0f - 128.0f, -65.0f), 65.0f);
275 const dt_aligned_pixel_t lab = { 60.0f + value * (2.0f / 65.0f), 0.0f, value, 0.0f };
276 dt_Lab_to_XYZ(lab, xyz);
277 _XYZ_to_REC_709_normalized(xyz, pixel, 0.75f);
278 _write_pixel(pixel, out + j, preview, j / 4, in[j + 3] * alpha);
279 }
280 break;
282 __OMP_PARALLEL_FOR_SIMD__(aligned(in, out: 64))
283 for(size_t j = 0; j < buffsize; j += 4)
284 {
285 const dt_aligned_pixel_t pixel = { in[j + 1], 0.0f, 0.0f, 0.0f };
286 _write_pixel(pixel, out + j, preview, j / 4, in[j + 3] * alpha);
287 }
288 break;
290 __OMP_PARALLEL_FOR_SIMD__(aligned(in, out: 64))
291 for(size_t j = 0; j < buffsize; j += 4)
292 {
293 const dt_aligned_pixel_t pixel = { 0.0f, in[j + 1], 0.0f, 0.0f };
294 _write_pixel(pixel, out + j, preview, j / 4, in[j + 3] * alpha);
295 }
296 break;
298 __OMP_PARALLEL_FOR_SIMD__(aligned(in, out: 64))
299 for(size_t j = 0; j < buffsize; j += 4)
300 {
301 const dt_aligned_pixel_t pixel = { 0.0f, 0.0f, in[j + 1], 0.0f };
302 _write_pixel(pixel, out + j, preview, j / 4, in[j + 3] * alpha);
303 }
304 break;
308 __OMP_PARALLEL_FOR_SIMD__(aligned(in, out: 64))
309 for(size_t j = 0; j < buffsize; j += 4)
310 {
311 const dt_aligned_pixel_t pixel = { 0.5f, 0.5f * (1.0f - in[j + 1]), 0.5f, 0.0f };
312 _write_pixel(pixel, out + j, preview, j / 4, in[j + 3] * alpha);
313 }
314 break;
316 __OMP_PARALLEL_FOR_SIMD__(aligned(in, out: 64))
317 for(size_t j = 0; j < buffsize; j += 4)
318 {
319 dt_aligned_pixel_t lch = { 65.0f, 37.0f, in[j + 1], 0.0f };
320 dt_aligned_pixel_t lab, xyz, pixel;
321 dt_LCH_2_Lab(lch, lab);
322 lab[3] = 0.0f;
323 dt_Lab_to_XYZ(lab, xyz);
324 _XYZ_to_REC_709_normalized(xyz, pixel, 0.75f);
325 _write_pixel(pixel, out + j, preview, j / 4, in[j + 3] * alpha);
326 }
327 break;
330 for(size_t j = 0; j < buffsize; j += 4)
331 {
332 dt_aligned_pixel_t hsl = { in[j + 1], 0.5f, 0.5f, 0.0f };
333 dt_aligned_pixel_t pixel;
334 dt_HSL_2_RGB(hsl, pixel);
335 _normalize_color(pixel, 0.75f);
336 _write_pixel(pixel, out + j, preview, j / 4, in[j + 3] * alpha);
337 }
338 break;
341 for(size_t j = 0; j < buffsize; j += 4)
342 {
343 const dt_aligned_pixel_t JzCzhz = { 0.011f, 0.01f, in[j + 1] };
346 dt_aligned_pixel_t pixel;
347 dt_JzCzhz_2_JzAzBz(JzCzhz, JzAzBz);
348 dt_JzAzBz_2_XYZ(JzAzBz, XYZ_D65);
349 dt_XYZ_to_Rec709_D65(XYZ_D65, pixel);
350 _normalize_color(pixel, 0.75f);
351 _write_pixel(pixel, out + j, preview, j / 4, in[j + 3] * alpha);
352 }
353 break;
358 default:
359 _channel_display_monochrome(in, out, buffsize, alpha, preview);
360 break;
361 }
362}
364static void _mask_display(const float *const restrict in, uint8_t *const restrict out, const size_t buffsize,
365 const float alpha, const dt_iop_gamma_mask_preview_t *const preview)
366{
367 // Loop over the displayed mask and preserve the image colors unless the global monochrome option is enabled.
368 __OMP_PARALLEL_FOR_SIMD__(aligned(in, out: 64))
369 for(size_t j = 0; j < buffsize; j += 4)
370 {
371 dt_aligned_pixel_t pixel = { in[j], in[j + 1], in[j + 2], 0.0f };
372 if(preview->black_and_white)
373 {
374 const float gray = 0.3f * in[j + 0] + 0.59f * in[j + 1] + 0.11f * in[j + 2];
375 pixel[0] = pixel[1] = pixel[2] = gray;
376 }
377 const float hide = 1.0f - fminf(fmaxf(in[j + 3] * alpha, 0.0f), 1.0f);
378 _write_pixel(pixel, out + j, preview, j / 4, hide);
379 }
380}
382static void _copy_output(const float *const restrict in, uint8_t *const restrict out, const size_t buffsize)
383{
384 __OMP_PARALLEL_FOR_SIMD__(aligned(in, out: 64))
385 for(size_t j = 0; j < buffsize; j += 4)
386 {
387 // the output of this module is BGR(A) instead of RGBA, so we can't use for_each_channel
388 for(size_t c = 0; c < 3; c++)
389 {
390 out[j + 2 - c] = (uint8_t)(fminf(roundf(255.0f * fmaxf(in[j + c], 0.0f)), 255.0f));
391 }
392 }
393}
394
395
396int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const i, void *const o)
397{
398 const dt_iop_roi_t *const roi_out = &piece->roi_out;
400 const size_t buffsize = (size_t)roi_out->width * roi_out->height * 4;
401
403 {
404 _copy_output((const float *const restrict)i, (uint8_t *const restrict)o, buffsize);
405 return 0;
406 }
407
408 /* Settled in commit_params(); nothing here reads conf. A node whose allocation failed is
409 * normally disabled by dt_iop_commit_params(), but this one is the last of the pipe and a
410 * disabled display encoding is a black window -- so fall back to the plain copy, which is
411 * what an ordinary frame does anyway, and lose only the preview. */
412 const dt_iop_gamma_data_t *const d = (const dt_iop_gamma_data_t *)piece->data;
413 if(IS_NULL_PTR(d))
414 {
415 _copy_output((const float *const restrict)i, (uint8_t *const restrict)o, buffsize);
416 return 0;
417 }
418
419 const float alpha = (mask_display & DT_DEV_PIXELPIPE_DISPLAY_MASK) ? 1.0f : 0.0f;
421 preview.width = roi_out->width;
422
423 if((mask_display & DT_DEV_PIXELPIPE_DISPLAY_CHANNEL) && (mask_display & DT_DEV_PIXELPIPE_DISPLAY_ANY))
424 {
425 if(d->false_color)
426 {
427 _channel_display_false_color((const float *const restrict)i, (uint8_t *const restrict)o, buffsize, alpha,
428 mask_display, &preview);
429 }
430 else
431 {
432 _channel_display_monochrome((const float *const restrict)i, (uint8_t *const restrict)o, buffsize, alpha,
433 &preview);
434 }
435 return 0;
436 }
437
438 if(mask_display & DT_DEV_PIXELPIPE_DISPLAY_MASK)
439 {
440 _mask_display((const float *const restrict)i, (uint8_t *const restrict)o, buffsize, 1.0f, &preview);
441 return 0;
442 }
443
444 _copy_output((const float *const restrict)i, (uint8_t *const restrict)o, buffsize);
445 return 0;
446}
447
448#ifdef HAVE_OPENCL
481
482int 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)
483{
484 const dt_iop_roi_t *const roi_out = &piece->roi_out;
486 const int devid = pipe->devid;
487 cl_int err = CL_SUCCESS;
488
489 const int width = roi_out->width;
490 const int height = roi_out->height;
491
492 size_t sizes[] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
493
495
496 /* Settled in commit_params(), exactly as the CPU path above reads it -- the two used to read
497 * conf separately, which is how a GUI-only condition duplicated between process() and
498 * process_cl() drifts (CLAUDE.md names this class by name). One source now, one commit. */
499 const dt_iop_gamma_data_t *const d = (const dt_iop_gamma_data_t *)piece->data;
500 if(IS_NULL_PTR(d)) return FALSE;
501
502 int mode = DT_IOP_GAMMA_KERNEL_COPY;
503 int channel = DT_IOP_GAMMA_FALSE_COLOR_MONO;
504 float alpha = (mask_display & DT_DEV_PIXELPIPE_DISPLAY_MASK) ? 1.0f : 0.0f;
505 /* These two MUST stay arrays, not pointers to d->preview's. The kernel argument below is
506 * sized with sizeof(), so a pointer passes 8 bytes of host address where the kernel wants a
507 * 16-byte float4 -- CL_INVALID_KERNEL_ARGS (-52) on every frame, the GPU path failing over
508 * to a CPU fallback that reads host input the RAM-caching policy never populated, i.e. the
509 * previous life of a rekeyed cacheline: an older frame, drawn silently. Nothing warns,
510 * because sizeof() on a pointer is perfectly legal. */
511 dt_aligned_pixel_t checker_color_1;
512 dt_aligned_pixel_t checker_color_2;
513 for(int c = 0; c < 4; c++)
514 {
515 checker_color_1[c] = d->preview.checker_color_1[c];
516 checker_color_2[c] = d->preview.checker_color_2[c];
517 }
518 const int checker_1 = (int)d->preview.checker_1;
519 const int checker_2 = (int)d->preview.checker_2;
520 const int black_and_white = d->preview.black_and_white ? 1 : 0;
521
522 if((mask_display & DT_DEV_PIXELPIPE_DISPLAY_CHANNEL)
523 && (mask_display & DT_DEV_PIXELPIPE_DISPLAY_ANY))
524 {
525 if(d->false_color)
526 {
528 channel = _false_color_channel_to_kernel_code(mask_display);
529 }
530 else
531 {
533 }
534 }
535 else if(mask_display & DT_DEV_PIXELPIPE_DISPLAY_MASK)
536 {
538 alpha = 1.0f;
539 }
540 dt_opencl_set_kernel_arg(devid, gd->kernel_gamma_pack, 0, sizeof(cl_mem), (void *)&dev_in);
541 dt_opencl_set_kernel_arg(devid, gd->kernel_gamma_pack, 1, sizeof(cl_mem), (void *)&dev_out);
542 dt_opencl_set_kernel_arg(devid, gd->kernel_gamma_pack, 2, sizeof(int), (void *)&width);
543 dt_opencl_set_kernel_arg(devid, gd->kernel_gamma_pack, 3, sizeof(int), (void *)&height);
544 dt_opencl_set_kernel_arg(devid, gd->kernel_gamma_pack, 4, sizeof(int), (void *)&mode);
545 dt_opencl_set_kernel_arg(devid, gd->kernel_gamma_pack, 5, sizeof(int), (void *)&channel);
546 dt_opencl_set_kernel_arg(devid, gd->kernel_gamma_pack, 6, sizeof(float), (void *)&alpha);
547 /* The kernel wants a float4 for each; sizeof() on a decayed pointer would quietly pass 8
548 * bytes of host address instead, which the compiler cannot warn about. Checked here rather
549 * than trusted, because the runtime symptom is an older frame drawn silently. */
550 _Static_assert(sizeof(checker_color_1) == 4 * sizeof(float), "checker colour 1 must be a float4, not a pointer");
551 _Static_assert(sizeof(checker_color_2) == 4 * sizeof(float), "checker colour 2 must be a float4, not a pointer");
552 dt_opencl_set_kernel_arg(devid, gd->kernel_gamma_pack, 7, sizeof(checker_color_1), (void *)&checker_color_1);
553 dt_opencl_set_kernel_arg(devid, gd->kernel_gamma_pack, 8, sizeof(checker_color_2), (void *)&checker_color_2);
554 dt_opencl_set_kernel_arg(devid, gd->kernel_gamma_pack, 9, sizeof(int), (void *)&checker_1);
555 dt_opencl_set_kernel_arg(devid, gd->kernel_gamma_pack, 10, sizeof(int), (void *)&checker_2);
556 dt_opencl_set_kernel_arg(devid, gd->kernel_gamma_pack, 11, sizeof(int), (void *)&black_and_white);
557
558 err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_gamma_pack, sizes);
559 if(err == CL_SUCCESS) return TRUE;
560
561 dt_print(DT_DEBUG_OPENCL, "[opencl_gamma] couldn't enqueue kernel! %d\n", err);
562 return FALSE;
563}
564
566{
567 const int program = 2; // basic.cl, from programs.conf
569 if(!gd) return;
570 module->data = gd;
571 gd->kernel_gamma_pack = dt_opencl_create_kernel(program, "gamma_pack");
572}
573
580#endif
581
583{
584 // module->data = malloc(sizeof(dt_iop_gamma_data_t));
585 module->params = calloc(1, sizeof(dt_iop_gamma_params_t));
586 module->default_params = calloc(1, sizeof(dt_iop_gamma_params_t));
587 module->params_size = sizeof(dt_iop_gamma_params_t);
588 module->hide_enable_button = 1;
589 module->default_enabled = 1;
590}
591
592/* The settled mask-preview appearance is part of this node's effective contract, so it has to
593 * be part of its cache key: the values come from conf, which no history carries, and without
594 * this a changed checkerboard would be served from a cacheline keyed on the old one. The whole
595 * struct is content -- no pointers -- so the full sizeof() is the hashed prefix. */
598{
599 return TRUE;
600}
601
603{
605 piece->data_size = IS_NULL_PTR(piece->data) ? 0 : sizeof(dt_iop_gamma_data_t);
606}
607
609{
610 dt_free_align(piece->data);
611 piece->data = NULL;
612 piece->data_size = 0;
613}
614
617{
618 // Only GUI pipes return 8 bits unsigned integer BGRA
620 piece->enabled = 1;
621 else
622 piece->enabled = 0;
623
625 if(IS_NULL_PTR(d)) return;
626
627 /* commit_params() runs for EVERY node of EVERY pipe, disabled ones included -- thumbnails,
628 * exports, the navigation preview -- so anything read here is charged to all of them. This
629 * module is enabled in the two GUI pipes only (just above), and the settled values below
630 * describe a mask preview that cannot exist anywhere else.
631 *
632 * The cost is not the arithmetic: each dt_conf_get_* takes the application-wide
633 * darktable.conf->mutex, and dt_conf_get_float additionally runs dt_calculator_solve() over
634 * the stored string. Nine acquisitions of a lock the GUI thread holds constantly, per node
635 * resync, on every thumbnail worker at once, is contention charged to the whole application
636 * for a checkerboard no thumbnail can draw. */
637 if(!piece->enabled) return;
638
639 /* Settle the mask-preview appearance here, once, rather than in the two process() paths --
640 * see dt_iop_gamma_data_t. The keys keep Color Balance's historical namespace because
641 * views/darkroom.c's "Mask preview settings" toolbox writes them under those names, and it
642 * is that toolbox (not this module) that owns them: its four writers bump
643 * dev->mask_preview_settings_revision and call dt_dev_pixelpipe_resync_history_main(),
644 * which re-runs commit_params() for EVERY node -- with default params where history has
645 * none, which is this module's case, it carrying IOP_FLAGS_NO_HISTORY_STACK. */
646 const float checker_1_rgb[3] = {
647 CLAMP(dt_conf_get_float("plugins/darkroom/colorbalancergb/checker1/red"), 0.0f, 1.0f),
648 CLAMP(dt_conf_get_float("plugins/darkroom/colorbalancergb/checker1/green"), 0.0f, 1.0f),
649 CLAMP(dt_conf_get_float("plugins/darkroom/colorbalancergb/checker1/blue"), 0.0f, 1.0f)
650 };
651 const float checker_2_rgb[3] = {
652 CLAMP(dt_conf_get_float("plugins/darkroom/colorbalancergb/checker2/red"), 0.0f, 1.0f),
653 CLAMP(dt_conf_get_float("plugins/darkroom/colorbalancergb/checker2/green"), 0.0f, 1.0f),
654 CLAMP(dt_conf_get_float("plugins/darkroom/colorbalancergb/checker2/blue"), 0.0f, 1.0f)
655 };
656
657 for(int c = 0; c < 3; c++)
658 {
659 d->preview.checker_color_1[c] = checker_1_rgb[c];
660 d->preview.checker_color_2[c] = checker_2_rgb[c];
661 }
662 d->preview.checker_color_1[3] = 0.0f;
663 d->preview.checker_color_2[3] = 0.0f;
664
665 const size_t checker_size
666 = MAX((size_t)DT_PIXEL_APPLY_DPI(dt_conf_get_int("plugins/darkroom/colorbalancergb/checker/size")), 2);
667 d->preview.checker_1 = checker_size;
668 d->preview.checker_2 = 2 * checker_size;
669
670 // The ROI's, not a setting: filled by process(), and deliberately left 0 here so it cannot
671 // reach the hash -- dt_pixelpipe_get_global_hash() already folds piece->roi_out in.
672 d->preview.width = 0;
673
674 d->preview.black_and_white
675 = dt_conf_get_bool("plugins/darkroom/colorbalancergb/mask_preview/greyscaled");
676 d->false_color = dt_conf_is_equal("channel_display", "false color");
677}
678
679// clang-format off
680// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
681// vim: shiftwidth=2 expandtab tabstop=2 cindent
682// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
683// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
static const float x
dt_XYZ_to_Rec709_D50(XYZ, rgb)
dt_Lab_to_XYZ(Lab, XYZ)
static dt_aligned_pixel_t XYZ
static dt_aligned_pixel_t sRGB
static dt_aligned_pixel_t XYZ_D65
const dt_colormatrix_t dt_aligned_pixel_t out
static dt_aligned_pixel_t JzAzBz
int dt_conf_get_bool(const char *name)
float dt_conf_get_float(const char *name)
Float for name, clamped to its declared bounds.
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
gboolean dt_conf_is_equal(const char *name, const char *value)
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)
dt_dev_pixelpipe_display_mask_t
Definition develop.h:121
@ DT_DEV_PIXELPIPE_DISPLAY_a
Definition develop.h:127
@ DT_DEV_PIXELPIPE_DISPLAY_OUTPUT
Definition develop.h:125
@ DT_DEV_PIXELPIPE_DISPLAY_G
Definition develop.h:130
@ DT_DEV_PIXELPIPE_DISPLAY_L
Definition develop.h:126
@ DT_DEV_PIXELPIPE_DISPLAY_CHANNEL
Definition develop.h:124
@ DT_DEV_PIXELPIPE_DISPLAY_ANY
Definition develop.h:143
@ DT_DEV_PIXELPIPE_DISPLAY_LCH_h
Definition develop.h:134
@ DT_DEV_PIXELPIPE_DISPLAY_JzCzhz_hz
Definition develop.h:140
@ DT_DEV_PIXELPIPE_DISPLAY_HSL_H
Definition develop.h:135
@ DT_DEV_PIXELPIPE_DISPLAY_HSL_S
Definition develop.h:136
@ DT_DEV_PIXELPIPE_DISPLAY_JzCzhz_Cz
Definition develop.h:139
@ DT_DEV_PIXELPIPE_DISPLAY_LCH_C
Definition develop.h:133
@ DT_DEV_PIXELPIPE_DISPLAY_b
Definition develop.h:128
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
Definition develop.h:123
@ DT_DEV_PIXELPIPE_DISPLAY_JzCzhz_Jz
Definition develop.h:138
@ DT_DEV_PIXELPIPE_DISPLAY_HSL_l
Definition develop.h:137
@ DT_DEV_PIXELPIPE_DISPLAY_GRAY
Definition develop.h:132
@ DT_DEV_PIXELPIPE_DISPLAY_B
Definition develop.h:131
@ DT_DEV_PIXELPIPE_DISPLAY_R
Definition develop.h:129
GtkWidget * preview
what the selected row actually captures
@ IOP_CS_RGB_DISPLAY
Definition format.h:71
@ TYPE_FLOAT
Definition format.h:56
@ TYPE_UINT8
Definition format.h:58
void init(dt_iop_module_t *module)
Definition gamma.c:582
static __DT_CLONE_TARGETS__ void _channel_display_monochrome(const float *const restrict in, uint8_t *const restrict out, const size_t buffsize, const float alpha, const dt_iop_gamma_mask_preview_t *const preview)
Definition gamma.c:234
int default_group()
Definition gamma.c:110
int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const i, void *const o)
Definition gamma.c:396
static int _false_color_channel_to_kernel_code(const dt_dev_pixelpipe_display_mask_t mask_display)
Definition gamma.c:449
static __DT_CLONE_TARGETS__ void _channel_display_false_color(const float *const restrict in, uint8_t *const restrict out, const size_t buffsize, const float alpha, dt_dev_pixelpipe_display_mask_t channel, const dt_iop_gamma_mask_preview_t *const preview)
Definition gamma.c:247
static void _write_pixel(const float *const restrict in, uint8_t *const restrict out, const dt_iop_gamma_mask_preview_t *const preview, const size_t pixel_index, const float alpha)
Blend one linear RGB pixel with its mask checker and encode it for display.
Definition gamma.c:191
static __DT_CLONE_TARGETS__ void _copy_output(const float *const restrict in, uint8_t *const restrict out, const size_t buffsize)
Definition gamma.c:382
dt_iop_gamma_kernel_mode_t
Definition gamma.c:83
@ DT_IOP_GAMMA_KERNEL_MASK
Definition gamma.c:85
@ DT_IOP_GAMMA_KERNEL_CHANNEL_FALSE_COLOR
Definition gamma.c:87
@ DT_IOP_GAMMA_KERNEL_COPY
Definition gamma.c:84
@ DT_IOP_GAMMA_KERNEL_CHANNEL_MONO
Definition gamma.c:86
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition gamma.c:602
const char * name()
Definition gamma.c:105
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 gamma.c:133
dt_iop_gamma_false_color_t
Definition gamma.c:91
@ DT_IOP_GAMMA_FALSE_COLOR_MONO
Definition gamma.c:92
@ DT_IOP_GAMMA_FALSE_COLOR_G
Definition gamma.c:96
@ DT_IOP_GAMMA_FALSE_COLOR_C
Definition gamma.c:98
@ DT_IOP_GAMMA_FALSE_COLOR_A
Definition gamma.c:93
@ DT_IOP_GAMMA_FALSE_COLOR_R
Definition gamma.c:95
@ DT_IOP_GAMMA_FALSE_COLOR_B_CH
Definition gamma.c:97
@ DT_IOP_GAMMA_FALSE_COLOR_LCH_H
Definition gamma.c:99
@ DT_IOP_GAMMA_FALSE_COLOR_JZ_HZ
Definition gamma.c:101
@ DT_IOP_GAMMA_FALSE_COLOR_HSL_H
Definition gamma.c:100
@ DT_IOP_GAMMA_FALSE_COLOR_B
Definition gamma.c:94
void cleanup_global(dt_iop_module_so_t *module)
Definition gamma.c:574
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition gamma.c:120
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 gamma.c:125
int flags()
Definition gamma.c:115
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 gamma.c:615
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition gamma.c:608
void init_global(dt_iop_module_so_t *module)
Definition gamma.c:565
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 gamma.c:482
static __DT_CLONE_TARGETS__ void _mask_display(const float *const restrict in, uint8_t *const restrict out, const size_t buffsize, const float alpha, const dt_iop_gamma_mask_preview_t *const preview)
Definition gamma.c:364
gboolean runtime_data_hash(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition gamma.c:596
@ IOP_FLAGS_HIDDEN
Definition imageop.h:189
@ IOP_FLAGS_UNSAFE_COPY
Definition imageop.h:196
@ IOP_FLAGS_ONE_INSTANCE
Definition imageop.h:191
@ IOP_FLAGS_NO_HISTORY_STACK
Definition imageop.h:193
@ IOP_GROUP_TECHNICAL
Definition imageop.h:162
static const dt_dev_pixelpipe_t * pipe
Definition layers.h:49
static const dt_dev_pixelpipe_t const dt_dev_pixelpipe_iop_t * piece
Definition layers.h:50
static const dt_iop_drawlayer_params_t * params
Definition layers.h:80
@ linear
Definition lightroom.c:369
@ DT_DEBUG_OPENCL
Definition logging.h:57
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
#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 o
#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:2612
int dt_opencl_create_kernel(const int prog, const char *name)
Definition opencl.c:2506
void dt_opencl_free_kernel(const int kernel)
Definition opencl.c:2549
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:2603
#define ROUNDUPDHT(a, b)
Definition opencl.h:86
#define ROUNDUPDWD(a, b)
Definition opencl.h:85
#define __OMP_DECLARE_SIMD__(...)
Definition openmp.h:100
#define __OMP_PARALLEL_FOR__(...)
Definition openmp.h:95
#define __OMP_PARALLEL_FOR_SIMD__(...)
Definition openmp.h:96
const float factor
Definition pdf.h:91
@ DT_DEV_PIXELPIPE_PREVIEW
Definition pixelpipe.h:44
@ DT_DEV_PIXELPIPE_FULL
Definition pixelpipe.h:43
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
Definition simd.h:53
#define for_each_channel(_var,...)
Definition simd.h:87
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
Definition simd.h:55
static const dt_aligned_pixel_simd_t value
Definition simd.h:144
dt_dev_pixelpipe_type_t type
unsigned int channels
Definition format.h:83
dt_iop_buffer_type_t datatype
Definition format.h:85
Everything the two process() paths need, settled once per commit_params().
Definition gamma.c:182
dt_iop_gamma_mask_preview_t preview
Definition gamma.c:183
gboolean false_color
Definition gamma.c:184
Shared appearance of mask previews rendered by the display encoding module.
Definition gamma.c:149
dt_aligned_pixel_t checker_color_2
Definition gamma.c:151
dt_aligned_pixel_t checker_color_1
Definition gamma.c:150
This module converts float32 RGBA pixels to uint8 BGRA pixels, for GUI pipelines only (darkroom main ...
Definition gamma.c:72
dt_iop_global_data_t * data
Definition imageop.h:238
dt_iop_global_data_t * global_data
Definition imageop.h:337
Region of interest passed through the pixelpipe.
Definition format.h:49
int width
Definition format.h:50
int height
Definition format.h:50
#define __DT_CLONE_TARGETS__
#define MAX(a, b)
Definition thinplate.c:29
#define DT_PIXEL_APPLY_DPI(value)