Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
iop_profile.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2018-2019 Edgardo Hoszowski.
4 Copyright (C) 2019-2021, 2025 Aurélien PIERRE.
5 Copyright (C) 2019 Hanno Schwalm.
6 Copyright (C) 2019 luzpaz.
7 Copyright (C) 2019 Marcus Rückert.
8 Copyright (C) 2019-2020 Pascal Obry.
9 Copyright (C) 2020-2021 Dan Torop.
10 Copyright (C) 2020 Harold le Clément de Saint-Marcq.
11 Copyright (C) 2021 Heiko Bauke.
12 Copyright (C) 2021 Hubert Kowalski.
13 Copyright (C) 2021 Ralf Brown.
14 Copyright (C) 2021 Sakari Kapanen.
15 Copyright (C) 2022 Martin Bařinka.
16
17 darktable is free software: you can redistribute it and/or modify
18 it under the terms of the GNU Lesser General Public License as published by
19 the Free Software Foundation, either version 3 of the License, or
20 (at your option) any later version.
21
22 darktable is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU Lesser General Public License for more details.
26
27 You should have received a copy of the GNU Lesser General Public License
28 along with darktable. If not, see <http://www.gnu.org/licenses/>.
29*/
30#ifndef DT_IOP_PROFILE_H
31#define DT_IOP_PROFILE_H
32
34#include "common/colorspaces.h"
35#include "common/matrices.h"
36#include "develop/imageop.h"
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42#ifdef HAVE_OPENCL
43#include <CL/cl.h> // for cl_mem
44#endif
45
46struct dt_iop_module_t;
47struct dt_develop_t;
50
52{
56 dt_colormatrix_t matrix_in; // don't align on more than 16 bits or OpenCL will fail
59 float *lut_in[3];
60 float *lut_out[3];
61 float unbounded_coeffs_in[3][3] DT_ALIGNED_PIXEL;
62 float unbounded_coeffs_out[3][3] DT_ALIGNED_PIXEL;
64 float grey;
65 dt_colormatrix_t matrix_in_transposed; // same as matrix_in, but stored such as to permit vectorization
66 dt_colormatrix_t matrix_out_transposed; // same as matrix_out, but stored such as to permit vectorization
68
73
79 const char *profile_filename);
80
86 const dt_colorspaces_color_profile_type_t profile_type,
87 const char *profile_filename,
88 const int intent);
89
95 GList *iop_list);
97 GList *iop_list);
98
105 struct dt_dev_pixelpipe_t *pipe,
107 const char *filename,
108 const int intent);
109
112 struct dt_dev_pixelpipe_t *pipe,
114 const char *filename,
115 const int intent, const dt_colormatrix_t matrix_in);
116
119 struct dt_dev_pixelpipe_t *pipe,
121 const char *filename,
122 const int intent);
123
128
133
136 const struct dt_dev_pixelpipe_t *pipe);
137
141 const char **profile_filename);
145 const char **profile_filename);
149 const char **profile_filename);
150
152void dt_ioppr_transform_image_colorspace(struct dt_iop_module_t *self, const float *const image_in,
153 float *const image_out, const int width, const int height,
154 const int cst_from, const int cst_to, int *converted_cst,
155 const dt_iop_order_iccprofile_info_t *const profile_info);
156
157void dt_ioppr_transform_image_colorspace_rgb(const float *const image_in, float *const image_out, const int width,
158 const int height,
159 const dt_iop_order_iccprofile_info_t *const profile_info_from,
160 const dt_iop_order_iccprofile_info_t *const profile_info_to,
161 const char *message);
162
163#ifdef HAVE_OPENCL
164typedef struct dt_colorspaces_cl_global_t
165{
166 int kernel_colorspaces_transform_lab_to_rgb_matrix;
167 int kernel_colorspaces_transform_rgb_matrix_to_lab;
168 int kernel_colorspaces_transform_rgb_matrix_to_rgb;
169} dt_colorspaces_cl_global_t;
170
171// must be in synch with colorspaces.cl dt_colorspaces_iccprofile_info_cl_t
173{
174 cl_float matrix_in[9];
175 cl_float matrix_out[9];
176 cl_int lutsize;
177 cl_float unbounded_coeffs_in[3][3];
178 cl_float unbounded_coeffs_out[3][3];
179 cl_int nonlinearlut;
180 cl_float grey;
182
183dt_colorspaces_cl_global_t *dt_colorspaces_init_cl_global(void);
184void dt_colorspaces_free_cl_global(dt_colorspaces_cl_global_t *g);
185
189void dt_ioppr_get_profile_info_cl(const dt_iop_order_iccprofile_info_t *const profile_info, dt_colorspaces_iccprofile_info_cl_t *profile_info_cl);
193cl_float *dt_ioppr_get_trc_cl(const dt_iop_order_iccprofile_info_t *const profile_info);
194
196cl_int dt_ioppr_build_iccprofile_params_cl(const dt_iop_order_iccprofile_info_t *const profile_info,
197 const int devid, dt_colorspaces_iccprofile_info_cl_t **_profile_info_cl,
198 cl_float **_profile_lut_cl, cl_mem *_dev_profile_info,
199 cl_mem *_dev_profile_lut);
201void dt_ioppr_free_iccprofile_params_cl(dt_colorspaces_iccprofile_info_cl_t **_profile_info_cl,
202 cl_float **_profile_lut_cl, cl_mem *_dev_profile_info,
203 cl_mem *_dev_profile_lut);
204
206int dt_ioppr_transform_image_colorspace_cl(struct dt_iop_module_t *self, const int devid, cl_mem dev_img_in,
207 cl_mem dev_img_out, const int width, const int height,
208 const int cst_from, const int cst_to, int *converted_cst,
209 const dt_iop_order_iccprofile_info_t *const profile_info);
210
211int dt_ioppr_transform_image_colorspace_rgb_cl(const int devid, cl_mem dev_img_in, cl_mem dev_img_out,
212 const int width, const int height,
213 const dt_iop_order_iccprofile_info_t *const profile_info_from,
214 const dt_iop_order_iccprofile_info_t *const profile_info_to,
215 const char *message);
216#endif
217
220#ifdef _OPENMP
221#pragma omp declare simd aligned(lut:64) uniform(lut)
222#endif
223static inline __attribute__((always_inline)) float extrapolate_lut(const float *const lut, const float v, const int lutsize)
224{
225 // TODO: check if optimization is worthwhile!
226 const float ft = CLAMPS(v * (lutsize - 1), 0, lutsize - 1);
227 const int t = (ft < lutsize - 2) ? ft : lutsize - 2;
228 const float f = ft - t;
229 const float l1 = lut[t];
230 const float l2 = lut[t + 1];
231 return l1 * (1.0f - f) + l2 * f;
232}
233
234
235#ifdef _OPENMP
236#pragma omp declare simd uniform(coeff)
237#endif
238static inline __attribute__((always_inline)) float eval_exp(const float coeff[3], const float x)
239{
240 return coeff[1] * powf(x * coeff[0], coeff[2]);
241}
242
243#ifdef _OPENMP
244#pragma omp declare simd aligned(lut:64) uniform(lut, coeff)
245#endif
246static inline __attribute__((always_inline)) float dt_ioppr_eval_trc(const float x, const float *const lut, const float coeff[3], const int lutsize)
247{
248 return (x < 1.0f) ? extrapolate_lut(lut, x, lutsize) : eval_exp(coeff, x);
249}
250
251
252#ifdef _OPENMP
253#pragma omp declare simd \
254 aligned(rgb_in, rgb_out, unbounded_coeffs:16) \
255 aligned(lut:64) \
256 uniform(rgb_in, rgb_out, unbounded_coeffs, lut)
257#endif
258static inline void _apply_trc(const dt_aligned_pixel_t rgb_in, dt_aligned_pixel_t rgb_out,
259 float *const lut[3],
260 const float unbounded_coeffs[3][3],
261 const int lutsize)
262{
263 for(int c = 0; c < 3; c++)
264 {
265 rgb_out[c] = (lut[c][0] >= 0.0f) ? dt_ioppr_eval_trc(rgb_in[c], lut[c], unbounded_coeffs[c], lutsize)
266 : rgb_in[c];
267 }
268}
269
270#ifdef _OPENMP
271#pragma omp declare simd \
272 aligned(rgb, matrix_in, unbounded_coeffs_in:16) \
273 aligned(lut_in:64) \
274 uniform(rgb, matrix_in, lut_in, unbounded_coeffs_in)
275#endif
276static inline float dt_ioppr_get_rgb_matrix_luminance(const dt_aligned_pixel_t rgb,
277 const dt_colormatrix_t matrix_in, float *const lut_in[3],
278 const float unbounded_coeffs_in[3][3],
279 const int lutsize, const int nonlinearlut)
280{
281 float luminance = 0.f;
282
283 if(nonlinearlut)
284 {
285 dt_aligned_pixel_t linear_rgb;
286 _apply_trc(rgb, linear_rgb, lut_in, unbounded_coeffs_in, lutsize);
287 luminance = matrix_in[1][0] * linear_rgb[0] + matrix_in[1][1] * linear_rgb[1] + matrix_in[1][2] * linear_rgb[2];
288 }
289 else
290 luminance = matrix_in[1][0] * rgb[0] + matrix_in[1][1] * rgb[1] + matrix_in[1][2] * rgb[2];
291
292 return luminance;
293}
294
295
296#ifdef _OPENMP
297#pragma omp declare simd \
298 aligned(unbounded_coeffs_in:16) \
299 aligned(lut_in:64) \
300 uniform(lut_in, unbounded_coeffs_in)
301#endif
302static inline void dt_ioppr_rgb_matrix_to_xyz(const dt_aligned_pixel_t rgb, dt_aligned_pixel_t xyz,
303 const dt_colormatrix_t matrix_in_transposed, float *const lut_in[3],
304 const float unbounded_coeffs_in[3][3],
305 const int lutsize, const int nonlinearlut)
306{
307 if(nonlinearlut)
308 {
309 dt_aligned_pixel_t linear_rgb;
310 _apply_trc(rgb, linear_rgb, lut_in, unbounded_coeffs_in, lutsize);
311 dt_apply_transposed_color_matrix(linear_rgb, matrix_in_transposed, xyz);
312 }
313 else
314 dt_apply_transposed_color_matrix(rgb, matrix_in_transposed, xyz);
315}
316
317#ifdef _OPENMP
318#pragma omp declare simd \
319 aligned(unbounded_coeffs_out:16) \
320 aligned(lut_out:64) \
321 uniform(lut_out, unbounded_coeffs_out)
322#endif
323static inline void dt_ioppr_lab_to_rgb_matrix(const dt_aligned_pixel_t lab, dt_aligned_pixel_t rgb,
324 const dt_colormatrix_t matrix_out_transposed, float *const lut_out[3],
325 const float unbounded_coeffs_out[3][3],
326 const int lutsize, const int nonlinearlut)
327{
328 dt_aligned_pixel_t xyz;
329 dt_Lab_to_XYZ(lab, xyz);
330
331 if(nonlinearlut)
332 {
333 dt_aligned_pixel_t linear_rgb;
334 dt_apply_transposed_color_matrix(xyz, matrix_out_transposed, linear_rgb);
335 _apply_trc(linear_rgb, rgb, lut_out, unbounded_coeffs_out, lutsize);
336 }
337 else
338 {
339 dt_apply_transposed_color_matrix(xyz, matrix_out_transposed, rgb);
340 }
341}
342
343#ifdef _OPENMP
344#pragma omp declare simd \
345 aligned(unbounded_coeffs_in:16) \
346 aligned(lut_in:64) \
347 uniform(lut_in, unbounded_coeffs_in)
348#endif
349static inline void dt_ioppr_rgb_matrix_to_lab(const dt_aligned_pixel_t rgb, dt_aligned_pixel_t lab,
350 const dt_colormatrix_t matrix_in_transposed, float *const lut_in[3],
351 const float unbounded_coeffs_in[3][3],
352 const int lutsize, const int nonlinearlut)
353{
354 dt_aligned_pixel_t xyz = { 0.f };
355 dt_ioppr_rgb_matrix_to_xyz(rgb, xyz, matrix_in_transposed, lut_in, unbounded_coeffs_in, lutsize, nonlinearlut);
356 dt_XYZ_to_Lab(xyz, lab);
357}
358
359static inline float dt_ioppr_get_profile_info_middle_grey(const dt_iop_order_iccprofile_info_t *const profile_info)
360{
361 return profile_info->grey;
362}
363
364#ifdef _OPENMP
365#pragma omp declare simd
366#endif
367static inline float dt_ioppr_compensate_middle_grey(const float x, const dt_iop_order_iccprofile_info_t *const profile_info)
368{
369 // we transform the curve nodes from the image colorspace to lab
370 dt_aligned_pixel_t lab = { 0.0f };
371 const dt_aligned_pixel_t rgb = { x, x, x };
372 dt_ioppr_rgb_matrix_to_lab(rgb, lab, profile_info->matrix_in_transposed, profile_info->lut_in,
373 profile_info->unbounded_coeffs_in, profile_info->lutsize, profile_info->nonlinearlut);
374 return lab[0] * .01f;
375}
376
377#ifdef _OPENMP
378#pragma omp declare simd
379#endif
380static inline float dt_ioppr_uncompensate_middle_grey(const float x, const dt_iop_order_iccprofile_info_t *const profile_info)
381{
382 // we transform the curve nodes from lab to the image colorspace
383 const dt_aligned_pixel_t lab = { x * 100.f, 0.0f, 0.0f };
384 dt_aligned_pixel_t rgb = { 0.0f };
385
386 dt_ioppr_lab_to_rgb_matrix(lab, rgb, profile_info->matrix_out_transposed, profile_info->lut_out,
387 profile_info->unbounded_coeffs_out, profile_info->lutsize, profile_info->nonlinearlut);
388 return rgb[0];
389}
390
391#endif
392// clang-format off
393// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
394// vim: shiftwidth=2 expandtab tabstop=2 cindent
395// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
396// clang-format on
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
dt_iop_color_intent_t
Definition colorspaces.h:63
#define DT_IOP_COLOR_ICC_LEN
Definition colorspaces.h:57
dt_colorspaces_color_profile_type_t
Definition colorspaces.h:81
const float c
Definition colorspaces_inline_conversions.h:1365
dt_Lab_to_XYZ(Lab, XYZ)
const float g
Definition colorspaces_inline_conversions.h:925
dt_apply_transposed_color_matrix(XYZ, xyz_to_srgb_matrix_transposed, sRGB)
dt_XYZ_to_Lab(XYZ, Lab)
static dt_aligned_pixel_t rgb
Definition colorspaces_inline_conversions.h:530
int type
Definition common/metadata.c:62
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Multi-tap smudge source sample with directional jitter.
Definition darktable.h:448
static const float x
Definition iop_profile.h:239
const float l2
Definition iop_profile.h:230
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_output_profile_info(const struct dt_dev_pixelpipe_t *pipe)
Definition iop_profile.c:924
dt_iop_order_iccprofile_info_t * dt_ioppr_add_profile_info_to_list(struct dt_develop_t *dev, const dt_colorspaces_color_profile_type_t profile_type, const char *profile_filename, const int intent)
Definition iop_profile.c:768
void dt_ioppr_transform_image_colorspace(struct dt_iop_module_t *self, const float *const image_in, float *const image_out, const int width, const int height, const int cst_from, const int cst_to, int *converted_cst, const dt_iop_order_iccprofile_info_t *const profile_info)
Definition iop_profile.c:1044
void dt_ioppr_get_work_profile_type(struct dt_develop_t *dev, dt_colorspaces_color_profile_type_t *profile_type, const char **profile_filename)
Definition iop_profile.c:950
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_work_profile_info(const struct dt_dev_pixelpipe_t *pipe)
Definition iop_profile.c:914
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)
Definition iop_profile.c:835
void dt_ioppr_transform_image_colorspace_rgb(const float *const image_in, float *const image_out, const int width, const int height, const dt_iop_order_iccprofile_info_t *const profile_info_from, const dt_iop_order_iccprofile_info_t *const profile_info_to, const char *message)
const float f
Definition iop_profile.h:228
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)
Definition iop_profile.c:888
static const float *const lut
Definition iop_profile.h:246
static const float *const const float coeff[3]
Definition iop_profile.h:246
static float dt_ioppr_compensate_middle_grey(const float x, const dt_iop_order_iccprofile_info_t *const profile_info)
Definition iop_profile.h:367
dt_iop_order_iccprofile_info_t * dt_ioppr_get_iop_input_profile_info(struct dt_iop_module_t *module, GList *iop_list)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_histogram_profile_info(struct dt_develop_t *dev)
static void _apply_trc(const dt_aligned_pixel_t rgb_in, dt_aligned_pixel_t rgb_out, float *const lut[3], const float unbounded_coeffs[3][3], const int lutsize)
Definition iop_profile.h:258
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_input_profile_info(const struct dt_dev_pixelpipe_t *pipe)
Definition iop_profile.c:919
dt_iop_order_iccprofile_info_t * dt_ioppr_get_profile_info_from_list(struct dt_develop_t *dev, dt_colorspaces_color_profile_type_t profile_type, const char *profile_filename)
Definition iop_profile.c:748
void dt_ioppr_get_input_profile_type(struct dt_develop_t *dev, dt_colorspaces_color_profile_type_t *profile_type, const char **profile_filename)
const int t
Definition iop_profile.h:227
static void dt_ioppr_rgb_matrix_to_lab(const dt_aligned_pixel_t rgb, dt_aligned_pixel_t lab, const dt_colormatrix_t matrix_in_transposed, float *const lut_in[3], const float unbounded_coeffs_in[3][3], const int lutsize, const int nonlinearlut)
Definition iop_profile.h:349
dt_iop_order_iccprofile_info_t * dt_ioppr_get_iop_work_profile_info(struct dt_iop_module_t *module, GList *iop_list)
Definition iop_profile.c:792
static float dt_ioppr_get_rgb_matrix_luminance(const dt_aligned_pixel_t rgb, const dt_colormatrix_t matrix_in, float *const lut_in[3], const float unbounded_coeffs_in[3][3], const int lutsize, const int nonlinearlut)
Definition iop_profile.h:276
const float l1
Definition iop_profile.h:229
static float dt_ioppr_uncompensate_middle_grey(const float x, const dt_iop_order_iccprofile_info_t *const profile_info)
Definition iop_profile.h:380
static float dt_ioppr_get_profile_info_middle_grey(const dt_iop_order_iccprofile_info_t *const profile_info)
Definition iop_profile.h:359
static void dt_ioppr_lab_to_rgb_matrix(const dt_aligned_pixel_t lab, dt_aligned_pixel_t rgb, const dt_colormatrix_t matrix_out_transposed, float *const lut_out[3], const float unbounded_coeffs_out[3][3], const int lutsize, const int nonlinearlut)
Definition iop_profile.h:323
static const float v
Definition iop_profile.h:223
void dt_ioppr_cleanup_profile_info(dt_iop_order_iccprofile_info_t *profile_info)
Definition iop_profile.c:646
static void dt_ioppr_rgb_matrix_to_xyz(const dt_aligned_pixel_t rgb, dt_aligned_pixel_t xyz, const dt_colormatrix_t matrix_in_transposed, float *const lut_in[3], const float unbounded_coeffs_in[3][3], const int lutsize, const int nonlinearlut)
Definition iop_profile.h:302
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)
Definition iop_profile.c:854
void dt_ioppr_get_export_profile_type(struct dt_develop_t *dev, dt_colorspaces_color_profile_type_t *profile_type, const char **profile_filename)
Definition iop_profile.c:997
static const float const int lutsize
Definition iop_profile.h:224
void dt_ioppr_init_profile_info(dt_iop_order_iccprofile_info_t *profile_info, const int lutsize)
Definition iop_profile.c:624
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_current_profile_info(struct dt_iop_module_t *module, const struct dt_dev_pixelpipe_t *pipe)
Definition iop_profile.c:929
#define CLAMPS(A, L, H)
Definition math.h:76
float DT_ALIGNED_ARRAY dt_colormatrix_t[4][4]
Definition matrices.h:33
Definition color_conversion.h:42
int lutsize
Definition color_conversion.h:45
float grey
Definition color_conversion.h:49
int nonlinearlut
Definition color_conversion.h:48
float unbounded_coeffs_out[3][3]
Definition color_conversion.h:47
float matrix_out[9]
Definition color_conversion.h:44
float unbounded_coeffs_in[3][3]
Definition color_conversion.h:46
float matrix_in[9]
Definition color_conversion.h:43
Definition pixelpipe_hb.h:95
Definition pixelpipe_hb.h:216
Definition develop.h:155
Definition imageop.h:216
Definition iop_profile.h:52
int nonlinearlut
Definition iop_profile.h:63
int lutsize
Definition iop_profile.h:58
dt_iop_color_intent_t intent
Definition iop_profile.h:55
dt_colormatrix_t matrix_out_transposed
Definition iop_profile.h:66
float grey
Definition iop_profile.h:64
dt_colorspaces_color_profile_type_t type
Definition iop_profile.h:53
float * lut_out[3]
Definition iop_profile.h:60
dt_colormatrix_t matrix_out
Definition iop_profile.h:57
float * lut_in[3]
Definition iop_profile.h:59
char filename[DT_IOP_COLOR_ICC_LEN]
Definition iop_profile.h:54
float unbounded_coeffs_in[3][3] DT_ALIGNED_PIXEL
Definition iop_profile.h:61
dt_colormatrix_t matrix_in_transposed
Definition iop_profile.h:65
dt_colormatrix_t matrix_in
Definition iop_profile.h:56
float unbounded_coeffs_out[3][3] DT_ALIGNED_PIXEL
Definition iop_profile.h:62