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"
48#endif
49#include "bauhaus/bauhaus.h"
51#include "common/opencl.h"
52#include "control/control.h"
53#include "develop/develop.h"
54#include "develop/imageop.h"
55#include "develop/imageop_gui.h"
56
58#include "gui/gtk.h"
59#include "iop/iop_api.h"
60#ifdef GDK_WINDOWING_QUARTZ
61#include "osx/osx.h"
62#endif
63
64#include <assert.h>
65#include <gtk/gtk.h>
66#include <inttypes.h>
67#include <math.h>
68#include <stdlib.h>
69#include <string.h>
70
72
73// legacy parameters of version 1 of module
81
83{
84 float hue; // $MIN: 0.0 $MAX: 1.0 $DEFAULT: 0.0
85 float saturation; // $MIN: 0.0 $MAX: 1.0 $DEFAULT: 0.5
86 float source_lightness_mix; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 50.0 $DESCRIPTION: "source mix"
87 float lightness; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 50.0
90
92{
93 GtkWidget *lightness, *source_mix; // lightness, source_lightnessmix
94 GtkWidget *hue, *saturation; // hue, saturation
96
98{
99 float L;
100 float a;
101 float b;
102 float mix;
104
105const char *name()
106{
107 return _("colorize");
108}
109
114
116{
117 return IOP_GROUP_COLOR;
118}
119
121{
122 return IOP_CS_LAB;
123}
124
127{
128 default_input_format(self, pipe, piece, dsc);
129 dsc->channels = 4;
130 dsc->datatype = TYPE_FLOAT;
131}
132
133const char **description(struct dt_iop_module_t *self)
134{
135 return dt_iop_set_description(self, _("overlay a solid color on the image"),
136 _("creative"),
137 _("linear or non-linear, Lab, display-referred"),
138 _("non-linear, Lab"),
139 _("non-linear, Lab, display-referred"));
140}
141
142int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version,
143 void *new_params, const int new_version)
144{
145 if(old_version == 1 && new_version == 2)
146 {
147 const dt_iop_colorize_params1_t *old = old_params;
148 dt_iop_colorize_params_t *new = new_params;
149
150 new->hue = old->hue;
151 new->saturation = old->saturation;
152 new->source_lightness_mix = old->source_lightness_mix;
153 new->lightness = old->lightness;
154 new->version = 1;
155 return 0;
156 }
157 return 1;
158}
159
161int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
162 void *const ovoid)
163{
164 const dt_iop_roi_t *const roi_out = &piece->roi_out;
165 float *in, *out;
167 const int ch = 4;
168
169 const float L = d->L;
170 const float a = d->a;
171 const float b = d->b;
172 const float mix = d->mix;
173 const float Lmlmix = L - (mix * 100.0f) / 2.0f;
174 __OMP_PARALLEL_FOR__(private(in, out) )
175 for(int k = 0; k < roi_out->height; k++)
176 {
177
178 const int stride = ch * roi_out->width;
179
180 in = (float *)ivoid + (size_t)k * stride;
181 out = (float *)ovoid + (size_t)k * stride;
182
183 for(int l = 0; l < stride; l += ch)
184 {
185 out[l + 0] = Lmlmix + in[l + 0] * mix;
186 out[l + 1] = a;
187 out[l + 2] = b;
188 out[l + 3] = in[l + 3];
189 }
190 }
191 return 0;
192}
193
194static inline void update_saturation_slider_end_color(GtkWidget *slider, float hue)
195{
197 hsl2rgb(rgb, hue, 1.0, 0.5);
198 dt_bauhaus_slider_set_stop(slider, 1.0, rgb[0], rgb[1], rgb[2]);
199}
200
201void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
202{
205
206 if(w == g->hue)
207 {
208 update_saturation_slider_end_color(g->saturation, p->hue);
209 gtk_widget_queue_draw(g->saturation);
210 }
211}
212
214{
217
218 // convert picker RGB 2 HSL
219 float H = .0f, S = .0f, L = .0f;
224 rgb2hsl(rgb, &H, &S, &L);
225
226 if(fabsf(p->hue - H) < 0.0001f && fabsf(p->saturation - S) < 0.0001f)
227 {
228 // interrupt infinite loops
229 return;
230 }
231
232 p->hue = H;
233 p->saturation = S;
234
236 dt_bauhaus_slider_set(g->hue, p->hue);
237 dt_bauhaus_slider_set(g->saturation, p->saturation);
238 update_saturation_slider_end_color(g->saturation, p->hue);
240
242}
243
244void gui_reset(struct dt_iop_module_t *self)
245{
247}
248
251{
254
255 /* create Lab */
256 dt_aligned_pixel_t rgb = { 0 };
257 dt_aligned_pixel_t XYZ = { 0 };
258 dt_aligned_pixel_t Lab = { 0 };
259 hsl2rgb(rgb, p->hue, p->saturation, p->lightness / 100.0);
260
261 if(p->version == 1)
262 {
263 // the old matrix is a bit off. in fact it's the conversion matrix from AdobeRGB to XYZ@D65
264 XYZ[0] = (rgb[0] * 0.5767309f) + (rgb[1] * 0.1855540f) + (rgb[2] * 0.1881852f);
265 XYZ[1] = (rgb[0] * 0.2973769f) + (rgb[1] * 0.6273491f) + (rgb[2] * 0.0752741f);
266 XYZ[2] = (rgb[0] * 0.0270343f) + (rgb[1] * 0.0706872f) + (rgb[2] * 0.9911085f);
267 }
268 else
269 {
270 // this fits better. conversion matrix from sRGB to XYZ@D50 - which is what dt_XYZ_to_Lab() expects as
271 // input
272 XYZ[0] = (rgb[0] * 0.4360747f) + (rgb[1] * 0.3850649f) + (rgb[2] * 0.1430804f);
273 XYZ[1] = (rgb[0] * 0.2225045f) + (rgb[1] * 0.7168786f) + (rgb[2] * 0.0606169f);
274 XYZ[2] = (rgb[0] * 0.0139322f) + (rgb[1] * 0.0971045f) + (rgb[2] * 0.7141733f);
275 }
276
278
279 /* a/b components */
280 d->L = Lab[0];
281 d->a = Lab[1];
282 d->b = Lab[2];
283 d->mix = p->source_lightness_mix / 100.0f;
284}
285
287{
289 piece->data_size = sizeof(dt_iop_colorize_data_t);
290}
291
293{
294 dt_free_align(piece->data);
295 piece->data = NULL;
296}
297
307
309{
310 dt_iop_default_init(module);
311
312 ((dt_iop_colorize_params_t *)module->default_params)->version = module->version();
313}
314
315void gui_init(struct dt_iop_module_t *self)
316{
318
321 dt_bauhaus_slider_set_factor(g->hue, 360.0f);
322 dt_bauhaus_slider_set_format(g->hue, "\302\260");
323 dt_bauhaus_slider_set_stop(g->hue, 0.0f , 1.0f, 0.0f, 0.0f);
324 dt_bauhaus_slider_set_stop(g->hue, 0.166f, 1.0f, 1.0f, 0.0f);
325 dt_bauhaus_slider_set_stop(g->hue, 0.322f, 0.0f, 1.0f, 0.0f);
326 dt_bauhaus_slider_set_stop(g->hue, 0.498f, 0.0f, 1.0f, 1.0f);
327 dt_bauhaus_slider_set_stop(g->hue, 0.664f, 0.0f, 0.0f, 1.0f);
328 dt_bauhaus_slider_set_stop(g->hue, 0.830f, 1.0f, 0.0f, 1.0f);
329 dt_bauhaus_slider_set_stop(g->hue, 1.0f , 1.0f, 0.0f, 0.0f);
330 gtk_widget_set_tooltip_text(g->hue, _("select the hue tone"));
331
332 g->saturation = dt_bauhaus_slider_from_params(self, N_("saturation"));
333 dt_bauhaus_slider_set_format(g->saturation, "%");
334 dt_bauhaus_slider_set_stop(g->saturation, 0.0f, 0.2f, 0.2f, 0.2f);
335 dt_bauhaus_slider_set_stop(g->saturation, 1.0f, 1.0f, 1.0f, 1.0f);
336 gtk_widget_set_tooltip_text(g->saturation, _("select the saturation shadow tone"));
337
338 g->lightness = dt_bauhaus_slider_from_params(self, N_("lightness"));
339 dt_bauhaus_slider_set_format(g->lightness, "%");
340 gtk_widget_set_tooltip_text(g->lightness, _("lightness of color"));
341
342 g->source_mix = dt_bauhaus_slider_from_params(self, "source_lightness_mix");
343 dt_bauhaus_slider_set_format(g->source_mix, "%");
344 gtk_widget_set_tooltip_text(g->source_mix, _("mix value of source lightness"));
345}
346
347// clang-format off
348// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
349// vim: shiftwidth=2 expandtab tabstop=2 cindent
350// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
351// 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:2372
void dt_bauhaus_slider_set_feedback(GtkWidget *widget, int feedback)
Definition bauhaus.c:3580
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
Definition bauhaus.c:3506
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3598
void dt_bauhaus_slider_set_factor(GtkWidget *widget, float factor)
Definition bauhaus.c:3611
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_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:249
void init(dt_iop_module_t *module)
Definition colorize.c:308
const char ** description(struct dt_iop_module_t *self)
Definition colorize.c:133
int default_group()
Definition colorize.c:115
__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:161
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition colorize.c:286
const char * name()
Definition colorize.c:105
void gui_reset(struct dt_iop_module_t *self)
Definition colorize.c:244
void gui_update(struct dt_iop_module_t *self)
Definition colorize.c:298
void gui_init(struct dt_iop_module_t *self)
Definition colorize.c:315
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
Definition colorize.c:201
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition colorize.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 colorize.c:125
int flags()
Definition colorize.c:110
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition colorize.c:292
static void update_saturation_slider_end_color(GtkWidget *slider, float hue)
Definition colorize.c:194
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:213
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:142
void rgb2hsl(const dt_aligned_pixel_t rgb, float *h, float *s, float *l)
void hsl2rgb(dt_aligned_pixel_t rgb, float h, float s, float l)
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)
darktable_t darktable
Definition darktable.c:181
#define dt_free_align(ptr)
Definition darktable.h:481
static void * dt_calloc_align(size_t size)
Definition darktable.h:488
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
Definition darktable.h:151
#define __DT_CLONE_TARGETS__
Definition darktable.h:367
#define __OMP_PARALLEL_FOR__(...)
Definition darktable.h:258
#define dt_dev_add_history_item(dev, module, enable, redraw)
void dt_iop_params_t
Definition dev_history.h:41
#define H
Definition diffuse.c:613
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
void dt_iop_default_init(dt_iop_module_t *module)
Definition imageop.c:316
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:3141
@ 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_COLOR
Definition imageop.h:139
#define IOP_GUI_ALLOC(module)
Definition imageop.h:599
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
Definition imageop_gui.c:77
void *const ovoid
static float mix(const float a, const float b, const float t)
Definition liquify.c:705
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
float dt_aligned_pixel_t[4]
struct _GtkWidget GtkWidget
Definition splash.h:29
struct dt_gui_gtk_t * gui
Definition darktable.h:775
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
dt_iop_params_t * default_params
Definition imageop.h:307
dt_iop_gui_data_t * gui_data
Definition imageop.h:311
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