Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
invert.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011, 2014 Henrik Andersson.
4 Copyright (C) 2011-2013, 2016 johannes hanika.
5 Copyright (C) 2011 Robert Bieber.
6 Copyright (C) 2011-2014, 2016, 2018-2019 Tobias Ellinghaus.
7 Copyright (C) 2012 parafin.
8 Copyright (C) 2012 Richard Wonka.
9 Copyright (C) 2013, 2020 Aldric Renaudin.
10 Copyright (C) 2013 Dennis Gnad.
11 Copyright (C) 2013-2016 Roman Lebedev.
12 Copyright (C) 2013-2014, 2016-2017 Ulrich Pegelow.
13 Copyright (C) 2014 Dan Torop.
14 Copyright (C) 2015-2016 Pedro Côrte-Real.
15 Copyright (C) 2018-2020, 2023, 2025-2026 Aurélien PIERRE.
16 Copyright (C) 2018-2019 Edgardo Hoszowski.
17 Copyright (C) 2018 Kelvie Wong.
18 Copyright (C) 2018 Maurizio Paglia.
19 Copyright (C) 2018-2022 Pascal Obry.
20 Copyright (C) 2018 rawfiner.
21 Copyright (C) 2019 Andreas Schneider.
22 Copyright (C) 2019-2020, 2022 Diederik Ter Rahe.
23 Copyright (C) 2019, 2022 Hanno Schwalm.
24 Copyright (C) 2020 Hubert Kowalski.
25 Copyright (C) 2020-2021 Ralf Brown.
26 Copyright (C) 2021 Chris Elston.
27 Copyright (C) 2022 Martin Bařinka.
28 Copyright (C) 2022 Philipp Lutz.
29
30 darktable is free software: you can redistribute it and/or modify
31 it under the terms of the GNU General Public License as published by
32 the Free Software Foundation, either version 3 of the License, or
33 (at your option) any later version.
34
35 darktable is distributed in the hope that it will be useful,
36 but WITHOUT ANY WARRANTY; without even the implied warranty of
37 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 GNU General Public License for more details.
39
40 You should have received a copy of the GNU General Public License
41 along with darktable. If not, see <http://www.gnu.org/licenses/>.
42*/
43
44#ifdef HAVE_CONFIG_H
45#include "config.h"
46#endif
47#include <gtk/gtk.h>
48#include <stdlib.h>
49
50#include "common/colorspaces.h"
51#include "control/control.h"
52#include "develop/imageop.h"
54#include "dtgtk/button.h"
55#include "dtgtk/resetlabel.h"
57
58#include "gui/gtk.h"
59#include "iop/iop_api.h"
60
62
64{
65 float color[4]; // $DEFAULT: 1.0 color of film material
67
77
79{
80 float color[4]; // color of film material
82
83int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params,
84 const int new_version)
85{
86 if(old_version == 1 && new_version == 2)
87 {
88 typedef struct dt_iop_invert_params_v1_t
89 {
90 float color[3]; // color of film material
91 } dt_iop_invert_params_v1_t;
92
93 dt_iop_invert_params_v1_t *o = (dt_iop_invert_params_v1_t *)old_params;
95
96 n->color[0] = o->color[0];
97 n->color[1] = o->color[1];
98 n->color[2] = o->color[2];
99 n->color[3] = NAN;
100
101 if(self->dev && self->dev->image_storage.flags & DT_IMAGE_4BAYER)
102 {
103 double RGB_to_CAM[4][3];
104
105 // Get and store the matrix to go from camera to RGB for 4Bayer images (used for spot WB)
107 RGB_to_CAM, NULL,
108 self->dev->image_storage.d65_color_matrix, NULL))
109 {
110 const char *camera = self->dev->image_storage.camera_makermodel;
111 fprintf(stderr, "[invert] `%s' color matrix not found for 4bayer image\n", camera);
112 dt_control_log(_("`%s' color matrix not found for 4bayer image"), camera);
113 }
114 else
115 {
116 dt_colorspaces_rgb_to_cygm(n->color, 1, RGB_to_CAM);
117 }
118 }
119
120 return 0;
121 }
122 return 1;
123}
124
125
126const char *name()
127{
128 return _("invert");
129}
130
131const char *deprecated_msg()
132{
133 return _("this module is deprecated. please use the negadoctor module instead.");
134}
135
136const char **description(struct dt_iop_module_t *self)
137{
138 return dt_iop_set_description(self, _("invert film negatives"),
139 _("corrective"),
140 _("linear, raw, display-referred"),
141 _("linear, raw"),
142 _("linear, raw, display-referred"));
143}
144
145
147{
148 return IOP_GROUP_FILM;
149}
150
155
157{
158 return IOP_CS_RAW;
159}
160
163{
164 default_output_format(self, pipe, piece, dsc);
165}
166
168{
171
172 GdkRGBA color = (GdkRGBA){.red = p->color[0], .green = p->color[1], .blue = p->color[2], .alpha = 1.0 };
173
174 const dt_image_t *img = &self->dev->image_storage;
175 if(img->flags & DT_IMAGE_4BAYER)
176 {
178 for_four_channels(k) rgb[k] = p->color[k];
179
180 dt_colorspaces_cygm_to_rgb(rgb, 1, g->CAM_to_RGB);
181
182 color.red = rgb[0];
183 color.green = rgb[1];
184 color.blue = rgb[2];
185 }
186
187 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(g->colorpicker), &color);
188}
189
191{
192 static dt_aligned_pixel_t old = { 0.0f, 0.0f, 0.0f, 0.0f };
193
194 const float *grayrgb = self->picked_color;
195
196 if(grayrgb[0] == old[0] && grayrgb[1] == old[1] && grayrgb[2] == old[2] && grayrgb[3] == old[3]) return;
197
198 for_four_channels(k) old[k] = grayrgb[k];
199
201 for_four_channels(k) p->color[k] = grayrgb[k];
202
206
209}
210
211static void colorpicker_callback(GtkColorButton *widget, dt_iop_module_t *self)
212{
213 if(darktable.gui->reset) return;
216
218
219 GdkRGBA c;
220 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget), &c);
221 p->color[0] = c.red;
222 p->color[1] = c.green;
223 p->color[2] = c.blue;
224
225 const dt_image_t *img = &self->dev->image_storage;
226 if(img->flags & DT_IMAGE_4BAYER)
227 {
228 dt_colorspaces_rgb_to_cygm(p->color, 1, g->RGB_to_CAM);
229 }
230 else if(dt_image_is_monochrome(img))
231 { // Just to make sure the monochrome stays monochrome we take the luminosity of the chosen color on all channels
232 p->color[0] = p->color[1] = p->color[2] = 0.21f*c.red + 0.72f*c.green + 0.07f*c.blue ;
233 }
235}
236
238int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
239 void *const ovoid)
240{
241 const dt_iop_roi_t *const roi_out = &piece->roi_out;
242 const dt_iop_invert_data_t *const d = (dt_iop_invert_data_t *)piece->data;
243
244 const float *const m = piece->dsc_in.processed_maximum;
245
246 const dt_aligned_pixel_t film_rgb_f
247 = { d->color[0] * m[0], d->color[1] * m[1], d->color[2] * m[2], d->color[3] * m[3] };
248
249 // FIXME: it could be wise to make this a NOP when picking colors. not sure about that though.
250 // if(self->request_color_pick){
251 // do nothing
252 // }
253
254 const uint32_t filters = piece->dsc_in.filters;
255 const uint8_t(*const xtrans)[6] = (const uint8_t(*const)[6])piece->dsc_in.xtrans;
256
257 const float *const in = (const float *const)ivoid;
258 float *const out = (float *const)ovoid;
259
260 if(filters == 9u)
261 { // xtrans float mosaiced
262 __OMP_PARALLEL_FOR_SIMD__(collapse(2))
263 for(int j = 0; j < roi_out->height; j++)
264 {
265 for(int i = 0; i < roi_out->width; i++)
266 {
267 const size_t p = (size_t)j * roi_out->width + i;
268 out[p] = CLAMP(film_rgb_f[FCxtrans(j, i, roi_out, xtrans)] - in[p], 0.0f, 1.0f);
269 }
270 }
271 }
272 else if(filters)
273 { // bayer float mosaiced
274 __OMP_PARALLEL_FOR_SIMD__(collapse(2))
275 for(int j = 0; j < roi_out->height; j++)
276 {
277 for(int i = 0; i < roi_out->width; i++)
278 {
279 const size_t p = (size_t)j * roi_out->width + i;
280 out[p] = CLAMP(film_rgb_f[FC(j + roi_out->y, i + roi_out->x, filters)] - in[p], 0.0f, 1.0f);
281 }
282 }
283 }
284 else
285 { // non-mosaiced
286 const int ch = piece->dsc_in.channels;
287 __OMP_PARALLEL_FOR_SIMD__(collapse(2))
288 for(size_t k = 0; k < (size_t)ch * roi_out->width * roi_out->height; k += ch)
289 {
290 for(int c = 0; c < 3; c++)
291 {
292 const size_t p = (size_t)k + c;
293 out[p] = d->color[c] - in[p];
294 }
295 }
296
297 if(pipe->mask_display & DT_DEV_PIXELPIPE_DISPLAY_MASK) dt_iop_alpha_copy(ivoid, ovoid, roi_out->width, roi_out->height);
298 }
299 return 0;
300}
301
303{
305
306 if (!IS_NULL_PTR(g))
307 {
309 {
310 // Here we could provide more for monochrome special cases. As no monochrome camera
311 // has a bayer sensor we don't need g->RGB_to_CAM and g->CAM_to_RGB corrections
312 dtgtk_reset_label_set_text(g->label, _("brightness of film material"));
313 }
314 else
315 {
316 dtgtk_reset_label_set_text(g->label, _("color of film material"));
317
319 {
320 // Get and store the matrix to go from camera to RGB for 4Bayer images (used for spot WB)
322 g->RGB_to_CAM, g->CAM_to_RGB,
323 self->dev->image_storage.d65_color_matrix, NULL))
324 {
325 const char *camera = self->dev->image_storage.camera_makermodel;
326 fprintf(stderr, "[invert] `%s' color matrix not found for 4bayer image\n", camera);
327 dt_control_log(_("`%s' color matrix not found for 4bayer image"), camera);
328 }
329 }
330 }
331 }
332}
333
334
337{
340
341 for(int k = 0; k < 4; k++) d->color[k] = p->color[k];
342
343 // x-trans images not implemented in OpenCL yet
344 if(pipe->dev->image_storage.dsc.filters == 9u) piece->process_cl_ready = 0;
345
346 // 4Bayer images not implemented in OpenCL yet
348
349 if(self->hide_enable_button) piece->enabled = 0;
350
351 if(piece->dsc_in.filters)
352 for(int k = 0; k < 4; k++) piece->dsc_out.processed_maximum[k] = 1.0f;
353}
354
356{
357 piece->data = dt_calloc_align(sizeof(dt_iop_invert_data_t));
358 piece->data_size = sizeof(dt_iop_invert_data_t);
359}
360
362{
363 dt_free_align(piece->data);
364 piece->data = NULL;
365}
366
368{
370}
371
373{
376
377 self->widget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING);
378 g->label = DTGTK_RESET_LABEL(dtgtk_reset_label_new("", self, &p->color, sizeof(float) * 4));
379 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->label), TRUE, TRUE, 0);
380
381 g->pickerbuttons = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING));
382 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->pickerbuttons), TRUE, TRUE, 0);
383
384 GdkRGBA color = (GdkRGBA){.red = p->color[0], .green = p->color[1], .blue = p->color[2], .alpha = 1.0 };
385 g->colorpicker = gtk_color_button_new_with_rgba(&color);
386 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(g->colorpicker), FALSE);
387 gtk_color_button_set_title(GTK_COLOR_BUTTON(g->colorpicker), _("select color of film material"));
388 g_signal_connect(G_OBJECT(g->colorpicker), "color-set", G_CALLBACK(colorpicker_callback), self);
389 gtk_box_pack_start(GTK_BOX(g->pickerbuttons), GTK_WIDGET(g->colorpicker), TRUE, TRUE, 0);
390
391 g->picker = dt_color_picker_new(self, DT_COLOR_PICKER_AREA, GTK_WIDGET(g->pickerbuttons));
392}
393
394// clang-format off
395// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
396// vim: shiftwidth=2 expandtab tabstop=2 cindent
397// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
398// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
#define m
Definition basecurve.c:278
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
@ IOP_CS_RAW
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_CLONE_TARGETS__ int dt_colorspaces_conversion_matrices_rgb(const float adobe_XYZ_to_CAM[4][3], double out_RGB_to_CAM[4][3], double out_CAM_to_RGB[3][4], const float *embedded_matrix, double mul[4])
void dt_colorspaces_rgb_to_cygm(float *out, int num, double RGB_to_CAM[4][3])
__DT_CLONE_TARGETS__ void dt_colorspaces_cygm_to_rgb(float *out, int num, double CAM_to_RGB[3][4])
static dt_aligned_pixel_t rgb
const dt_colormatrix_t dt_aligned_pixel_t out
gboolean dt_image_is_monochrome(const dt_image_t *img)
void dt_control_log(const char *msg,...)
Definition control.c:761
void dt_control_queue_redraw_widget(GtkWidget *widget)
threadsafe request of redraw of specific widget. Use this function if you need to redraw a specific w...
Definition control.c:906
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 for_four_channels(_var,...)
Definition darktable.h:664
#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
static int FCxtrans(const int row, const int col, global const unsigned char(*const xtrans)[6])
static int FC(const int row, const int col, const unsigned int filters)
#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
void default_output_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
Definition format.c:75
#define DT_GUI_BOX_SPACING
Definition gtk.h:109
@ DT_IMAGE_4BAYER
Definition image.h:127
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_DEPRECATED
Definition imageop.h:168
@ IOP_FLAGS_ONE_INSTANCE
Definition imageop.h:172
@ IOP_GROUP_FILM
Definition imageop.h:138
#define IOP_GUI_ALLOC(module)
Definition imageop.h:599
void *const ovoid
const char ** description(struct dt_iop_module_t *self)
Definition invert.c:136
int default_group()
Definition invert.c:146
static void gui_update_from_coeffs(dt_iop_module_t *self)
Definition invert.c:167
__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 invert.c:238
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *params, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition invert.c:335
void gui_update(dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
Definition invert.c:367
static void colorpicker_callback(GtkColorButton *widget, dt_iop_module_t *self)
Definition invert.c:211
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition invert.c:355
const char * name()
Definition invert.c:126
void output_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
Definition invert.c:161
void gui_init(dt_iop_module_t *self)
Definition invert.c:372
void reload_defaults(dt_iop_module_t *self)
Definition invert.c:302
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition invert.c:156
int flags()
Definition invert.c:151
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition invert.c:361
const char * deprecated_msg()
Definition invert.c:131
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition invert.c:190
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 invert.c:83
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
float dt_aligned_pixel_t[4]
GtkWidget * dtgtk_reset_label_new(const gchar *text, dt_iop_module_t *module, void *param, int param_size)
Definition resetlabel.c:58
void dtgtk_reset_label_set_text(GtkDarktableResetLabel *label, const gchar *str)
Definition resetlabel.c:96
#define DTGTK_RESET_LABEL(obj)
Definition resetlabel.h:30
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
dt_iop_buffer_dsc_t dsc_out
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
struct dt_develop_t * dev
dt_image_t image_storage
Definition develop.h:259
int32_t reset
Definition gtk.h:172
char camera_makermodel[128]
Definition image.h:300
int32_t flags
Definition image.h:319
float d65_color_matrix[9]
Definition image.h:339
dt_iop_buffer_dsc_t dsc
Definition image.h:337
float adobe_XYZ_to_CAM[4][3]
Definition image.h:362
uint32_t filters
Definition format.h:60
unsigned int channels
Definition format.h:54
uint8_t xtrans[6][6]
Definition format.h:70
dt_aligned_pixel_t processed_maximum
Definition format.h:85
double RGB_to_CAM[4][3]
Definition invert.c:74
double CAM_to_RGB[3][4]
Definition invert.c:75
GtkWidget * picker
Definition invert.c:73
GtkWidget * colorpicker
Definition invert.c:70
GtkDarktableResetLabel * label
Definition invert.c:71
int32_t hide_enable_button
Definition imageop.h:262
GtkWidget * widget
Definition imageop.h:337
struct dt_develop_t * dev
Definition imageop.h:296
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