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
256
257// returns a pointer to the filename of the work profile instead of the actual string data
258// pointer must not be stored
261 const char **profile_filename)
262{
265
266 // use introspection to get the params values
270 {
272 if(!strcmp(module_so->op, "colorin"))
273 {
275 break;
276 }
277 }
278 if(colorin_so && colorin_so->get_p)
279 {
280 for(const GList *modules = dev->iop; modules; modules = g_list_next(modules))
281 {
282 dt_iop_module_t *module = (dt_iop_module_t *)(modules->data);
283 if(!strcmp(module->op, "colorin"))
284 {
285 colorin = module;
286 break;
287 }
288 }
289 }
290 if(colorin)
291 {
292 dt_colorspaces_color_profile_type_t *_type = colorin_so->get_p(colorin->params, "type_work");
293 char *_filename = colorin_so->get_p(colorin->params, "filename_work");
294 if(_type && _filename)
295 {
298 }
299 else
300 fprintf(stderr, "[dt_ioppr_get_work_profile_type] can't get colorin parameters\n");
301 }
302 else
303 fprintf(stderr, "[dt_ioppr_get_work_profile_type] can't find colorin iop\n");
304}
305
308 const char **profile_filename)
309{
312
313 // use introspection to get the params values
317 {
319 if(!strcmp(module_so->op, "colorout"))
320 {
322 break;
323 }
324 }
325 if(colorout_so && colorout_so->get_p)
326 {
328 {
329 dt_iop_module_t *module = (dt_iop_module_t *)(modules->data);
330 if(!strcmp(module->op, "colorout"))
331 {
332 colorout = module;
333 break;
334 }
335 }
336 }
337 if(colorout)
338 {
340 char *_filename = colorout_so->get_p(colorout->params, "filename");
341 if(_type && _filename)
342 {
345 }
346 else
347 fprintf(stderr, "[dt_ioppr_get_export_profile_type] can't get colorout parameters\n");
348 }
349 else
350 fprintf(stderr, "[dt_ioppr_get_export_profile_type] can't find colorout iop\n");
351}
352
353
354
355#undef DT_IOP_ORDER_PROFILE
356// clang-format off
357// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
358// vim: shiftwidth=2 expandtab tabstop=2 cindent
359// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
360// 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)
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_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)
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
_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:65
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:252
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__