Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
filmic.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2018-2020, 2023, 2025-2026 Aurélien PIERRE.
4 Copyright (C) 2018-2019 Edgardo Hoszowski.
5 Copyright (C) 2018 Matthieu Moy.
6 Copyright (C) 2018-2021 Pascal Obry.
7 Copyright (C) 2018 Philippe Weyland.
8 Copyright (C) 2019 Andreas Schneider.
9 Copyright (C) 2019-2020, 2022 Diederik Ter Rahe.
10 Copyright (C) 2019 luzpaz.
11 Copyright (C) 2019 Tobias Ellinghaus.
12 Copyright (C) 2020, 2022 Aldric Renaudin.
13 Copyright (C) 2020 Marco.
14 Copyright (C) 2020-2021 Ralf Brown.
15 Copyright (C) 2021 Chris Elston.
16 Copyright (C) 2021 Dan Torop.
17 Copyright (C) 2021 Hubert Kowalski.
18 Copyright (C) 2021 Victor Forsiuk.
19 Copyright (C) 2022 Hanno Schwalm.
20 Copyright (C) 2022 Martin Bařinka.
21 Copyright (C) 2022 Nicolas Auffray.
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 "config.h"
39#endif
40#include "bauhaus/bauhaus.h"
42#include "common/darktable.h"
43#include "common/math.h"
44#include "common/opencl.h"
45#include "control/control.h"
46#include "develop/develop.h"
48#include "dtgtk/button.h"
49#include "dtgtk/drawingarea.h"
50#include "dtgtk/expander.h"
51#include "dtgtk/paint.h"
52
53#include "gui/gtk.h"
54#include "gui/presets.h"
56#include "iop/iop_api.h"
57
58
59#include "develop/imageop.h"
60#include "gui/draw.h"
61
62#include <assert.h>
63#include <math.h>
64#include <stdlib.h>
65#include <string.h>
66
67#define DT_GUI_CURVE_EDITOR_INSET DT_PIXEL_APPLY_DPI(1)
68
69
71
72
119
144
146{
147 float table[0x10000]; // precomputed look-up table
148 float table_temp[0x10000]; // precomputed look-up for the optimized interpolation
149 float grad_2[0x10000];
150 float max_grad;
157 float contrast;
162
164{
165 int nodes;
166 float y[5];
167 float x[5];
169
175
176
177const char *name()
178{
179 return _("filmic (legacy)");
180}
181
183{
184 return IOP_GROUP_TONES;
185}
186
191
192const char *deprecated_msg()
193{
194 return _("this module is deprecated. better use filmic rgb module instead.");
195}
196
198{
199 return IOP_CS_LAB;
200}
201
204{
205 default_input_format(self, pipe, piece, dsc);
206 dsc->channels = 4;
207 dsc->datatype = TYPE_FLOAT;
208}
209
210int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params,
211 const int new_version)
212{
213 if(old_version == 1 && new_version == 3)
214 {
215 typedef struct dt_iop_filmic_params_v1_t
216 {
217 float grey_point_source;
218 float black_point_source;
219 float white_point_source;
220 float security_factor;
221 float grey_point_target;
222 float black_point_target;
223 float white_point_target;
224 float output_power;
225 float latitude_stops;
226 float contrast;
227 float saturation;
228 float balance;
229 int interpolator;
230 } dt_iop_filmic_params_v1_t;
231
232 dt_iop_filmic_params_v1_t *o = (dt_iop_filmic_params_v1_t *)old_params;
235
236 *n = *d; // start with a fresh copy of default parameters
237
238 n->grey_point_source = o->grey_point_source;
239 n->white_point_source = o->white_point_source;
240 n->black_point_source = o->black_point_source;
241 n->security_factor = o->security_factor;
242 n->grey_point_target = o->grey_point_target;
243 n->black_point_target = o->black_point_target;
244 n->white_point_target = o->white_point_target;
245 n->output_power = o->output_power;
246 n->latitude_stops = o->latitude_stops;
247 n->contrast = o->contrast;
248 n->saturation = o->saturation;
249 n->balance = o->balance;
250 n->interpolator = o->interpolator;
251 n->preserve_color = 0;
252 n->global_saturation = 100;
253 return 0;
254 }
255
256 if (old_version == 2 && new_version == 3)
257 {
258 typedef struct dt_iop_filmic_params_v2_t
259 {
260 float grey_point_source;
261 float black_point_source;
262 float white_point_source;
263 float security_factor;
264 float grey_point_target;
265 float black_point_target;
266 float white_point_target;
267 float output_power;
268 float latitude_stops;
269 float contrast;
270 float saturation;
271 float balance;
272 int interpolator;
273 int preserve_color;
274 } dt_iop_filmic_params_v2_t;
275
276 dt_iop_filmic_params_v2_t *o = (dt_iop_filmic_params_v2_t *)old_params;
279
280 *n = *d; // start with a fresh copy of default parameters
281
282 n->grey_point_source = o->grey_point_source;
283 n->white_point_source = o->white_point_source;
284 n->black_point_source = o->black_point_source;
285 n->security_factor = o->security_factor;
286 n->grey_point_target = o->grey_point_target;
287 n->black_point_target = o->black_point_target;
288 n->white_point_target = o->white_point_target;
289 n->output_power = o->output_power;
290 n->latitude_stops = o->latitude_stops;
291 n->contrast = o->contrast;
292 n->saturation = o->saturation;
293 n->balance = o->balance;
294 n->interpolator = o->interpolator;
295 n->preserve_color = o->preserve_color;
296 n->global_saturation = 100;
297 return 0;
298 }
299 return 1;
300}
301
303{
305 memset(&p, 0, sizeof(p));
306
307 // Fine-tune settings, no use here
308 p.interpolator = CUBIC_SPLINE;
309
310 // Output - standard display, gamma 2.2
311 p.output_power = 2.2f;
312 p.white_point_target = 100.0f;
313 p.black_point_target = 0.0f;
314 p.grey_point_target = 18.0f;
315
316 // Input - standard raw picture
317 p.security_factor = 0.0f;
318 p.contrast = 1.618f;
319 p.preserve_color = 1;
320 p.balance = -12.0f;
321 p.saturation = 60.0f;
322 p.global_saturation = 70.0f;
323
324 // Presets low-key
325 p.grey_point_source = 25.4f;
326 p.latitude_stops = 2.25f;
327 p.white_point_source = 1.95f;
328 p.black_point_source = -7.05f;
329 dt_gui_presets_add_generic(_("09 EV (low-key)"), self->op,
330 self->version(), &p, sizeof(p), 1, DEVELOP_BLEND_CS_RGB_DISPLAY);
331
332 // Presets indoors
333 p.grey_point_source = 18.0f;
334 p.latitude_stops = 2.75f;
335 p.white_point_source = 2.45f;
336 p.black_point_source = -7.55f;
337 dt_gui_presets_add_generic(_("10 EV (indoors)"), self->op,
338 self->version(), &p, sizeof(p), 1, DEVELOP_BLEND_CS_RGB_DISPLAY);
339
340 // Presets dim-outdoors
341 p.grey_point_source = 12.77f;
342 p.latitude_stops = 3.0f;
343 p.white_point_source = 2.95f;
344 p.black_point_source = -8.05f;
345 dt_gui_presets_add_generic(_("11 EV (dim outdoors)"), self->op,
346 self->version(), &p, sizeof(p), 1, DEVELOP_BLEND_CS_RGB_DISPLAY);
347
348 // Presets outdoors
349 p.grey_point_source = 9.0f;
350 p.latitude_stops = 3.5f;
351 p.white_point_source = 3.45f;
352 p.black_point_source = -8.55f;
353 dt_gui_presets_add_generic(_("12 EV (outdoors)"), self->op,
354 self->version(), &p, sizeof(p), 1, DEVELOP_BLEND_CS_RGB_DISPLAY);
355
356 // Presets outdoors
357 p.grey_point_source = 6.38f;
358 p.latitude_stops = 3.75f;
359 p.white_point_source = 3.95f;
360 p.black_point_source = -9.05f;
361 dt_gui_presets_add_generic(_("13 EV (bright outdoors)"), self->op,
362 self->version(), &p, sizeof(p), 1, DEVELOP_BLEND_CS_RGB_DISPLAY);
363
364 // Presets backlighting
365 p.grey_point_source = 4.5f;
366 p.latitude_stops = 4.25f;
367 p.white_point_source = 4.45f;
368 p.black_point_source = -9.55f;
369 dt_gui_presets_add_generic(_("14 EV (backlighting)"), self->op,
370 self->version(), &p, sizeof(p), 1, DEVELOP_BLEND_CS_RGB_DISPLAY);
371
372 // Presets sunset
373 p.grey_point_source = 3.19f;
374 p.latitude_stops = 4.50f;
375 p.white_point_source = 4.95f;
376 p.black_point_source = -10.05f;
377 dt_gui_presets_add_generic(_("15 EV (sunset)"), self->op,
378 self->version(), &p, sizeof(p), 1, DEVELOP_BLEND_CS_RGB_DISPLAY);
379
380 // Presets HDR
381 p.grey_point_source = 2.25f;
382 p.latitude_stops = 5.0f;
383 p.white_point_source = 5.45f;
384 p.black_point_source = -10.55f;
385 dt_gui_presets_add_generic(_("16 EV (HDR)"), self->op,
386 self->version(), &p, sizeof(p), 1, DEVELOP_BLEND_CS_RGB_DISPLAY);
387
388 // Presets HDR+
389 p.grey_point_source = 1.125f;
390 p.latitude_stops = 6.0f;
391 p.white_point_source = 6.45f;
392 p.black_point_source = -11.55f;
393 dt_gui_presets_add_generic(_("18 EV (HDR++)"), self->op,
394 self->version(), &p, sizeof(p), 1, DEVELOP_BLEND_CS_RGB_DISPLAY);
395}
396
397static inline float gaussian(float x, float std)
398{
399 return expf(- (x * x) / (2.0f * std * std)) / (std * powf(2.0f * M_PI, 0.5f));
400}
401
404 const void *const ivoid, void *const ovoid)
405{
406 const dt_iop_roi_t *const roi_out = &piece->roi_out;
407 dt_iop_filmic_data_t *const data = (dt_iop_filmic_data_t *)piece->data;
408
409 const int ch = 4;
410
418 const float EPS = powf(2.0f, -16);
419 const int preserve_color = data->preserve_color;
420
421 // If saturation == 100, we have a no-op. Disable the op then.
422 const int desaturate = (data->global_saturation == 100.0f) ? FALSE : TRUE;
423 const float saturation = data->global_saturation / 100.0f;
425 for(size_t k = 0; k < (size_t)roi_out->height * roi_out->width * ch; k += ch)
426 {
427 float *in = ((float *)ivoid) + k;
428 float *out = ((float *)ovoid) + k;
429
431 dt_Lab_to_XYZ(in, XYZ);
432
433 dt_aligned_pixel_t rgb = { 0.0f };
435
436 float concavity, luma;
437
438 // Global desaturation
439 if (desaturate)
440 {
441 luma = XYZ[1];
442
443 for(int c = 0; c < 3; c++)
444 {
445 rgb[c] = luma + saturation * (rgb[c] - luma);
446 }
447 }
448
449 if (preserve_color)
450 {
451 int index;
452 dt_aligned_pixel_t ratios;
453 float max = fmaxf(fmaxf(rgb[0], rgb[1]), rgb[2]);
454
455 // Save the ratios
456 for (int c = 0; c < 3; ++c) ratios[c] = rgb[c] / max;
457
458 // Log tone-mapping
459 max = max / data->grey_source;
460 max = (max > EPS) ? (fastlog2(max) - data->black_source) / data->dynamic_range : EPS;
461 max = CLAMP(max, 0.0f, 1.0f);
462
463 // Filmic S curve on the max RGB
464 index = CLAMP(max * 0x10000ul, 0, 0xffff);
465 max = data->table[index];
466 concavity = data->grad_2[index];
467
468 // Re-apply ratios
469 for (int c = 0; c < 3; ++c) rgb[c] = ratios[c] * max;
470
471 luma = max;
472 }
473 else
474 {
475 int DT_ALIGNED_ARRAY index[4];
476
477 for(int c = 0; c < 3; c++)
478 {
479 // Log tone-mapping on RGB
480 rgb[c] = rgb[c] / data->grey_source;
481 rgb[c] = (rgb[c] > EPS) ? (fastlog2(rgb[c]) - data->black_source) / data->dynamic_range : EPS;
482 rgb[c] = CLAMP(rgb[c], 0.0f, 1.0f);
483
484 // Store the index of the LUT
485 index[c] = CLAMP(rgb[c] * 0x10000ul, 0, 0xffff);
486 }
487
488 // Concavity
490 concavity = data->grad_2[(int)CLAMP(XYZ[1] * 0x10000ul, 0, 0xffff)];
491
492 // Filmic S curve
493 for(int c = 0; c < 3; c++) rgb[c] = data->table[index[c]];
494
496 luma = XYZ[1];
497 }
498
499 // Desaturate on the non-linear parts of the curve
500 for(int c = 0; c < 3; c++)
501 {
502 // Desaturate on the non-linear parts of the curve
503 rgb[c] = luma + concavity * (rgb[c] - luma);
504
505 // Apply the transfer function of the display
506 rgb[c] = powf(CLAMP(rgb[c], 0.0f, 1.0f), data->output_power);
507 }
508
509 // transform the result back to Lab
510 // sRGB -> XYZ
511 dt_prophotorgb_to_Lab(rgb, out);
512 }
513
515 dt_iop_alpha_copy(ivoid, ovoid, roi_out->width, roi_out->height);
516 return 0;
517}
518
519
520#ifdef HAVE_OPENCL
521int 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)
522{
523 const dt_iop_roi_t *const roi_in = &piece->roi_in;
526
527 cl_int err = -999;
528 const int devid = pipe->devid;
529 const int width = roi_in->width;
530 const int height = roi_in->height;
531
532 size_t sizes[] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
533
534 cl_mem dev_table = NULL;
535 cl_mem diff_table = NULL;
536
537 dev_table = dt_opencl_copy_host_to_device(devid, d->table, 256, 256, sizeof(float));
538 if(IS_NULL_PTR(dev_table)) goto error;
539
540 diff_table = dt_opencl_copy_host_to_device(devid, d->grad_2, 256, 256, sizeof(float));
541 if(IS_NULL_PTR(diff_table)) goto error;
542
543 const float dynamic_range = d->dynamic_range;
544 const float shadows_range = d->black_source;
545 const float grey = d->grey_source;
546 const float contrast = d->contrast;
547 const float power = d->output_power;
548 const int preserve_color = d->preserve_color;
549 const float saturation = d->global_saturation / 100.0f;
550
551 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 0, sizeof(cl_mem), (void *)&dev_in);
552 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 1, sizeof(cl_mem), (void *)&dev_out);
553 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 2, sizeof(int), (void *)&width);
554 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 3, sizeof(int), (void *)&height);
555 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 4, sizeof(float), (void *)&dynamic_range);
556 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 5, sizeof(float), (void *)&shadows_range);
557 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 6, sizeof(float), (void *)&grey);
558 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 7, sizeof(cl_mem), (void *)&dev_table);
559 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 8, sizeof(cl_mem), (void *)&diff_table);
560 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 9, sizeof(float), (void *)&contrast);
561 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 10, sizeof(float), (void *)&power);
562 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 11, sizeof(int), (void *)&preserve_color);
563 dt_opencl_set_kernel_arg(devid, gd->kernel_filmic, 12, sizeof(int), (void *)&saturation);
564
565 err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_filmic, sizes);
566 if(err != CL_SUCCESS) goto error;
569 return TRUE;
570
571error:
574 dt_print(DT_DEBUG_OPENCL, "[opencl_filmic] couldn't enqueue kernel! %d\n", err);
575 return FALSE;
576}
577#endif
578
580{
581 if (p->latitude_stops > (p->white_point_source - p->black_point_source) * 0.99f)
582 {
583 // The film latitude is its linear part
584 // it can never be higher than the dynamic range
585 p->latitude_stops = (p->white_point_source - p->black_point_source) * 0.99f;
587 dt_bauhaus_slider_set(g->latitude_stops, p->latitude_stops);
589 }
590}
591
593{
594 if(darktable.gui->reset) return;
597
598 dt_aligned_pixel_t XYZ = { 0.0f };
600
601 const float grey = XYZ[1];
602 const float prev_grey = p->grey_point_source;
603 p->grey_point_source = 100.f * grey;
604 const float grey_var = Log2(prev_grey / p->grey_point_source);
605 p->black_point_source = p->black_point_source - grey_var;
606 p->white_point_source = p->white_point_source + grey_var;
607
609 dt_bauhaus_slider_set(g->grey_point_source, p->grey_point_source);
610 dt_bauhaus_slider_set(g->black_point_source, p->black_point_source);
611 dt_bauhaus_slider_set(g->white_point_source, p->white_point_source);
613
615 gtk_widget_queue_draw(self->widget);
616}
617
619{
620 if(darktable.gui->reset) return;
623
624 const float noise = powf(2.0f, -16.0f);
625 dt_aligned_pixel_t XYZ = { 0.0f };
626
627 // Black
629 const float black = XYZ[1];
630 float EVmin = Log2Thres(black / (p->grey_point_source / 100.0f), noise);
631 EVmin *= (1.0f + p->security_factor / 100.0f);
632
633 p->black_point_source = EVmin;
634
636 dt_bauhaus_slider_set(g->black_point_source, p->black_point_source);
638
640
642 gtk_widget_queue_draw(self->widget);
643}
644
645
647{
648 if(darktable.gui->reset) return;
651
652 const float noise = powf(2.0f, -16.0f);
653 dt_aligned_pixel_t XYZ = { 0.0f };
654
655 // White
657 const float white = XYZ[1];
658 float EVmax = Log2Thres(white / (p->grey_point_source / 100.0f), noise);
659 EVmax *= (1.0f + p->security_factor / 100.0f);
660
661 p->white_point_source = EVmax;
662
664 dt_bauhaus_slider_set(g->white_point_source, p->white_point_source);
666
668
670 gtk_widget_queue_draw(self->widget);
671}
672
673static void security_threshold_callback(GtkWidget *slider, gpointer user_data)
674{
675 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
676 if(darktable.gui->reset) return;
679
680 float previous = p->security_factor;
681 p->security_factor = dt_bauhaus_slider_get(slider);
682 float ratio = (p->security_factor - previous) / (previous + 100.0f);
683
684 float EVmin = p->black_point_source;
685 EVmin = EVmin + ratio * EVmin;
686
687 float EVmax = p->white_point_source;
688 EVmax = EVmax + ratio * EVmax;
689
690 p->white_point_source = EVmax;
691 p->black_point_source = EVmin;
692
694 dt_bauhaus_slider_set(g->white_point_source, p->white_point_source);
695 dt_bauhaus_slider_set(g->black_point_source, p->black_point_source);
697
699
701
703 gtk_widget_queue_draw(self->widget);
704}
705
707{
710
711 const float noise = powf(2.0f, -16.0f);
712 dt_aligned_pixel_t XYZ = { 0.0f };
713
714 // Grey
716 const float grey = XYZ[1];
717 p->grey_point_source = 100.f * grey;
718
719 // Black
721 const float black = XYZ[1];
722 float EVmin = Log2Thres(black / (p->grey_point_source / 100.0f), noise);
723 EVmin *= (1.0f + p->security_factor / 100.0f);
724
725 // White
727 const float white = XYZ[1];
728 float EVmax = Log2Thres(white / (p->grey_point_source / 100.0f), noise);
729 EVmax *= (1.0f + p->security_factor / 100.0f);
730
731 p->black_point_source = EVmin;
732 p->white_point_source = EVmax;
733
735 dt_bauhaus_slider_set(g->grey_point_source, p->grey_point_source);
736 dt_bauhaus_slider_set(g->black_point_source, p->black_point_source);
737 dt_bauhaus_slider_set(g->white_point_source, p->white_point_source);
739
741
743 gtk_widget_queue_draw(self->widget);
744}
745
747{
749 if (picker == g->grey_point_source)
750 apply_auto_grey(self);
751 else if(picker == g->black_point_source)
752 apply_auto_black(self);
753 else if(picker == g->white_point_source)
755 else if(picker == g->auto_button)
756 apply_autotune(self);
757 else
758 fprintf(stderr, "[filmic] unknown color picker\n");
759}
760
761static void grey_point_source_callback(GtkWidget *slider, gpointer user_data)
762{
763 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
764 if(darktable.gui->reset) return;
767 float prev_grey = p->grey_point_source;
768 p->grey_point_source = dt_bauhaus_slider_get(slider);
769
770 float grey_var = Log2(prev_grey / p->grey_point_source);
771 p->black_point_source = p->black_point_source - grey_var;
772 p->white_point_source = p->white_point_source + grey_var;
773
775 dt_bauhaus_slider_set(g->white_point_source, p->white_point_source);
776 dt_bauhaus_slider_set(g->black_point_source, p->black_point_source);
778
780
782 gtk_widget_queue_draw(self->widget);
783}
784
785static void white_point_source_callback(GtkWidget *slider, gpointer user_data)
786{
787 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
788 if(darktable.gui->reset) return;
791 p->white_point_source = dt_bauhaus_slider_get(slider);
792
794
796
798 gtk_widget_queue_draw(self->widget);
799}
800
801static void black_point_source_callback(GtkWidget *slider, gpointer user_data)
802{
803 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
804 if(darktable.gui->reset) return;
807 p->black_point_source = dt_bauhaus_slider_get(slider);
808
810
812
814 gtk_widget_queue_draw(self->widget);
815}
816
817static void grey_point_target_callback(GtkWidget *slider, gpointer user_data)
818{
819 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
820 if(darktable.gui->reset) return;
822 p->grey_point_target = dt_bauhaus_slider_get(slider);
825 gtk_widget_queue_draw(self->widget);
826}
827
828static void latitude_stops_callback(GtkWidget *slider, gpointer user_data)
829{
830 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
831 if(darktable.gui->reset) return;
834
835 p->latitude_stops = dt_bauhaus_slider_get(slider);
836
838
841 gtk_widget_queue_draw(self->widget);
842}
843
844static void contrast_callback(GtkWidget *slider, gpointer user_data)
845{
846 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
847 if(darktable.gui->reset) return;
849 p->contrast = dt_bauhaus_slider_get(slider);
852 gtk_widget_queue_draw(self->widget);
853}
854
855static void saturation_callback(GtkWidget *slider, gpointer user_data)
856{
857 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
858 if(darktable.gui->reset) return;
860 p->saturation = logf(9.0f * dt_bauhaus_slider_get(slider)/100.0 + 1.0f) / logf(10.0f) * 100.0f;
863}
864
865static void global_saturation_callback(GtkWidget *slider, gpointer user_data)
866{
867 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
868 if(darktable.gui->reset) return;
870 p->global_saturation = dt_bauhaus_slider_get(slider);
873}
874
875static void white_point_target_callback(GtkWidget *slider, gpointer user_data)
876{
877 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
878 if(darktable.gui->reset) return;
880 p->white_point_target = dt_bauhaus_slider_get(slider);
883 gtk_widget_queue_draw(self->widget);
884}
885
886static void black_point_target_callback(GtkWidget *slider, gpointer user_data)
887{
888 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
889 if(darktable.gui->reset) return;
891 p->black_point_target = dt_bauhaus_slider_get(slider);
894 gtk_widget_queue_draw(self->widget);
895}
896
897static void output_power_callback(GtkWidget *slider, gpointer user_data)
898{
899 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
900 if(darktable.gui->reset) return;
902 p->output_power = dt_bauhaus_slider_get(slider);
905 gtk_widget_queue_draw(self->widget);
906}
907
908static void balance_callback(GtkWidget *slider, gpointer user_data)
909{
910 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
911 if(darktable.gui->reset) return;
913 p->balance = dt_bauhaus_slider_get(slider);
916 gtk_widget_queue_draw(self->widget);
917}
918
920{
921 if(darktable.gui->reset) return;
924 const int combo = dt_bauhaus_combobox_get(widget);
925
926 switch (combo)
927 {
928 case CUBIC_SPLINE:
929 {
930 p->interpolator = CUBIC_SPLINE;
931 break;
932 }
933 case CATMULL_ROM:
934 {
935 p->interpolator = CATMULL_ROM;
936 break;
937 }
938 case MONOTONE_HERMITE:
939 {
940 p->interpolator = MONOTONE_HERMITE;
941 break;
942 }
943 case 3:
944 {
945 p->interpolator = 3; // Optimized
946 break;
947 }
948 default:
949 {
950 p->interpolator = CUBIC_SPLINE;
951 break;
952 }
953 }
954
956 gtk_widget_queue_draw(self->widget);
957}
958
960{
961 if(darktable.gui->reset) return;
963 p->preserve_color = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
965}
966
967void compute_curve_lut(dt_iop_filmic_params_t *p, float *table, float *table_temp, int res,
969{
970 dt_draw_curve_t *curve;
971
972 const float white_source = p->white_point_source;
973 const float black_source = p->black_point_source;
974 const float dynamic_range = white_source - black_source;
975
976 // luminance after log encoding
977 const float black_log = 0.0f; // assumes user set log as in the autotuner
978 const float grey_log = fabsf(p->black_point_source) / dynamic_range;
979 const float white_log = 1.0f; // assumes user set log as in the autotuner
980
981 // target luminance desired after filmic curve
982 const float black_display = CLAMP(p->black_point_target, 0.0f, p->grey_point_target) / 100.0f; // in %
983 const float grey_display = powf(CLAMP(p->grey_point_target, p->black_point_target, p->white_point_target) / 100.0f, 1.0f / (p->output_power));
984 const float white_display = CLAMP(p->white_point_target, p->grey_point_target, 100.0f) / 100.0f; // in %
985
986 const float latitude = CLAMP(p->latitude_stops, 0.01f, dynamic_range * 0.99f);
987 const float balance = CLAMP(p->balance, -50.0f, 50.0f) / 100.0f; // in %
988
989 const float contrast = p->contrast;
990
991 // nodes for mapping from log encoding to desired target luminance
992 // X coordinates
993 float toe_log = grey_log - latitude/dynamic_range * fabsf(black_source/dynamic_range);
994 float shoulder_log = grey_log + latitude/dynamic_range * white_source/dynamic_range;
995
996
997 // interception
998 float linear_intercept = grey_display - (contrast * grey_log);
999
1000 // y coordinates
1001 float toe_display = (toe_log * contrast + linear_intercept);
1002 float shoulder_display = (shoulder_log * contrast + linear_intercept);
1003
1004 // Apply the highlights/shadows balance as a shift along the contrast slope
1005 const float norm = powf(powf(contrast, 2.0f) + 1.0f, 0.5f);
1006
1007 // negative values drag to the left and compress the shadows, on the UI negative is the inverse
1008 const float coeff = -(dynamic_range - latitude) / dynamic_range * balance;
1009
1010 toe_display += coeff * contrast /norm;
1011 shoulder_display += coeff * contrast /norm;
1012 toe_log += coeff /norm;
1013 shoulder_log += coeff /norm;
1014
1015 // Sanitize pass 1
1016 toe_log = CLAMP(toe_log, 0.0f, grey_log);
1017 shoulder_log = CLAMP(shoulder_log, grey_log, 1.0f);
1018 toe_display = CLAMP(toe_display, black_display, grey_display);
1019 shoulder_display = CLAMP(shoulder_display, grey_display, white_display);
1020
1031 // sanitize pass 2
1032 int TOE_LOST = FALSE;
1033 int SHOULDER_LOST = FALSE;
1034
1035 if ((toe_log == grey_log && toe_display == grey_display) || (toe_log == 0.0f && toe_display == black_display))
1036 {
1037 TOE_LOST = TRUE;
1038 }
1039 if ((shoulder_log == grey_log && shoulder_display == grey_display) || (shoulder_log == 1.0f && shoulder_display == white_display))
1040 {
1041 SHOULDER_LOST = TRUE;
1042 }
1043
1044 // Build the curve from the nodes
1045
1046 if (SHOULDER_LOST && !TOE_LOST)
1047 {
1048 // shoulder only broke - we remove it
1049 nodes_data->nodes = 4;
1050 nodes_data->x[0] = black_log;
1051 nodes_data->x[1] = toe_log;
1052 nodes_data->x[2] = grey_log;
1053 nodes_data->x[3] = white_log;
1054
1055 nodes_data->y[0] = black_display;
1056 nodes_data->y[1] = toe_display;
1057 nodes_data->y[2] = grey_display;
1058 nodes_data->y[3] = white_display;
1059
1060 if(!IS_NULL_PTR(d))
1061 {
1062 d->latitude_min = toe_log;
1063 d->latitude_max = white_log;
1064 }
1065
1066 //dt_control_log(_("filmic curve using 4 nodes - highlights lost"));
1067
1068 }
1069 else if (TOE_LOST && !SHOULDER_LOST)
1070 {
1071 // toe only broke - we remove it
1072 nodes_data->nodes = 4;
1073
1074 nodes_data->x[0] = black_log;
1075 nodes_data->x[1] = grey_log;
1076 nodes_data->x[2] = shoulder_log;
1077 nodes_data->x[3] = white_log;
1078
1079 nodes_data->y[0] = black_display;
1080 nodes_data->y[1] = grey_display;
1081 nodes_data->y[2] = shoulder_display;
1082 nodes_data->y[3] = white_display;
1083
1084 if(!IS_NULL_PTR(d))
1085 {
1086 d->latitude_min = black_log;
1087 d->latitude_max = shoulder_log;
1088 }
1089
1090 //dt_control_log(_("filmic curve using 4 nodes - shadows lost"));
1091
1092 }
1093 else if (TOE_LOST && SHOULDER_LOST)
1094 {
1095 // toe and shoulder both broke - we remove them
1096 nodes_data->nodes = 3;
1097
1098 nodes_data->x[0] = black_log;
1099 nodes_data->x[1] = grey_log;
1100 nodes_data->x[2] = white_log;
1101
1102 nodes_data->y[0] = black_display;
1103 nodes_data->y[1] = grey_display;
1104 nodes_data->y[2] = white_display;
1105
1106 if(!IS_NULL_PTR(d))
1107 {
1108 d->latitude_min = black_log;
1109 d->latitude_max = white_log;
1110 }
1111
1112 //dt_control_log(_("filmic curve using 3 nodes - highlights & shadows lost"));
1113
1114 }
1115 else
1116 {
1117 // everything OK
1118 nodes_data->nodes = 4;
1119
1120 nodes_data->x[0] = black_log;
1121 nodes_data->x[1] = toe_log;
1122 //nodes_data->x[2] = grey_log,
1123 nodes_data->x[2] = shoulder_log;
1124 nodes_data->x[3] = white_log;
1125
1126 nodes_data->y[0] = black_display;
1127 nodes_data->y[1] = toe_display;
1128 //nodes_data->y[2] = grey_display,
1129 nodes_data->y[2] = shoulder_display;
1130 nodes_data->y[3] = white_display;
1131
1132 if(!IS_NULL_PTR(d))
1133 {
1134 d->latitude_min = toe_log;
1135 d->latitude_max = shoulder_log;
1136 }
1137
1138 //dt_control_log(_("filmic curve using 5 nodes - everything alright"));
1139 }
1140
1141 if (p->interpolator != 3)
1142 {
1143 // Compute the interpolation
1144
1145 // Catch bad interpolators exceptions (errors in saved params)
1146 int interpolator = CUBIC_SPLINE;
1147 if (p->interpolator > CUBIC_SPLINE && p->interpolator <= MONOTONE_HERMITE) interpolator = p->interpolator;
1148
1149 curve = dt_draw_curve_new(0.0, 1.0, interpolator);
1150 for(int k = 0; k < nodes_data->nodes; k++) (void)dt_draw_curve_add_point(curve, nodes_data->x[k], nodes_data->y[k]);
1151
1152 // Compute the LUT
1153 dt_draw_curve_calc_values(curve, 0.0f, 1.0f, res, NULL, table);
1154 dt_draw_curve_destroy(curve);
1155
1156 }
1157 else
1158 {
1159 // Compute the monotonic interpolation
1160 curve = dt_draw_curve_new(0.0, 1.0, MONOTONE_HERMITE);
1161 for(int k = 0; k < nodes_data->nodes; k++) (void)dt_draw_curve_add_point(curve, nodes_data->x[k], nodes_data->y[k]);
1162 dt_draw_curve_calc_values(curve, 0.0f, 1.0f, res, NULL, table_temp);
1163 dt_draw_curve_destroy(curve);
1164
1165 // Compute the cubic spline interpolation
1166 curve = dt_draw_curve_new(0.0, 1.0, CUBIC_SPLINE);
1167 for(int k = 0; k < nodes_data->nodes; k++) (void)dt_draw_curve_add_point(curve, nodes_data->x[k], nodes_data->y[k]);
1168 dt_draw_curve_calc_values(curve, 0.0f, 1.0f, res, NULL, table);
1169 dt_draw_curve_destroy(curve);
1170
1171 // Average both LUT
1173 for(int k = 0; k < res; k++) table[k] = (table[k] + table_temp[k]) / 2.0f;
1174 }
1175
1176}
1177
1180{
1183
1184 d->preserve_color = p->preserve_color;
1185
1186 // source luminance - Used only in the log encoding
1187 const float white_source = p->white_point_source;
1188 const float grey_source = p->grey_point_source / 100.0f; // in %
1189 const float black_source = p->black_point_source;
1190 const float dynamic_range = white_source - black_source;
1191
1192 // luminance after log encoding
1193 const float grey_log = fabsf(p->black_point_source) / dynamic_range;
1194
1195 // target luminance desired after filmic curve
1196 const float grey_display = powf(p->grey_point_target / 100.0f, 1.0f / (p->output_power));
1197
1198 float contrast = p->contrast;
1199 if (contrast < grey_display / grey_log)
1200 {
1201 // We need grey_display - (contrast * grey_log) <= 0.0
1202 contrast = 1.0001f * grey_display / grey_log;
1203 }
1204
1205 // commitproducts with no low-pass filter, you will increase the contrast of nois
1206 d->dynamic_range = dynamic_range;
1207 d->black_source = black_source;
1208 d->grey_source = grey_source;
1209 d->output_power = p->output_power;
1210 d->saturation = p->saturation;
1211 d->global_saturation = p->global_saturation;
1212 d->contrast = contrast;
1213
1214 // compute the curves and their LUT
1215 dt_iop_filmic_nodes_t *nodes_data = (dt_iop_filmic_nodes_t *)malloc(sizeof(dt_iop_filmic_nodes_t));
1216 compute_curve_lut(p, d->table, d->table_temp, 0x10000, d, nodes_data);
1217 dt_free(nodes_data);
1218
1219 // Build a window function based on the log.
1220 // This will be used to selectively desaturate the non-linear parts
1221 // to avoid over-saturation in the toe and shoulder.
1222
1223 const float latitude = d->latitude_max - d->latitude_min;
1224 const float center = (d->latitude_max + d->latitude_min)/2.0f;
1225 const float saturation = d->saturation / 100.0f;
1226 const float sigma = saturation * saturation * latitude * latitude;
1228 for(int k = 0; k < 65536; k++)
1229 {
1230 const float x = ((float)k) / 65536.0f;
1231 if (sigma != 0.0f)
1232 {
1233 d->grad_2[k] = expf(-0.5f * (center - x) * (center - x) / sigma);
1234 }
1235 else
1236 {
1237 d->grad_2[k] = 0.0f;
1238 }
1239 }
1240
1241}
1242
1244{
1245 piece->data = dt_calloc_align(sizeof(dt_iop_filmic_data_t));
1246 piece->data_size = sizeof(dt_iop_filmic_data_t);
1247}
1248
1250{
1251 dt_free_align(piece->data);
1252 piece->data = NULL;
1253}
1254
1256{
1257 dt_iop_module_t *module = (dt_iop_module_t *)self;
1259 dt_iop_filmic_params_t *p = (dt_iop_filmic_params_t *)module->params;
1260
1262
1263 dt_bauhaus_slider_set(g->white_point_source, p->white_point_source);
1264 dt_bauhaus_slider_set(g->grey_point_source, p->grey_point_source);
1265 dt_bauhaus_slider_set(g->black_point_source, p->black_point_source);
1266 dt_bauhaus_slider_set(g->security_factor, p->security_factor);
1267 dt_bauhaus_slider_set(g->white_point_target, p->white_point_target);
1268 dt_bauhaus_slider_set(g->grey_point_target, p->grey_point_target);
1269 dt_bauhaus_slider_set(g->black_point_target, p->black_point_target);
1270 dt_bauhaus_slider_set(g->output_power, p->output_power);
1271 dt_bauhaus_slider_set(g->latitude_stops, p->latitude_stops);
1272 dt_bauhaus_slider_set(g->contrast, p->contrast);
1273 dt_bauhaus_slider_set(g->global_saturation, p->global_saturation);
1274 dt_bauhaus_slider_set(g->saturation, (powf(10.0f, p->saturation/100.0f) - 1.0f) / 9.0f * 100.0f);
1275 dt_bauhaus_slider_set(g->balance, p->balance);
1276
1277 dt_bauhaus_combobox_set(g->interpolator, p->interpolator);
1278 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->preserve_color), p->preserve_color);
1279
1281 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->extra_toggle)));
1282
1283 gtk_widget_queue_draw(self->widget);
1284
1285}
1286
1288{
1289 module->params = calloc(1, sizeof(dt_iop_filmic_params_t));
1290 module->default_params = calloc(1, sizeof(dt_iop_filmic_params_t));
1291 module->default_enabled = 0;
1292 module->params_size = sizeof(dt_iop_filmic_params_t);
1293 module->gui_data = NULL;
1294
1297 .grey_point_source = 18, // source grey
1298 .black_point_source = -8.65, // source black
1299 .white_point_source = 2.45, // source white
1300 .security_factor = 0.0, // security factor
1301 .grey_point_target = 18.0, // target grey
1302 .black_point_target = 0.0, // target black
1303 .white_point_target = 100.0, // target white
1304 .output_power = 2.2, // target power (~ gamma)
1305 .latitude_stops = 2.0, // intent latitude
1306 .contrast = 1.5, // intent contrast
1307 .saturation = 100.0, // intent saturation
1308 .global_saturation = 100.0,
1309 .balance = 0.0, // balance shadows/highlights
1310 .interpolator = CUBIC_SPLINE, //interpolator
1311 .preserve_color = 0, // run the saturated variant
1312 };
1313}
1314
1316{
1317 const int program = 22; // filmic.cl, from programs.conf
1320
1321 module->data = gd;
1322 gd->kernel_filmic = dt_opencl_create_kernel(program, "filmic");
1323}
1324
1326{
1327 dt_free(module->params);
1328 dt_free(module->default_params);
1329}
1330
1337
1339{
1344 CPF_DIRECTION_LEFT, NULL);
1345 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->extra_toggle), FALSE);
1346}
1347
1348static gboolean dt_iop_tonecurve_draw(GtkWidget *widget, cairo_t *crf, gpointer user_data)
1349{
1350 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
1353 dt_iop_filmic_nodes_t *nodes_data = (dt_iop_filmic_nodes_t *)malloc(sizeof(dt_iop_filmic_nodes_t));
1354 compute_curve_lut(p, c->table, c->table_temp, 256, NULL, nodes_data);
1355
1356 const int inset = DT_GUI_CURVE_EDITOR_INSET;
1357 GtkAllocation allocation;
1358 gtk_widget_get_allocation(widget, &allocation);
1359 int width = allocation.width, height = allocation.height;
1360 cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
1361 cairo_t *cr = cairo_create(cst);
1362
1363 // clear bg
1364 cairo_set_source_rgb(cr, .2, .2, .2);
1365 cairo_paint(cr);
1366
1367 cairo_translate(cr, inset, inset);
1368 width -= 2 * inset;
1369 height -= 2 * inset;
1370
1371 cairo_set_source_rgb(cr, .3, .3, .3);
1372 cairo_rectangle(cr, 0, 0, width, height);
1373 cairo_fill(cr);
1374
1375 // draw grid
1376 cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(.4));
1377 cairo_set_source_rgb(cr, .1, .1, .1);
1378 dt_draw_grid(cr, 4, 0, 0, width, height);
1379
1380 // solve the equations for the rescaling parameters
1381 const float DR = (p->white_point_source - p->black_point_source);
1382 const float grey = -p->black_point_source / DR;
1383 int rescale = FALSE;
1384
1385 float a, b, d;
1386 a = DR;
1387 b = Log2( 1.0f / (-1 + powf(2.0f, a)));
1388 d = - powf(2.0f, b);
1389
1390 if (grey > powf(p->grey_point_target / 100.0f, p->output_power))
1391 {
1392 // The x-coordinate rescaling is valid only when the log grey value (dynamic range center)
1393 // is greater or equal to the destination grey value
1394 rescale = TRUE;
1395
1396 for (int i = 0; i < 50; ++i)
1397 { // Optimization loop for the non-linear problem
1398 a = Log2((0.5f - d) / (1.0f - d)) / (grey - 1.0f);
1399 b = Log2( 1.0f / (-1 + powf(2.0f, a)));
1400 d = - powf(2.0f, b);
1401 }
1402 }
1403
1404 const float gamma = (logf(p->grey_point_target / 100.0f) / logf(0.5f)) / p->output_power;
1405
1406 // draw nodes
1407 cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.));
1408 cairo_set_source_rgb(cr, 0.9, 0.9, 0.9);
1409
1410 for(int k = 0; k < nodes_data->nodes; k++)
1411 {
1412 /*
1413 * Use double precision locally to avoid cancellation effect on
1414 * the "+ d" operation.
1415 */
1416 const float x = (rescale) ? powf(2.0f, (double)a * nodes_data->x[k] + b) + d : nodes_data->x[k];
1417 const float y = powf(nodes_data->y[k], 1.0f / gamma);
1418
1419 cairo_arc(cr, x * width, (1.0 - y) * (double)height, DT_PIXEL_APPLY_DPI(3), 0, 2. * M_PI);
1420 cairo_stroke_preserve(cr);
1421 cairo_fill(cr);
1422 cairo_stroke(cr);
1423 }
1424 dt_free(nodes_data);
1425
1426 // draw curve
1427 cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.));
1428 cairo_set_source_rgb(cr, .9, .9, .9);
1429 cairo_move_to(cr, 0, height * (1.0 - c->table[0]));
1430
1431 for(int k = 1; k < 256; k++)
1432 {
1433 /*
1434 * Use double precision locally to avoid cancellation effect on
1435 * the "+ d" operation.
1436 */
1437 const float x = (rescale) ? powf(2.0f, (double)a * k / 255.0f + b) + d : k / 255.0f;
1438 const float y = powf(c->table[k], 1.0f / gamma);
1439 cairo_line_to(cr, x * width, (double)height * (1.0 - y));
1440 }
1441 cairo_stroke(cr);
1442 cairo_destroy(cr);
1443 cairo_set_source_surface(crf, cst, 0, 0);
1444 cairo_paint(crf);
1445 cairo_surface_destroy(cst);
1446 return TRUE;
1447}
1448
1449static void _extra_options_button_changed(GtkDarktableToggleButton *widget, gpointer user_data)
1450{
1451 dt_iop_module_t *self = (dt_iop_module_t *)user_data;
1453 const gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->extra_toggle));
1454 dtgtk_expander_set_expanded(DTGTK_EXPANDER(g->extra_expander), active);
1456 (active ? CPF_DIRECTION_DOWN : CPF_DIRECTION_LEFT), NULL);
1457}
1458
1460{
1463
1464 self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
1465
1466 // read-only graph; modest default height, user-resizable via its grip
1467 g->area = GTK_DRAWING_AREA(gtk_drawing_area_new());
1468 gtk_widget_set_hexpand(GTK_WIDGET(g->area), TRUE);
1469 gtk_widget_set_tooltip_text(GTK_WIDGET(g->area), _("read-only graph, use the parameters below to set the nodes"));
1470 gtk_box_pack_start(GTK_BOX(self->widget),
1471 dt_ui_resizable_drawing_area(GTK_WIDGET(g->area),
1472 "plugins/darkroom/filmic/graphheight", 200, 100),
1473 FALSE, FALSE, 0);
1474 g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(dt_iop_tonecurve_draw), self);
1475
1476 gtk_box_pack_start(GTK_BOX(self->widget), dt_ui_section_label_new(_("logarithmic shaper")), FALSE, FALSE, 0);
1477
1478 // grey_point_source slider
1479 g->grey_point_source = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), 0.0, 100., 0, p->grey_point_source, 2);
1480 dt_bauhaus_slider_set_soft_range(g->grey_point_source, 0.1, 36.0);
1481 dt_bauhaus_widget_set_label(g->grey_point_source, N_("middle gray luminance"));
1482 gtk_box_pack_start(GTK_BOX(self->widget), g->grey_point_source, TRUE, TRUE, 0);
1483 dt_bauhaus_slider_set_format(g->grey_point_source, "%");
1484 gtk_widget_set_tooltip_text(g->grey_point_source, _("adjust to match the average luminance of the subject.\n"
1485 "except in back-lighting situations, this should be around 18%."));
1486 g_signal_connect(G_OBJECT(g->grey_point_source), "value-changed", G_CALLBACK(grey_point_source_callback), self);
1487 dt_color_picker_new(self, DT_COLOR_PICKER_AREA, g->grey_point_source);
1488
1489 // White slider
1490 g->white_point_source = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), 0.0, 16.0, 0, p->white_point_source, 2);
1491 dt_bauhaus_slider_set_soft_range(g->white_point_source, 2.0, 8.0);
1492 dt_bauhaus_widget_set_label(g->white_point_source, N_("white relative exposure"));
1493 gtk_box_pack_start(GTK_BOX(self->widget), g->white_point_source, TRUE, TRUE, 0);
1494 dt_bauhaus_slider_set_format(g->white_point_source, _(" EV"));
1495 gtk_widget_set_tooltip_text(g->white_point_source, _("number of stops between middle gray and pure white.\n"
1496 "this is a reading a lightmeter would give you on the scene.\n"
1497 "adjust so highlights clipping is avoided"));
1498 g_signal_connect(G_OBJECT(g->white_point_source), "value-changed", G_CALLBACK(white_point_source_callback), self);
1499 dt_color_picker_new(self, DT_COLOR_PICKER_AREA, g->white_point_source);
1500
1501 // Black slider
1502 g->black_point_source = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), -16.0, -0.1, 0, p->black_point_source, 2);
1503 dt_bauhaus_slider_set_soft_range(g->black_point_source, -14.0, -3.0);
1504 dt_bauhaus_widget_set_label(g->black_point_source, N_("black relative exposure"));
1505 gtk_box_pack_start(GTK_BOX(self->widget), g->black_point_source, TRUE, TRUE, 0);
1506 dt_bauhaus_slider_set_format(g->black_point_source, _(" EV"));
1507 gtk_widget_set_tooltip_text(g->black_point_source, _("number of stops between middle gray and pure black.\n"
1508 "this is a reading a lightmeter would give you on the scene.\n"
1509 "increase to get more contrast.\ndecrease to recover more details in low-lights."));
1510 g_signal_connect(G_OBJECT(g->black_point_source), "value-changed", G_CALLBACK(black_point_source_callback), self);
1511 dt_color_picker_new(self, DT_COLOR_PICKER_AREA, g->black_point_source);
1512
1513 // Security factor
1514 g->security_factor = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), -50., 50., 0, p->security_factor, 2);
1515 dt_bauhaus_widget_set_label(g->security_factor, N_("safety factor"));
1516 gtk_box_pack_start(GTK_BOX(self->widget), g->security_factor, TRUE, TRUE, 0);
1517 dt_bauhaus_slider_set_format(g->security_factor, "%");
1518 gtk_widget_set_tooltip_text(g->security_factor, _("enlarge or shrink the computed dynamic range.\n"
1519 "useful in conjunction with \"auto tune levels\"."));
1520 g_signal_connect(G_OBJECT(g->security_factor), "value-changed", G_CALLBACK(security_threshold_callback), self);
1521
1522 // Auto tune slider
1524 dt_bauhaus_widget_set_label(g->auto_button, N_("auto tune levels"));
1525 dt_color_picker_new(self, DT_COLOR_PICKER_AREA, g->auto_button);
1526 gtk_widget_set_tooltip_text(g->auto_button, _("try to optimize the settings with some guessing.\n"
1527 "this will fit the luminance range inside the histogram bounds.\n"
1528 "works better for landscapes and evenly-lit pictures\nbut fails for high-keys and low-keys." ));
1529 gtk_box_pack_start(GTK_BOX(self->widget), g->auto_button, TRUE, TRUE, 0);
1530
1531 gtk_box_pack_start(GTK_BOX(self->widget), dt_ui_section_label_new(_("filmic S curve")), FALSE, FALSE, 0);
1532
1533 // contrast slider
1534 g->contrast = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), 0., 5., 0, p->contrast, 3);
1535 dt_bauhaus_slider_set_soft_range(g->contrast, 1.0, 2.0);
1536 dt_bauhaus_widget_set_label(g->contrast, N_("contrast"));
1537 gtk_box_pack_start(GTK_BOX(self->widget), g->contrast, TRUE, TRUE, 0);
1538 gtk_widget_set_tooltip_text(g->contrast, _("slope of the linear part of the curve\n"
1539 "affects mostly the mid-tones"));
1540 g_signal_connect(G_OBJECT(g->contrast), "value-changed", G_CALLBACK(contrast_callback), self);
1541
1542 // latitude slider
1543 g->latitude_stops = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), 0.01, 16.0, 0, p->latitude_stops, 3);
1544 dt_bauhaus_slider_set_soft_range(g->latitude_stops, 2, 8.0);
1545 dt_bauhaus_widget_set_label(g->latitude_stops, N_("latitude"));
1546 dt_bauhaus_slider_set_format(g->latitude_stops, _(" EV"));
1547 gtk_box_pack_start(GTK_BOX(self->widget), g->latitude_stops, TRUE, TRUE, 0);
1548 gtk_widget_set_tooltip_text(g->latitude_stops, _("width of the linear domain in the middle of the curve.\n"
1549 "increase to get more contrast at the extreme luminances.\n"
1550 "this has no effect on mid-tones."));
1551 g_signal_connect(G_OBJECT(g->latitude_stops), "value-changed", G_CALLBACK(latitude_stops_callback), self);
1552
1553 // balance slider
1554 g->balance = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), -50., 50., 0, p->balance, 2);
1555 dt_bauhaus_widget_set_label(g->balance, N_("shadows/highlights balance"));
1556 gtk_box_pack_start(GTK_BOX(self->widget), g->balance, TRUE, TRUE, 0);
1557 dt_bauhaus_slider_set_format(g->balance, "%");
1558 gtk_widget_set_tooltip_text(g->balance, _("slides the latitude along the slope\nto give more room to shadows or highlights.\n"
1559 "use it if you need to protect the details\nat one extremity of the histogram."));
1560 g_signal_connect(G_OBJECT(g->balance), "value-changed", G_CALLBACK(balance_callback), self);
1561
1562 // saturation slider
1563 g->global_saturation = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), 0., 1000., 0, p->global_saturation, 2);
1564 dt_bauhaus_widget_set_label(g->global_saturation, N_("global saturation"));
1565 dt_bauhaus_slider_set_soft_range(g->global_saturation, 0.0, 200.0);
1566 dt_bauhaus_slider_set_format(g->global_saturation, "%");
1567 gtk_box_pack_start(GTK_BOX(self->widget), g->global_saturation, TRUE, TRUE, 0);
1568 gtk_widget_set_tooltip_text(g->global_saturation, _("desaturates the input of the module globally.\n"
1569 "you need to set this value below 100%\nif the chrominance preservation is enabled."));
1570 g_signal_connect(G_OBJECT(g->global_saturation), "value-changed", G_CALLBACK(global_saturation_callback), self);
1571
1572 // saturation slider
1573 g->saturation = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), 0., 1000., 0, (powf(10.0f, p->saturation/100.0f) - 1.0f) / 9.0f *100.0f, 2);
1574 dt_bauhaus_widget_set_label(g->saturation, N_("extreme luminance saturation"));
1575 dt_bauhaus_slider_set_soft_range(g->saturation, 0.0, 200.0);
1576 dt_bauhaus_slider_set_format(g->saturation, "%");
1577 gtk_box_pack_start(GTK_BOX(self->widget), g->saturation, TRUE, TRUE, 0);
1578 gtk_widget_set_tooltip_text(g->saturation, _("desaturates the output of the module\nspecifically at extreme luminances.\n"
1579 "decrease if shadows and/or highlights are over-saturated."));
1580 g_signal_connect(G_OBJECT(g->saturation), "value-changed", G_CALLBACK(saturation_callback), self);
1581
1582 /* From src/common/curve_tools.h :
1583 #define CUBIC_SPLINE 0
1584 #define CATMULL_ROM 1
1585 #define MONOTONE_HERMITE 2
1586 */
1588 dt_bauhaus_widget_set_label(g->interpolator, N_("intent"));
1589 dt_bauhaus_combobox_add(g->interpolator, _("contrasted")); // cubic spline
1590 dt_bauhaus_combobox_add(g->interpolator, _("faded")); // centripetal spline
1591 dt_bauhaus_combobox_add(g->interpolator, _("linear")); // monotonic spline
1592 dt_bauhaus_combobox_add(g->interpolator, _("optimized")); // monotonic spline
1593 gtk_box_pack_start(GTK_BOX(self->widget), g->interpolator , TRUE, TRUE, 0);
1594 gtk_widget_set_tooltip_text(g->interpolator, _("change this method if you see reversed contrast or faded blacks"));
1595 g_signal_connect(G_OBJECT(g->interpolator), "value-changed", G_CALLBACK(interpolator_callback), self);
1596
1597 // Preserve color
1598 g->preserve_color = gtk_check_button_new_with_label(_("preserve the chrominance"));
1599 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(g->preserve_color), p->preserve_color);
1600 gtk_widget_set_tooltip_text(g->preserve_color, _("ensure the original color are preserved.\n"
1601 "may reinforce chromatic aberrations.\n"
1602 "you need to manually tune the saturation when using this mode."));
1603 gtk_box_pack_start(GTK_BOX(self->widget), g->preserve_color , TRUE, TRUE, 0);
1604 g_signal_connect(G_OBJECT(g->preserve_color), "toggled", G_CALLBACK(preserve_color_callback), self);
1605
1606
1607 // add collapsible section for those extra options that are generally not to be used
1608
1609 GtkWidget *destdisp_head = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING);
1610 GtkWidget *destdisp = dt_ui_section_label_new(_("destination/display"));
1612 GtkWidget *extra_options = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
1613 gtk_box_pack_start(GTK_BOX(destdisp_head), destdisp, TRUE, TRUE, 0);
1614 gtk_box_pack_start(GTK_BOX(destdisp_head), g->extra_toggle, FALSE, FALSE, 0);
1615 gtk_widget_set_visible(extra_options, FALSE);
1616 g->extra_expander = dtgtk_expander_new(destdisp_head, extra_options);
1618 gtk_box_pack_start(GTK_BOX(self->widget), g->extra_expander, FALSE, FALSE, 0);
1619
1620
1621 g_signal_connect(G_OBJECT(g->extra_toggle), "toggled", G_CALLBACK(_extra_options_button_changed), (gpointer)self);
1622
1623 // Black slider
1624 g->black_point_target = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), 0.0, 100.0, 0, p->black_point_target, 2);
1625 dt_bauhaus_widget_set_label(g->black_point_target, N_("target black luminance"));
1626 gtk_box_pack_start(GTK_BOX(extra_options), g->black_point_target, FALSE, FALSE, 0);
1627 dt_bauhaus_slider_set_format(g->black_point_target, "%");
1628 gtk_widget_set_tooltip_text(g->black_point_target, _("luminance of output pure black, "
1629 "this should be 0%\nexcept if you want a faded look"));
1630 g_signal_connect(G_OBJECT(g->black_point_target), "value-changed", G_CALLBACK(black_point_target_callback), self);
1631
1632 // grey_point_source slider
1633 g->grey_point_target = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), 0.1, 50., 0, p->grey_point_target, 2);
1634 dt_bauhaus_widget_set_label(g->grey_point_target, N_("target middle gray"));
1635 gtk_box_pack_start(GTK_BOX(extra_options), g->grey_point_target, FALSE, FALSE, 0);
1636 dt_bauhaus_slider_set_format(g->grey_point_target, "%");
1637 gtk_widget_set_tooltip_text(g->grey_point_target, _("middle gray value of the target display or color space.\n"
1638 "you should never touch that unless you know what you are doing."));
1639 g_signal_connect(G_OBJECT(g->grey_point_target), "value-changed", G_CALLBACK(grey_point_target_callback), self);
1640
1641 // White slider
1642 g->white_point_target = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), 0.0, 100.0, 0, p->white_point_target, 2);
1643 dt_bauhaus_widget_set_label(g->white_point_target, N_("target white luminance"));
1644 gtk_box_pack_start(GTK_BOX(extra_options), g->white_point_target, FALSE, FALSE, 0);
1645 dt_bauhaus_slider_set_format(g->white_point_target, "%");
1646 gtk_widget_set_tooltip_text(g->white_point_target, _("luminance of output pure white, "
1647 "this should be 100%\nexcept if you want a faded look"));
1648 g_signal_connect(G_OBJECT(g->white_point_target), "value-changed", G_CALLBACK(white_point_target_callback), self);
1649
1650 // power/gamma slider
1651 g->output_power = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(self), 1.0, 2.4, 0, p->output_power, 2);
1652 dt_bauhaus_widget_set_label(g->output_power, N_("target gamma"));
1653 gtk_box_pack_start(GTK_BOX(extra_options), g->output_power, FALSE, FALSE, 0);
1654 gtk_widget_set_tooltip_text(g->output_power, _("power or gamma of the transfer function\nof the display or color space.\n"
1655 "you should never touch that unless you know what you are doing."));
1656 g_signal_connect(G_OBJECT(g->output_power), "value-changed", G_CALLBACK(output_power_callback), self);
1657}
1658
1659
1660// clang-format off
1661// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1662// vim: shiftwidth=2 expandtab tabstop=2 cindent
1663// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1664// 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_range(GtkWidget *widget, float soft_min, float soft_max)
Definition bauhaus.c:1647
float dt_bauhaus_slider_get(GtkWidget *widget)
Definition bauhaus.c:3483
int dt_bauhaus_combobox_get(GtkWidget *widget)
Definition bauhaus.c:2347
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
Definition bauhaus.c:3506
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
Definition bauhaus.c:2301
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
Definition bauhaus.c:1653
GtkWidget * dt_bauhaus_slider_new_with_range(dt_bauhaus_t *bh, dt_gui_module_t *self, float min, float max, float step, float defval, int digits)
Definition bauhaus.c:1780
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
Definition bauhaus.c:1842
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3598
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
Definition bauhaus.c:2016
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
@ DEVELOP_BLEND_CS_RGB_DISPLAY
Definition blend.h:59
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
@ IOP_CS_LAB
void dt_iop_color_picker_reset(dt_iop_module_t *module, gboolean keep)
GtkWidget * dt_color_picker_new(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w)
@ DT_COLOR_PICKER_AREA
dt_prophotorgb_to_XYZ(rgb, XYZ)
static dt_aligned_pixel_t rgb
dt_Lab_to_XYZ(Lab, XYZ)
dt_XYZ_to_prophotorgb(XYZ, rgb)
static dt_aligned_pixel_t XYZ
const float max
const dt_colormatrix_t dt_aligned_pixel_t out
#define CATMULL_ROM
Definition curve_tools.h:34
#define CUBIC_SPLINE
Definition curve_tools.h:33
#define MONOTONE_HERMITE
Definition curve_tools.h:35
darktable_t darktable
Definition darktable.c:181
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1542
#define dt_free_align(ptr)
Definition darktable.h:481
static void * dt_calloc_align(size_t size)
Definition darktable.h:488
@ DT_DEBUG_OPENCL
Definition darktable.h:722
#define DT_ALIGNED_ARRAY
Definition darktable.h:388
#define dt_free(ptr)
Definition darktable.h:456
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
Definition darktable.h:151
#define __DT_CLONE_TARGETS__
Definition darktable.h:367
#define __OMP_PARALLEL_FOR_SIMD__(...)
Definition darktable.h:259
#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:281
#define dt_dev_add_history_item(dev, module, enable, redraw)
void dt_iop_params_t
Definition dev_history.h:41
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
Definition develop.h:118
static void dt_draw_curve_calc_values(dt_draw_curve_t *c, const float min, const float max, const int res, float *x, float *y)
Definition draw.h:309
static void dt_draw_grid(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom)
Definition draw.h:143
static void dt_draw_curve_destroy(dt_draw_curve_t *c)
Definition draw.h:282
static int dt_draw_curve_add_point(dt_draw_curve_t *c, const float x, const float y)
Definition draw.h:364
static dt_draw_curve_t * dt_draw_curve_new(const float min, const float max, unsigned int type)
Definition draw.h:266
void dtgtk_cairo_paint_solid_arrow(cairo_t *cr, gint x, int y, gint w, gint h, gint flags, void *data)
@ CPF_DIRECTION_LEFT
Definition dtgtk/paint.h:63
@ CPF_DIRECTION_DOWN
Definition dtgtk/paint.h:62
void dtgtk_expander_set_expanded(GtkDarktableExpander *expander, gboolean expanded)
Definition expander.c:70
GtkWidget * dtgtk_expander_new(GtkWidget *header, GtkWidget *body)
Definition expander.c:101
#define DTGTK_EXPANDER(obj)
Definition expander.h:30
static void preserve_color_callback(GtkWidget *widget, dt_iop_module_t *self)
Definition filmic.c:959
void init(dt_iop_module_t *module)
Definition filmic.c:1287
static void white_point_target_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:875
int default_group()
Definition filmic.c:182
void gui_reset(dt_iop_module_t *self)
Definition filmic.c:1338
static void sanitize_latitude(dt_iop_filmic_params_t *p, dt_iop_filmic_gui_data_t *g)
Definition filmic.c:579
static void contrast_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:844
static void interpolator_callback(GtkWidget *widget, dt_iop_module_t *self)
Definition filmic.c:919
static gboolean dt_iop_tonecurve_draw(GtkWidget *widget, cairo_t *crf, gpointer user_data)
Definition filmic.c:1348
static void output_power_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:897
static void latitude_stops_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:828
void gui_update(dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
Definition filmic.c:1255
__DT_CLONE_TARGETS__ int process(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
Definition filmic.c:403
#define DT_GUI_CURVE_EDITOR_INSET
Definition filmic.c:67
static void security_threshold_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:673
static void apply_autotune(dt_iop_module_t *self)
Definition filmic.c:706
void cleanup(dt_iop_module_t *module)
Definition filmic.c:1325
static void balance_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:908
const char * name()
Definition filmic.c:177
void gui_init(dt_iop_module_t *self)
Definition filmic.c:1459
static void grey_point_target_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:817
static void grey_point_source_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:761
void commit_params(dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition filmic.c:1178
static float gaussian(float x, float std)
Definition filmic.c:397
void cleanup_global(dt_iop_module_so_t *module)
Definition filmic.c:1331
static void _extra_options_button_changed(GtkDarktableToggleButton *widget, gpointer user_data)
Definition filmic.c:1449
void cleanup_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition filmic.c:1249
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition filmic.c:197
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 filmic.c:202
int flags()
Definition filmic.c:187
static void apply_auto_white_point_source(dt_iop_module_t *self)
Definition filmic.c:646
static void global_saturation_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:865
void init_presets(dt_iop_module_so_t *self)
Definition filmic.c:302
static void saturation_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:855
static void black_point_target_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:886
void init_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition filmic.c:1243
static void white_point_source_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:785
static void black_point_source_callback(GtkWidget *slider, gpointer user_data)
Definition filmic.c:801
void compute_curve_lut(dt_iop_filmic_params_t *p, float *table, float *table_temp, int res, dt_iop_filmic_data_t *d, dt_iop_filmic_nodes_t *nodes_data)
Definition filmic.c:967
static void apply_auto_black(dt_iop_module_t *self)
Definition filmic.c:618
void init_global(dt_iop_module_so_t *module)
Definition filmic.c:1315
const char * deprecated_msg()
Definition filmic.c:192
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 filmic.c:521
static void apply_auto_grey(dt_iop_module_t *self)
Definition filmic.c:592
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition filmic.c:746
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 filmic.c:210
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)
Definition format.c:57
@ TYPE_FLOAT
Definition format.h:46
GtkWidget * dt_ui_resizable_drawing_area(GtkWidget *area, char *config_str, int default_height, int min_height)
Make a self-drawing widget (typically a GtkDrawingArea graph or scope) vertically resizable.
Definition gtk.c:2836
static cairo_surface_t * dt_cairo_image_surface_create(cairo_format_t format, int width, int height)
Definition gtk.h:316
static GtkWidget * dt_ui_section_label_new(const gchar *str)
Definition gtk.h:451
#define DT_GUI_BOX_SPACING
Definition gtk.h:109
#define DT_PIXEL_APPLY_DPI(value)
Definition gtk.h:90
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)
#define DT_GUI_MODULE(x)
@ IOP_FLAGS_INCLUDE_IN_STYLES
Definition imageop.h:166
@ IOP_FLAGS_DEPRECATED
Definition imageop.h:168
@ IOP_FLAGS_SUPPORTS_BLENDING
Definition imageop.h:167
@ IOP_FLAGS_ALLOW_TILING
Definition imageop.h:169
@ IOP_GROUP_TONES
Definition imageop.h:137
#define IOP_GUI_ALLOC(module)
Definition imageop.h:599
void *const ovoid
static const float x
const float *const const float coeff[3]
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
static float fastlog2(float x)
Definition math.h:122
static float Log2(float x)
Definition math.h:111
static float Log2Thres(float x, float Thres)
Definition math.h:116
#define M_PI
Definition math.h:45
float dt_aligned_pixel_t[4]
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
Definition opencl.c:2136
int dt_opencl_create_kernel(const int prog, const char *name)
Definition opencl.c:2030
void dt_opencl_free_kernel(const int kernel)
Definition opencl.c:2073
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:2127
void * dt_opencl_copy_host_to_device(const int devid, void *host, const int width, const int height, const int bpp)
Definition opencl.c:2347
void dt_opencl_release_mem_object(cl_mem mem)
Definition opencl.c:2383
#define ROUNDUPDHT(a, b)
Definition opencl.h:82
#define ROUNDUPDWD(a, b)
Definition opencl.h:81
struct _GtkWidget GtkWidget
Definition splash.h:29
const float sigma
const float noise
struct dt_gui_gtk_t * gui
Definition darktable.h:775
struct dt_bauhaus_t * bauhaus
Definition darktable.h:778
struct dt_develop_t * develop
Definition darktable.h:770
struct dt_iop_module_t *void * data
int32_t reset
Definition gtk.h:172
unsigned int channels
Definition format.h:54
dt_iop_buffer_type_t datatype
Definition format.h:56
float table_temp[0x10000]
Definition filmic.c:148
float grad_2[0x10000]
Definition filmic.c:149
float global_saturation
Definition filmic.c:155
float table[0x10000]
Definition filmic.c:147
GtkWidget * contrast
Definition filmic.c:132
GtkWidget * saturation
Definition filmic.c:134
GtkWidget * extra_toggle
Definition filmic.c:139
GtkWidget * extra_expander
Definition filmic.c:138
GtkWidget * preserve_color
Definition filmic.c:137
GtkWidget * black_point_target
Definition filmic.c:129
GtkDrawingArea * area
Definition filmic.c:140
GtkWidget * global_saturation
Definition filmic.c:133
GtkWidget * black_point_source
Definition filmic.c:124
GtkWidget * auto_button
Definition filmic.c:126
GtkWidget * output_power
Definition filmic.c:130
float table_temp[256]
Definition filmic.c:142
GtkWidget * white_point_target
Definition filmic.c:128
GtkWidget * grey_point_source
Definition filmic.c:123
GtkWidget * white_point_source
Definition filmic.c:122
GtkWidget * grey_point_target
Definition filmic.c:127
GtkWidget * interpolator
Definition filmic.c:136
GtkWidget * security_factor
Definition filmic.c:125
GtkWidget * latitude_stops
Definition filmic.c:131
GtkWidget * balance
Definition filmic.c:135
GModule *dt_dev_operation_t op
Definition imageop.h:230
dt_iop_global_data_t * data
Definition imageop.h:233
dt_iop_params_t * default_params
Definition imageop.h:307
GtkWidget * widget
Definition imageop.h:337
dt_iop_gui_data_t * gui_data
Definition imageop.h:311
dt_iop_global_data_t * global_data
Definition imageop.h:314
dt_aligned_pixel_t picked_color_min
Definition imageop.h:272
dt_aligned_pixel_t picked_color_max
Definition imageop.h:272
dt_aligned_pixel_t picked_color
Definition imageop.h:272
dt_iop_params_t * params
Definition imageop.h:307
Region of interest passed through the pixelpipe.
Definition imageop.h:72
void dtgtk_togglebutton_set_paint(GtkDarktableToggleButton *button, DTGTKCairoPaintIconFunc paint, gint paintflags, void *paintdata)
GtkWidget * dtgtk_togglebutton_new(DTGTKCairoPaintIconFunc paint, gint paintflags, void *paintdata)
#define DTGTK_TOGGLEBUTTON(obj)