Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
velvia.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010 Bernhard Schneider.
4 Copyright (C) 2010-2011 Bruce Guenter.
5 Copyright (C) 2010-2012 Henrik Andersson.
6 Copyright (C) 2010-2013, 2016 johannes hanika.
7 Copyright (C) 2010 Stuart Henderson.
8 Copyright (C) 2011 Antony Dovgal.
9 Copyright (C) 2011 Jérémy Rosen.
10 Copyright (C) 2011 Olivier Tribout.
11 Copyright (C) 2011 Robert Bieber.
12 Copyright (C) 2011 Rostyslav Pidgornyi.
13 Copyright (C) 2011-2014, 2016, 2019 Tobias Ellinghaus.
14 Copyright (C) 2012 Richard Wonka.
15 Copyright (C) 2012, 2014, 2017 Ulrich Pegelow.
16 Copyright (C) 2013 Simon Spannagel.
17 Copyright (C) 2014-2016 Roman Lebedev.
18 Copyright (C) 2015 Pedro Côrte-Real.
19 Copyright (C) 2017 Heiko Bauke.
20 Copyright (C) 2018, 2020, 2022-2023, 2025-2026 Aurélien PIERRE.
21 Copyright (C) 2018 Edgardo Hoszowski.
22 Copyright (C) 2018 Maurizio Paglia.
23 Copyright (C) 2018, 2020, 2022 Pascal Obry.
24 Copyright (C) 2018 rawfiner.
25 Copyright (C) 2019 Andreas Schneider.
26 Copyright (C) 2019 Diederik ter Rahe.
27 Copyright (C) 2020 Aldric Renaudin.
28 Copyright (C) 2020, 2022 Diederik Ter Rahe.
29 Copyright (C) 2020-2021 Hubert Kowalski.
30 Copyright (C) 2020-2021 Ralf Brown.
31 Copyright (C) 2021 Chris Elston.
32 Copyright (C) 2022 Hanno Schwalm.
33 Copyright (C) 2022 Martin Bařinka.
34 Copyright (C) 2022 Philipp Lutz.
35
36 darktable is free software: you can redistribute it and/or modify
37 it under the terms of the GNU General Public License as published by
38 the Free Software Foundation, either version 3 of the License, or
39 (at your option) any later version.
40
41 darktable is distributed in the hope that it will be useful,
42 but WITHOUT ANY WARRANTY; without even the implied warranty of
43 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 GNU General Public License for more details.
45
46 You should have received a copy of the GNU General Public License
47 along with darktable. If not, see <http://www.gnu.org/licenses/>.
48*/
49#ifdef HAVE_CONFIG_H
50#include "config.h"
51#endif
52#include <assert.h>
53#include <math.h>
54#include <stdlib.h>
55#include <string.h>
56
57#include "widgets/bauhaus.h"
60#include "common/imagebuf.h"
61#include "develop/develop.h"
62#include "develop/imageop.h"
64#include "develop/imageop_gui.h"
65
66#include "iop/iop_api.h"
67
68#include <gtk/gtk.h>
69#include <inttypes.h>
70
72
74{
75 float strength; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 25.0
76 float bias; // $MIN: 0.0 $MAX: 1.0 $DEFAULT: 1.0 $DESCRIPTION: "mid-tones bias"
78
79/* legacy version 1 params */
87
94
100
101const char *name()
102{
103 return _("velvia");
104}
105
106const char *aliases()
107{
108 return _("saturation");
109}
110
115
117{
118 return IOP_GROUP_COLOR;
119}
120
122{
123 return IOP_CS_RGB;
124}
125
128{
129 default_input_format(self, pipe, piece, dsc);
130 dsc->channels = 4;
131 dsc->datatype = TYPE_FLOAT;
132}
133
134const char **description(struct dt_iop_module_t *self)
135{
136 return dt_iop_set_description(self, _("resaturate giving more weight to blacks, whites and low-saturation pixels"),
137 _("creative"),
138 _("linear, RGB, scene-referred"),
139 _("linear, RGB"),
140 _("linear, RGB, scene-referred"));
141}
142
143int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version,
144 void *new_params, const int new_version)
145{
146 if(old_version == 1 && new_version == 2)
147 {
148 const dt_iop_velvia_params1_t *old = old_params;
149 dt_iop_velvia_params_t *new = new_params;
150 new->strength = old->saturation * old->vibrance / 100.0f;
151 new->bias = old->luminance;
152 return 0;
153 }
154 return 1;
155}
156
158int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
159 void *const ovoid)
160{
161 const dt_iop_roi_t *const roi_out = &piece->roi_out;
162 const dt_iop_velvia_data_t *const data = (dt_iop_velvia_data_t *)piece->data;
163
164 const size_t ch = 4;
165 const float strength = data->strength / 100.0f;
166
167 // Apply velvia saturation
168 if(strength <= 0.0)
169 dt_iop_image_copy_by_size(ovoid, ivoid, roi_out->width, roi_out->height, ch);
170 else
171 {
173 for(size_t k = 0; k < (size_t)roi_out->width * roi_out->height; k++)
174 {
175 const float *const in = (const float *const)ivoid + ch * k;
176 float *const out = (float *const)ovoid + ch * k;
177
178 // calculate vibrance, and apply boost velvia saturation at least saturated pixels
179 float pmax = MAX(in[0], MAX(in[1], in[2])); // max value in RGB set
180 float pmin = MIN(in[0], MIN(in[1], in[2])); // min value in RGB set
181 float plum = (pmax + pmin) / 2.0f; // pixel luminocity
182 float psat = (plum <= 0.5f) ? (pmax - pmin) / (1e-5f + pmax + pmin)
183 : (pmax - pmin) / (1e-5f + MAX(0.0f, 2.0f - pmax - pmin));
184
185 float pweight
186 = CLAMPS(((1.0f - (1.5f * psat)) + ((1.0f + (fabsf(plum - 0.5f) * 2.0f)) * (1.0f - data->bias)))
187 / (1.0f + (1.0f - data->bias)),
188 0.0f, 1.0f); // The weight of pixel
189 float saturation = strength * pweight; // So lets calculate the final affection of filter on pixel
190
191 // Apply velvia saturation values
192 out[0] = CLAMPS(in[0] + saturation * (in[0] - 0.5f * (in[1] + in[2])), 0.0f, 1.0f);
193 out[1] = CLAMPS(in[1] + saturation * (in[1] - 0.5f * (in[2] + in[0])), 0.0f, 1.0f);
194 out[2] = CLAMPS(in[2] + saturation * (in[2] - 0.5f * (in[0] + in[1])), 0.0f, 1.0f);
195 }
196 }
197
198 if(pipe->mask_display & DT_DEV_PIXELPIPE_DISPLAY_MASK) dt_iop_alpha_copy(ivoid, ovoid, roi_out->width, roi_out->height);
199 return 0;
200}
201
204{
207
208 d->strength = p->strength;
209 d->bias = p->bias;
210}
211
213{
214 piece->data = dt_calloc_align(sizeof(dt_iop_velvia_data_t));
215 piece->data_size = sizeof(dt_iop_velvia_data_t);
216}
217
219{
220 dt_free_align(piece->data);
221 piece->data = NULL;
222}
223
224void gui_update(struct dt_iop_module_t *self)
225{
228 dt_bauhaus_slider_set(g->strength_scale, p->strength);
229 dt_bauhaus_slider_set(g->bias_scale, p->bias);
230}
231
232void gui_init(struct dt_iop_module_t *self)
233{
235
236 g->strength_scale = dt_bauhaus_slider_from_params(self, N_("strength"));
237 dt_bauhaus_slider_set_format(g->strength_scale, "%");
238 gtk_widget_set_tooltip_text(g->strength_scale, _("the strength of saturation boost"));
239
240 g->bias_scale = dt_bauhaus_slider_from_params(self, "bias");
241 gtk_widget_set_tooltip_text(g->bias_scale, _("how much to spare highlights and shadows"));
242}
243
244// clang-format off
245// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
246// vim: shiftwidth=2 expandtab tabstop=2 cindent
247// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
248// clang-format on
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
Definition bauhaus.c:3331
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3407
@ IOP_CS_RGB
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
const dt_colormatrix_t dt_aligned_pixel_t out
static float strength(float value, float strength)
Definition colorzones.c:431
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
Definition develop.h:123
@ TYPE_FLOAT
Definition format.h:56
static void dt_iop_image_copy_by_size(float *const __restrict__ out, const float *const __restrict__ in, const size_t width, const size_t height, const size_t ch)
Definition imagebuf.h:91
const char ** dt_iop_set_description(dt_iop_module_t *module, const char *main_text, const char *purpose, const char *input, const char *process, const char *output)
Definition imageop.c:1893
@ IOP_FLAGS_INCLUDE_IN_STYLES
Definition imageop.h:185
@ IOP_FLAGS_DEPRECATED
Definition imageop.h:187
@ IOP_FLAGS_SUPPORTS_BLENDING
Definition imageop.h:186
@ IOP_FLAGS_ALLOW_TILING
Definition imageop.h:188
@ IOP_GROUP_COLOR
Definition imageop.h:158
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
static dt_iop_gui_data_t * dt_iop_gui_data(const struct dt_iop_module_t *m)
The module's GUI data blob, NULL-safe for headless callers: IOP process() implementations read it for...
Definition imageop_gui.h:81
#define IOP_GUI_ALLOC(module)
Definition imageop_gui.h:93
void *const ovoid
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#define CLAMPS(A, L, H)
Definition math.h:78
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
Definition mem_alloc.h:214
static void * dt_calloc_align(size_t size)
dt_alloc_align() followed by a zero fill.
Definition mem_alloc.h:225
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
#define __OMP_PARALLEL_FOR_SIMD__(...)
Definition openmp.h:96
struct dt_iop_module_t *void * data
unsigned int channels
Definition format.h:83
dt_iop_buffer_type_t datatype
Definition format.h:85
dt_iop_params_t * params
Definition imageop.h:333
Region of interest passed through the pixelpipe.
Definition format.h:49
int width
Definition format.h:50
int height
Definition format.h:50
GtkWidget * bias_scale
Definition velvia.c:92
GtkWidget * strength_scale
Definition velvia.c:91
#define __DT_CLONE_TARGETS__
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition velvia.c:202
const char ** description(struct dt_iop_module_t *self)
Definition velvia.c:134
int default_group()
Definition velvia.c:116
__DT_CLONE_TARGETS__ int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
Definition velvia.c:158
const char * aliases()
Definition velvia.c:106
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition velvia.c:212
const char * name()
Definition velvia.c:101
void gui_update(struct dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
Definition velvia.c:224
void gui_init(struct dt_iop_module_t *self)
Definition velvia.c:232
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition velvia.c:121
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 velvia.c:126
int flags()
Definition velvia.c:111
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition velvia.c:218
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 velvia.c:143