Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
colorize.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011 Henrik Andersson.
4 Copyright (C) 2011-2013, 2016 johannes hanika.
5 Copyright (C) 2011-2012 Jérémy Rosen.
6 Copyright (C) 2011 Robert Bieber.
7 Copyright (C) 2012 Edouard Gomez.
8 Copyright (C) 2012 Richard Wonka.
9 Copyright (C) 2012-2014, 2016-2017, 2019 Tobias Ellinghaus.
10 Copyright (C) 2012-2014 Ulrich Pegelow.
11 Copyright (C) 2013 Dennis Gnad.
12 Copyright (C) 2013-2016 Roman Lebedev.
13 Copyright (C) 2015 Pedro Côrte-Real.
14 Copyright (C) 2017 Heiko Bauke.
15 Copyright (C) 2017 luzpaz.
16 Copyright (C) 2018, 2020, 2022-2023, 2025-2026 Aurélien PIERRE.
17 Copyright (C) 2018-2019 Edgardo Hoszowski.
18 Copyright (C) 2018 Maurizio Paglia.
19 Copyright (C) 2018 parafin.
20 Copyright (C) 2018-2022 Pascal Obry.
21 Copyright (C) 2018 rawfiner.
22 Copyright (C) 2019 Andreas Schneider.
23 Copyright (C) 2019 Diederik ter Rahe.
24 Copyright (C) 2020 Aldric Renaudin.
25 Copyright (C) 2020, 2022 Diederik Ter Rahe.
26 Copyright (C) 2020-2021 Ralf Brown.
27 Copyright (C) 2021 Hubert Kowalski.
28 Copyright (C) 2022 Hanno Schwalm.
29 Copyright (C) 2022 Martin Bařinka.
30 Copyright (C) 2022 Philipp Lutz.
31 Copyright (C) 2023 Luca Zulberti.
32
33 darktable is free software: you can redistribute it and/or modify
34 it under the terms of the GNU General Public License as published by
35 the Free Software Foundation, either version 3 of the License, or
36 (at your option) any later version.
37
38 darktable is distributed in the hope that it will be useful,
39 but WITHOUT ANY WARRANTY; without even the implied warranty of
40 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 GNU General Public License for more details.
42
43 You should have received a copy of the GNU General Public License
44 along with darktable. If not, see <http://www.gnu.org/licenses/>.
45*/
46#ifdef HAVE_CONFIG_H
47#include "config.h"
49#endif
50#include "widgets/bauhaus.h"
51#include "system/openmp.h"
53#include "system/mem_alloc.h"
54#include "system/simd.h"
56#include "develop/develop.h"
57#include "develop/imageop.h"
58#include "develop/imageop_gui.h"
59
61#include "iop/iop_api.h"
62#ifdef GDK_WINDOWING_QUARTZ
63#endif
64
65#include <assert.h>
66#include <gtk/gtk.h>
67#include <inttypes.h>
68#include <math.h>
69#include <stdlib.h>
70#include <string.h>
71
73
74// legacy parameters of version 1 of module
82
84{
85 float hue; // $MIN: 0.0 $MAX: 1.0 $DEFAULT: 0.0
86 float saturation; // $MIN: 0.0 $MAX: 1.0 $DEFAULT: 0.5
87 float source_lightness_mix; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 50.0 $DESCRIPTION: "source mix"
88 float lightness; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 50.0
91
93{
94 GtkWidget *lightness, *source_mix; // lightness, source_lightnessmix
95 GtkWidget *hue, *saturation; // hue, saturation
97
99{
100 float L;
101 float a;
102 float b;
103 float mix;
105
106const char *name()
107{
108 return _("colorize");
109}
110
115
117{
118 return IOP_GROUP_COLOR;
119}
120
122{
123 return IOP_CS_LAB;
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, _("overlay a solid color on the image"),
137 _("creative"),
138 _("linear or non-linear, Lab, display-referred"),
139 _("non-linear, Lab"),
140 _("non-linear, Lab, display-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_colorize_params1_t *old = old_params;
149 dt_iop_colorize_params_t *new = new_params;
150
151 new->hue = old->hue;
152 new->saturation = old->saturation;
153 new->source_lightness_mix = old->source_lightness_mix;
154 new->lightness = old->lightness;
155 new->version = 1;
156 return 0;
157 }
158 return 1;
159}
160
162int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
163 void *const ovoid)
164{
165 const dt_iop_roi_t *const roi_out = &piece->roi_out;
166 float *in, *out;
168 const int ch = 4;
169
170 const float L = d->L;
171 const float a = d->a;
172 const float b = d->b;
173 const float mix = d->mix;
174 const float Lmlmix = L - (mix * 100.0f) / 2.0f;
175 __OMP_PARALLEL_FOR__(private(in, out) )
176 for(int k = 0; k < roi_out->height; k++)
177 {
178
179 const int stride = ch * roi_out->width;
180
181 in = (float *)ivoid + (size_t)k * stride;
182 out = (float *)ovoid + (size_t)k * stride;
183
184 for(int l = 0; l < stride; l += ch)
185 {
186 out[l + 0] = Lmlmix + in[l + 0] * mix;
187 out[l + 1] = a;
188 out[l + 2] = b;
189 out[l + 3] = in[l + 3];
190 }
191 }
192 return 0;
193}
194
195static inline void update_saturation_slider_end_color(GtkWidget *slider, float hue)
196{
198 hsl2rgb(rgb, hue, 1.0, 0.5);
199 dt_bauhaus_slider_set_stop(slider, 1.0, rgb[0], rgb[1], rgb[2]);
200}
201
202void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
203{
206
207 if(w == g->hue)
208 {
209 update_saturation_slider_end_color(g->saturation, p->hue);
210 gtk_widget_queue_draw(g->saturation);
211 }
212}
213
215{
218
219 // convert picker RGB 2 HSL
220 float H = .0f, S = .0f, L = .0f;
225 rgb2hsl(rgb, &H, &S, &L);
226
227 if(fabsf(p->hue - H) < 0.0001f && fabsf(p->saturation - S) < 0.0001f)
228 {
229 // interrupt infinite loops
230 return;
231 }
232
233 p->hue = H;
234 p->saturation = S;
235
237 dt_bauhaus_slider_set(g->hue, p->hue);
238 dt_bauhaus_slider_set(g->saturation, p->saturation);
239 update_saturation_slider_end_color(g->saturation, p->hue);
241
242 dt_dev_add_history_item(self->dev, self, TRUE, TRUE);
243}
244
245void gui_reset(struct dt_iop_module_t *self)
246{
248}
249
252{
255
256 /* create Lab */
257 dt_aligned_pixel_t rgb = { 0 };
258 dt_aligned_pixel_t XYZ = { 0 };
259 dt_aligned_pixel_t Lab = { 0 };
260 hsl2rgb(rgb, p->hue, p->saturation, p->lightness / 100.0);
261
262 if(p->version == 1)
263 {
264 // the old matrix is a bit off. in fact it's the conversion matrix from AdobeRGB to XYZ@D65
265 XYZ[0] = (rgb[0] * 0.5767309f) + (rgb[1] * 0.1855540f) + (rgb[2] * 0.1881852f);
266 XYZ[1] = (rgb[0] * 0.2973769f) + (rgb[1] * 0.6273491f) + (rgb[2] * 0.0752741f);
267 XYZ[2] = (rgb[0] * 0.0270343f) + (rgb[1] * 0.0706872f) + (rgb[2] * 0.9911085f);
268 }
269 else
270 {
271 // this fits better. conversion matrix from sRGB to XYZ@D50 - which is what dt_XYZ_to_Lab() expects as
272 // input
273 XYZ[0] = (rgb[0] * 0.4360747f) + (rgb[1] * 0.3850649f) + (rgb[2] * 0.1430804f);
274 XYZ[1] = (rgb[0] * 0.2225045f) + (rgb[1] * 0.7168786f) + (rgb[2] * 0.0606169f);
275 XYZ[2] = (rgb[0] * 0.0139322f) + (rgb[1] * 0.0971045f) + (rgb[2] * 0.7141733f);
276 }
277
279
280 /* a/b components */
281 d->L = Lab[0];
282 d->a = Lab[1];
283 d->b = Lab[2];
284 d->mix = p->source_lightness_mix / 100.0f;
285}
286
288{
290 piece->data_size = sizeof(dt_iop_colorize_data_t);
291}
292
294{
295 dt_free_align(piece->data);
296 piece->data = NULL;
297}
298
308
310{
311 dt_iop_default_init(module);
312
313 ((dt_iop_colorize_params_t *)module->default_params)->version = module->version();
314}
315
316void gui_init(struct dt_iop_module_t *self)
317{
319
322 dt_bauhaus_slider_set_factor(g->hue, 360.0f);
323 dt_bauhaus_slider_set_format(g->hue, "\302\260");
324 dt_bauhaus_slider_set_stop(g->hue, 0.0f , 1.0f, 0.0f, 0.0f);
325 dt_bauhaus_slider_set_stop(g->hue, 0.166f, 1.0f, 1.0f, 0.0f);
326 dt_bauhaus_slider_set_stop(g->hue, 0.322f, 0.0f, 1.0f, 0.0f);
327 dt_bauhaus_slider_set_stop(g->hue, 0.498f, 0.0f, 1.0f, 1.0f);
328 dt_bauhaus_slider_set_stop(g->hue, 0.664f, 0.0f, 0.0f, 1.0f);
329 dt_bauhaus_slider_set_stop(g->hue, 0.830f, 1.0f, 0.0f, 1.0f);
330 dt_bauhaus_slider_set_stop(g->hue, 1.0f , 1.0f, 0.0f, 0.0f);
331 gtk_widget_set_tooltip_text(g->hue, _("select the hue tone"));
332
333 g->saturation = dt_bauhaus_slider_from_params(self, N_("saturation"));
334 dt_bauhaus_slider_set_format(g->saturation, "%");
335 dt_bauhaus_slider_set_stop(g->saturation, 0.0f, 0.2f, 0.2f, 0.2f);
336 dt_bauhaus_slider_set_stop(g->saturation, 1.0f, 1.0f, 1.0f, 1.0f);
337 gtk_widget_set_tooltip_text(g->saturation, _("select the saturation shadow tone"));
338
339 g->lightness = dt_bauhaus_slider_from_params(self, N_("lightness"));
340 dt_bauhaus_slider_set_format(g->lightness, "%");
341 gtk_widget_set_tooltip_text(g->lightness, _("lightness of color"));
342
343 g->source_mix = dt_bauhaus_slider_from_params(self, "source_lightness_mix");
344 dt_bauhaus_slider_set_format(g->source_mix, "%");
345 gtk_widget_set_tooltip_text(g->source_mix, _("mix value of source lightness"));
346}
347
348// clang-format off
349// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
350// vim: shiftwidth=2 expandtab tabstop=2 cindent
351// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
352// clang-format on
#define TRUE
Definition ashift_lsd.c:162
void dt_bauhaus_slider_set_stop(GtkWidget *widget, float stop, float r, float g, float b)
Definition bauhaus.c:2161
void dt_bauhaus_slider_set_feedback(GtkWidget *widget, int feedback)
Definition bauhaus.c:3389
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
void dt_bauhaus_slider_set_factor(GtkWidget *widget, float factor)
Definition bauhaus.c:3423
@ 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_POINT
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 colorize.c:250
void init(dt_iop_module_t *module)
Definition colorize.c:309
const char ** description(struct dt_iop_module_t *self)
Definition colorize.c:134
int default_group()
Definition colorize.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 colorize.c:162
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition colorize.c:287
const char * name()
Definition colorize.c:106
void gui_reset(struct dt_iop_module_t *self)
Definition colorize.c:245
void gui_update(struct dt_iop_module_t *self)
Definition colorize.c:299
void gui_init(struct dt_iop_module_t *self)
Definition colorize.c:316
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
Definition colorize.c:202
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition colorize.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 colorize.c:126
int flags()
Definition colorize.c:111
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition colorize.c:293
static void update_saturation_slider_end_color(GtkWidget *slider, float hue)
Definition colorize.c:195
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition colorize.c:214
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 colorize.c:143
void rgb2hsl(const dt_aligned_pixel_t rgb, float *h, float *s, float *l)
Convert RGB to HSL. Common helper used by iop modules.
void hsl2rgb(dt_aligned_pixel_t rgb, float h, float s, float l)
Convert HSL back to RGB. Common helper used by iop modules.
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
static dt_aligned_pixel_t rgb
dt_Lab_to_XYZ(Lab, XYZ)
dt_XYZ_to_sRGB(XYZ, result)
static dt_aligned_pixel_t XYZ
static dt_aligned_pixel_t Lab
const dt_colormatrix_t dt_aligned_pixel_t out
dt_XYZ_to_Lab(XYZ, Lab)
#define S(V, params)
#define dt_dev_add_history_item(dev, module, enable, redraw)
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)
#define H
Definition diffuse.c:614
@ TYPE_FLOAT
Definition format.h:56
void dt_iop_default_init(dt_iop_module_t *module)
Definition imageop.c:308
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
static float mix(const float a, const float b, const float t)
Definition liquify.c:751
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#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__(...)
Definition openmp.h:95
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
Definition simd.h:53
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 * default_params
Definition imageop.h:333
struct dt_develop_t * dev
Definition imageop.h:311
dt_aligned_pixel_t picked_color
Definition imageop.h:287
dt_iop_params_t * params
Definition imageop.h:333
Region of interest passed through the pixelpipe.
Definition format.h:49
int width
Definition format.h:50
int height
Definition format.h:50
#define __DT_CLONE_TARGETS__
#define dt_gui_freeze_begin()
#define dt_gui_freeze_end()