Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
develop/iop_profile.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2018-2021, 2023, 2026 Aurélien PIERRE.
4 Copyright (C) 2018-2019 Edgardo Hoszowski.
5 Copyright (C) 2019 Aldric Renaudin.
6 Copyright (C) 2019 Andreas Schneider.
7 Copyright (C) 2019, 2022 Hanno Schwalm.
8 Copyright (C) 2019 Heiko Bauke.
9 Copyright (C) 2019 Jacques Le Clerc.
10 Copyright (C) 2019 jakubfi.
11 Copyright (C) 2019 luzpaz.
12 Copyright (C) 2019-2021 Pascal Obry.
13 Copyright (C) 2019, 2021 Philippe Weyland.
14 Copyright (C) 2019, 2021 Sakari Kapanen.
15 Copyright (C) 2019 Tobias Ellinghaus.
16 Copyright (C) 2020-2021 Dan Torop.
17 Copyright (C) 2020 Harold le Clément de Saint-Marcq.
18 Copyright (C) 2020 Hubert Kowalski.
19 Copyright (C) 2020-2021 Ralf Brown.
20 Copyright (C) 2021 paolodepetrillo.
21 Copyright (C) 2022 Martin Bařinka.
22 Copyright (C) 2022 Philipp Lutz.
23 Copyright (C) 2022 Victor Forsiuk.
24 Copyright (C) 2024 Alynx Zhou.
25
26 darktable is free software: you can redistribute it and/or modify
27 it under the terms of the GNU General Public License as published by
28 the Free Software Foundation, either version 3 of the License, or
29 (at your option) any later version.
30
31 darktable is distributed in the hope that it will be useful,
32 but WITHOUT ANY WARRANTY; without even the implied warranty of
33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 GNU General Public License for more details.
35
36 You should have received a copy of the GNU General Public License
37 along with darktable. If not, see <http://www.gnu.org/licenses/>.
38*/
39#ifdef HAVE_CONFIG_H
40/* The pipeline-facing half of the colour-profile module: resolving which profile a module,
41 * pipe or export should use, and transforming an image with it. Everything here takes
42 * dt_develop_t, dt_dev_pixelpipe_t or dt_iop_module_t, which is why it sits at layer 5.
43 *
44 * The profile maths it delegates to lives in colorprofiles/iop_profile.c -- see the note there.
45 */
46
48#include "config.h"
49#endif
50
53#include "develop/iop_profile.h"
54#include "math/matrices.h"
55#include "develop/imageop.h"
56#include "develop/pixelpipe.h"
57#include "develop/develop.h"
58
59#include <assert.h>
60#include <stdio.h>
61#include <stdlib.h>
62#include <string.h>
64#include "common/times.h"
65
66
67
69
70
72{
74
75 // first check if the module is between colorin and colorout
76 gboolean in_between = FALSE;
77
78 for(GList *modules = iop_list; modules; modules = g_list_next(modules))
79 {
81
82 // we reach the module, that's it
83 if(strcmp(mod->op, module->op) == 0) break;
84
85 // if we reach colorout means that the module is after it
86 if(strcmp(mod->op, "colorout") == 0)
87 {
89 break;
90 }
91
92 // we reach colorin, so far we're good
93 if(strcmp(mod->op, "colorin") == 0)
94 {
96 break;
97 }
98 }
99
100 if(in_between)
101 {
103 const char *filename = NULL;
104 dt_develop_t *dev = module->dev;
105
106 dt_ioppr_get_work_profile_type(dev, &type, &filename);
107 if(filename) profile = dt_colorspaces_add_profile(type, filename, DT_INTENT_PERCEPTUAL);
108 }
109
110 return profile;
111}
112
115 struct dt_dev_pixelpipe_t *pipe,
117 const char *filename,
118 const int intent)
119{
121
122 if(IS_NULL_PTR(profile_info) || isnan(profile_info->matrix_in[0][0]) || isnan(profile_info->matrix_out[0][0]))
123 {
124 fprintf(stderr, "[dt_ioppr_set_pipe_work_profile_info] unsupported working profile %i %s, it will be replaced with linear Rec2020\n", type, filename);
126 }
128
129 return profile_info;
130}
131
134 struct dt_dev_pixelpipe_t *pipe,
136 const char *filename,
137 const int intent,
138 const dt_colormatrix_t matrix_in)
139{
141
142 /* An image-derived profile cannot be shared, and cannot be resolved by identity either:
143 * these types are not registered in the profile list, so the memo entry for them is a
144 * placeholder with NaN matrices that only becomes real when the matrix colorin computed
145 * FROM THIS IMAGE is written into it below. Keyed on (type, "") that entry is common to
146 * every image of the same camera-matrix kind. Give it storage the pipe owns instead. */
148
149 if(image_derived)
150 {
152 {
156 }
158
160 {
162 g_strlcpy(profile_info->filename, filename, sizeof(profile_info->filename));
163 profile_info->intent = intent;
164 profile_info->nonlinearlut = 0;
165 profile_info->grey = 0.1842f;
166 }
167 }
168 else
169 {
170 profile_info = dt_colorspaces_add_profile(type, filename, intent);
171 }
172
174 {
176 "[dt_ioppr_set_pipe_input_profile_info] unsupported input profile %i %s, it will be replaced with "
177 "linear Rec2020\n",
178 type, filename);
180 }
181 else if(image_derived)
182 {
183 /* We have a camera input matrix, these are not generated from files but in colorin,
184 * so we need to fetch and replace them from somewhere.
185 */
186 memcpy(profile_info->matrix_in, matrix_in, sizeof(profile_info->matrix_in));
187 mat3SSEinv(profile_info->matrix_out, profile_info->matrix_in);
188 transpose_3xSSE(profile_info->matrix_in, profile_info->matrix_in_transposed);
189 transpose_3xSSE(profile_info->matrix_out, profile_info->matrix_out_transposed);
190 }
192
193 return profile_info;
194}
195
198 struct dt_dev_pixelpipe_t *pipe,
200 const char *filename,
201 const int intent)
202{
204
205 if(IS_NULL_PTR(profile_info) || isnan(profile_info->matrix_in[0][0]) || isnan(profile_info->matrix_out[0][0]))
206 {
208 {
209 // ??? this error output has been disabled for a display profile.
210 // see discussion in https://github.com/darktable-org/darktable/issues/6774
212 "[dt_ioppr_set_pipe_output_profile_info] unsupported output"
213 " profile %i %s, it will be replaced with sRGB\n",
214 type, filename);
215 }
217 }
219
220 return profile_info;
221}
222
227
232
237
239{
240 if(module->iop_order < dt_ioppr_get_iop_order(module->dev->iop_order_list, "colorin", 0))
242 if(module->iop_order < dt_ioppr_get_iop_order(module->dev->iop_order_list, "colorout", 0))
245}
246
260
261// returns a pointer to the filename of the work profile instead of the actual string data
262// pointer must not be stored
265 const char **profile_filename)
266{
269
270 // use introspection to get the params values
274 {
276 if(!strcmp(module_so->op, "colorin"))
277 {
279 break;
280 }
281 }
282 if(colorin_so && colorin_so->get_p)
283 {
284 for(const GList *modules = dev->iop; modules; modules = g_list_next(modules))
285 {
286 dt_iop_module_t *module = (dt_iop_module_t *)(modules->data);
287 if(!strcmp(module->op, "colorin"))
288 {
289 colorin = module;
290 break;
291 }
292 }
293 }
294 if(colorin)
295 {
296 dt_colorspaces_color_profile_type_t *_type = colorin_so->get_p(colorin->params, "type_work");
297 char *_filename = colorin_so->get_p(colorin->params, "filename_work");
298 if(_type && _filename)
299 {
302 }
303 else
304 fprintf(stderr, "[dt_ioppr_get_work_profile_type] can't get colorin parameters\n");
305 }
306 else
307 fprintf(stderr, "[dt_ioppr_get_work_profile_type] can't find colorin iop\n");
308}
309
312 const char **profile_filename)
313{
316
317 // use introspection to get the params values
321 {
323 if(!strcmp(module_so->op, "colorout"))
324 {
326 break;
327 }
328 }
329 if(colorout_so && colorout_so->get_p)
330 {
332 {
333 dt_iop_module_t *module = (dt_iop_module_t *)(modules->data);
334 if(!strcmp(module->op, "colorout"))
335 {
336 colorout = module;
337 break;
338 }
339 }
340 }
341 if(colorout)
342 {
344 char *_filename = colorout_so->get_p(colorout->params, "filename");
345 if(_type && _filename)
346 {
349 }
350 else
351 fprintf(stderr, "[dt_ioppr_get_export_profile_type] can't get colorout parameters\n");
352 }
353 else
354 fprintf(stderr, "[dt_ioppr_get_export_profile_type] can't find colorout iop\n");
355}
356
357
358
359#undef DT_IOP_ORDER_PROFILE
360// clang-format off
361// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
362// vim: shiftwidth=2 expandtab tabstop=2 cindent
363// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
364// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
dt_iop_order_iccprofile_info_t * dt_colorspaces_add_profile(const dt_colorspaces_color_profile_type_t profile_type, const char *profile_filename, const int intent)
Find-or-build the derived matrix/LUT data for a profile identity, memoised.
__DT_CLONE_TARGETS__ void dt_ioppr_init_profile_info(dt_iop_order_iccprofile_info_t *profile_info, const int lutsize)
Put a freshly allocated dt_iop_order_iccprofile_info_t into its empty state – must be called before u...
The colour-profile struct and the maths over it: the derived matrix/LUT engine.
The colour-profile module's API: which profiles exist, and how to apply one.
GList * dt_iop_get_modules_so(void)
Definition darktable.c:533
void * dt_alloc_align(size_t size)
Allocate cacheline-aligned memory.
Definition darktable.c:508
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_output_profile_info(const struct dt_dev_pixelpipe_t *pipe)
void dt_ioppr_get_work_profile_type(struct dt_develop_t *dev, dt_colorspaces_color_profile_type_t *profile_type, const char **profile_filename)
dt_ioppr_profile_stage_t dt_ioppr_get_module_profile_stage(const dt_iop_module_t *module)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_work_profile_info(const struct dt_dev_pixelpipe_t *pipe)
dt_iop_order_iccprofile_info_t * dt_ioppr_set_pipe_work_profile_info(struct dt_develop_t *dev, struct dt_dev_pixelpipe_t *pipe, const dt_colorspaces_color_profile_type_t type, const char *filename, const int intent)
dt_iop_order_iccprofile_info_t * dt_ioppr_set_pipe_output_profile_info(struct dt_develop_t *dev, struct dt_dev_pixelpipe_t *pipe, const dt_colorspaces_color_profile_type_t type, const char *filename, const int intent)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_current_profile_info(dt_iop_module_t *module, const struct dt_dev_pixelpipe_t *pipe)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_input_profile_info(const struct dt_dev_pixelpipe_t *pipe)
dt_iop_order_iccprofile_info_t * dt_ioppr_set_pipe_input_profile_info(struct dt_develop_t *dev, struct dt_dev_pixelpipe_t *pipe, const dt_colorspaces_color_profile_type_t type, const char *filename, const int intent, const dt_colormatrix_t matrix_in)
__DT_CLONE_TARGETS__ dt_iop_order_iccprofile_info_t * dt_ioppr_get_iop_work_profile_info(struct dt_iop_module_t *module, GList *iop_list)
void dt_ioppr_get_export_profile_type(struct dt_develop_t *dev, dt_colorspaces_color_profile_type_t *profile_type, const char **profile_filename)
dt_ioppr_profile_stage_t
@ DT_IOPPR_PROFILE_STAGE_INPUT
@ DT_IOPPR_PROFILE_STAGE_WORK
@ DT_IOPPR_PROFILE_STAGE_OUTPUT
int dt_ioppr_get_iop_order(GList *iop_order_list, const char *op_name, const int multi_priority)
Return the iop_order for a given operation/instance pair.
Definition iop_order.c:913
static const dt_dev_pixelpipe_t * pipe
Definition layers.h:49
_lib_location_type_t type
Definition location.c:1
#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 macros.h:96
float DT_ALIGNED_ARRAY dt_colormatrix_t[4][4]
Definition matrices.h:34
static void transpose_3xSSE(const dt_colormatrix_t input, dt_colormatrix_t output)
Definition matrices.h:69
static int mat3SSEinv(dt_colormatrix_t dst, const dt_colormatrix_t src)
Definition matrices.h:37
@ DT_INTENT_PERCEPTUAL
dt_colorspaces_color_profile_type_t
@ DT_COLORSPACE_EMBEDDED_ICC
Image-derived profiles: enum 9..14, NOT registered in the list.
@ DT_COLORSPACE_DISPLAY
The monitor profile – the one list entry that mutates after init.
@ DT_COLORSPACE_SRGB
sRGB – registered TWICE, and the two entries are not interchangeable.
@ DT_COLORSPACE_NONE
No profile / "take it from the image settings". Never matches a list entry.
@ DT_COLORSPACE_LIN_REC2020
@ DT_COLORSPACE_ALTERNATE_MATRIX
struct dt_iop_order_iccprofile_info_t * work_profile_info
struct dt_iop_order_iccprofile_info_t * input_profile_info
struct dt_iop_order_iccprofile_info_t * output_profile_info
struct dt_iop_order_iccprofile_info_t * owned_input_profile_info
GList * iop
Definition develop.h:269
A profile reduced to the arithmetic the pixel loop can run: two matrices and six tone-curve LUTs,...
dt_colorspaces_color_profile_type_t type
Profile identity, half of the memo key. DT_COLORSPACE_NONE means "unset" and makes every apply functi...
#define __DT_CLONE_TARGETS__