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
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];
180 cl_float grey;
182
185
193cl_float *dt_ioppr_get_trc_cl(const dt_iop_order_iccprofile_info_t *const profile_info);
194
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);
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__OMP_DECLARE_SIMD__(aligned(lut:64) uniform(lut))
221static inline __attribute__((always_inline)) float extrapolate_lut(const float *const lut, const float v, const int lutsize)
222{
223 // TODO: check if optimization is worthwhile!
224 const float ft = CLAMPS(v * (lutsize - 1), 0, lutsize - 1);
225 const int t = (ft < lutsize - 2) ? ft : lutsize - 2;
226 const float f = ft - t;
227 const float l1 = lut[t];
228 const float l2 = lut[t + 1];
229 return l1 * (1.0f - f) + l2 * f;
230}
231
232
234static inline __attribute__((always_inline)) float eval_exp(const float coeff[3], const float x)
235{
236 return coeff[1] * powf(x * coeff[0], coeff[2]);
237}
238
239__OMP_DECLARE_SIMD__(aligned(lut:64) uniform(lut, coeff))
240static inline __attribute__((always_inline)) float dt_ioppr_eval_trc(const float x, const float *const lut, const float coeff[3], const int lutsize)
241{
242 return (x < 1.0f) ? extrapolate_lut(lut, x, lutsize) : eval_exp(coeff, x);
243}
244#ifdef _OPENMP
245#pragma omp declare simd \
246 aligned(rgb_in, rgb_out, unbounded_coeffs:16) \
247 aligned(lut:64) \
248 uniform(lut, unbounded_coeffs)
249#endif
250static inline __attribute__((always_inline)) void
251_apply_trc(const dt_aligned_pixel_t rgb_in, dt_aligned_pixel_t rgb_out, float *const lut[3],
252 const float unbounded_coeffs[3][3], const int lutsize)
253{
254 for(int c = 0; c < 3; c++)
255 {
256 rgb_out[c] = (lut[c][0] >= 0.0f) ? dt_ioppr_eval_trc(rgb_in[c], lut[c], unbounded_coeffs[c], lutsize)
257 : rgb_in[c];
258 }
259}
260
261#ifdef _OPENMP
262#pragma omp declare simd \
263 aligned(rgb:16) \
264 aligned(matrix_in:64) \
265 aligned(unbounded_coeffs_in:16) \
266 aligned(lut_in:64) \
267 uniform(matrix_in, lut_in, unbounded_coeffs_in)
268#endif
269static inline float dt_ioppr_get_rgb_matrix_luminance(const dt_aligned_pixel_t rgb,
270 const dt_colormatrix_t matrix_in, float *const lut_in[3],
271 const float unbounded_coeffs_in[3][3],
272 const int lutsize, const int nonlinearlut)
273{
274 float luminance = 0.f;
275
276 if(nonlinearlut)
277 {
278 dt_aligned_pixel_t linear_rgb;
279 _apply_trc(rgb, linear_rgb, lut_in, unbounded_coeffs_in, lutsize);
280 luminance = matrix_in[1][0] * linear_rgb[0] + matrix_in[1][1] * linear_rgb[1] + matrix_in[1][2] * linear_rgb[2];
281 }
282 else
283 luminance = matrix_in[1][0] * rgb[0] + matrix_in[1][1] * rgb[1] + matrix_in[1][2] * rgb[2];
284
285 return luminance;
286}
287
288
289#ifdef _OPENMP
290#pragma omp declare simd \
291 aligned(rgb, xyz:16) \
292 aligned(matrix_in_transposed:64) \
293 aligned(unbounded_coeffs_in:16) \
294 aligned(lut_in:64) \
295 uniform(matrix_in_transposed, lut_in, unbounded_coeffs_in)
296#endif
297static inline void dt_ioppr_rgb_matrix_to_xyz(const dt_aligned_pixel_t rgb, dt_aligned_pixel_t xyz,
298 const dt_colormatrix_t matrix_in_transposed, float *const lut_in[3],
299 const float unbounded_coeffs_in[3][3],
300 const int lutsize, const int nonlinearlut)
301{
302 if(nonlinearlut)
303 {
304 dt_aligned_pixel_t linear_rgb;
305 _apply_trc(rgb, linear_rgb, lut_in, unbounded_coeffs_in, lutsize);
306 dt_apply_transposed_color_matrix(linear_rgb, matrix_in_transposed, xyz);
307 }
308 else
309 dt_apply_transposed_color_matrix(rgb, matrix_in_transposed, xyz);
310}
311
312#ifdef _OPENMP
313#pragma omp declare simd \
314 aligned(lab, rgb:16) \
315 aligned(matrix_out_transposed:64) \
316 aligned(unbounded_coeffs_out:16) \
317 aligned(lut_out:64) \
318 uniform(matrix_out_transposed, lut_out, unbounded_coeffs_out)
319#endif
320static inline void dt_ioppr_lab_to_rgb_matrix(const dt_aligned_pixel_t lab, dt_aligned_pixel_t rgb,
321 const dt_colormatrix_t matrix_out_transposed, float *const lut_out[3],
322 const float unbounded_coeffs_out[3][3],
323 const int lutsize, const int nonlinearlut)
324{
326 dt_Lab_to_XYZ(lab, xyz);
327
328 if(nonlinearlut)
329 {
330 dt_aligned_pixel_t linear_rgb;
331 dt_apply_transposed_color_matrix(xyz, matrix_out_transposed, linear_rgb);
332 _apply_trc(linear_rgb, rgb, lut_out, unbounded_coeffs_out, lutsize);
333 }
334 else
335 {
336 dt_apply_transposed_color_matrix(xyz, matrix_out_transposed, rgb);
337 }
338}
339
340#ifdef _OPENMP
341#pragma omp declare simd \
342 aligned(rgb, lab:16) \
343 aligned(matrix_in_transposed:64) \
344 aligned(unbounded_coeffs_in:16) \
345 aligned(lut_in:64) \
346 uniform(matrix_in_transposed, lut_in, unbounded_coeffs_in)
347#endif
348static inline void dt_ioppr_rgb_matrix_to_lab(const dt_aligned_pixel_t rgb, dt_aligned_pixel_t lab,
349 const dt_colormatrix_t matrix_in_transposed, float *const lut_in[3],
350 const float unbounded_coeffs_in[3][3],
351 const int lutsize, const int nonlinearlut)
352{
353 dt_aligned_pixel_t xyz = { 0.f };
354 dt_ioppr_rgb_matrix_to_xyz(rgb, xyz, matrix_in_transposed, lut_in, unbounded_coeffs_in, lutsize, nonlinearlut);
355 dt_XYZ_to_Lab(xyz, lab);
356}
357
358static inline float dt_ioppr_get_profile_info_middle_grey(const dt_iop_order_iccprofile_info_t *const profile_info)
359{
360 return profile_info->grey;
361}
362
363__OMP_DECLARE_SIMD__(uniform(profile_info))
364static inline float dt_ioppr_compensate_middle_grey(const float x, const dt_iop_order_iccprofile_info_t *const profile_info)
365{
366 // we transform the curve nodes from the image colorspace to lab
367 dt_aligned_pixel_t lab = { 0.0f };
368 const dt_aligned_pixel_t rgb = { x, x, x };
369 dt_ioppr_rgb_matrix_to_lab(rgb, lab, profile_info->matrix_in_transposed, profile_info->lut_in,
370 profile_info->unbounded_coeffs_in, profile_info->lutsize, profile_info->nonlinearlut);
371 return lab[0] * .01f;
372}
373
374__OMP_DECLARE_SIMD__(uniform(profile_info))
375static inline float dt_ioppr_uncompensate_middle_grey(const float x, const dt_iop_order_iccprofile_info_t *const profile_info)
376{
377 // we transform the curve nodes from lab to the image colorspace
378 const dt_aligned_pixel_t lab = { x * 100.f, 0.0f, 0.0f };
379 dt_aligned_pixel_t rgb = { 0.0f };
380
381 dt_ioppr_lab_to_rgb_matrix(lab, rgb, profile_info->matrix_out_transposed, profile_info->lut_out,
382 profile_info->unbounded_coeffs_out, profile_info->lutsize, profile_info->nonlinearlut);
383 return rgb[0];
384}
385
386#endif
387// clang-format off
388// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
389// vim: shiftwidth=2 expandtab tabstop=2 cindent
390// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
391// 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
static dt_aligned_pixel_t rgb
Definition colorspaces_inline_conversions.h:344
dt_Lab_to_XYZ(Lab, XYZ)
const float g
Definition colorspaces_inline_conversions.h:674
dt_apply_transposed_color_matrix(XYZ, xyz_to_srgb_matrix_transposed, sRGB)
dt_XYZ_to_Lab(XYZ, Lab)
int type
Definition common/metadata.c:62
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Enable aggressive floating-point arithmetic optimizations, in denormals handling. Set through user pr...
Definition darktable.h:524
#define __OMP_DECLARE_SIMD__(...)
Definition darktable.h:263
static const float x
Definition iop_profile.h:235
const float l2
Definition iop_profile.h:228
static dt_aligned_pixel_t rgb_out
Definition iop_profile.h:251
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_output_profile_info(const struct dt_dev_pixelpipe_t *pipe)
Definition iop_profile.c:879
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:723
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:999
const float *const lut
Definition iop_profile.h:240
const float const int lutsize
Definition iop_profile.h:222
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:905
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_work_profile_info(const struct dt_dev_pixelpipe_t *pipe)
Definition iop_profile.c:869
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:790
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:226
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:843
dt_colorspaces_cl_global_t * dt_colorspaces_init_cl_global(void)
Definition iop_profile.c:1109
int dt_ioppr_transform_image_colorspace_cl(struct dt_iop_module_t *self, const int devid, cl_mem dev_img_in, cl_mem dev_img_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:1247
const float *const const float coeff[3]
Definition iop_profile.h:240
void 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)
Definition iop_profile.c:1133
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)
void dt_colorspaces_free_cl_global(dt_colorspaces_cl_global_t *g)
Definition iop_profile.c:1121
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_input_profile_info(const struct dt_dev_pixelpipe_t *pipe)
Definition iop_profile.c:874
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:703
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:225
void dt_ioppr_free_iccprofile_params_cl(dt_colorspaces_iccprofile_info_cl_t **_profile_info_cl, cl_float **_profile_lut_cl, cl_mem *_dev_profile_info, cl_mem *_dev_profile_lut)
Definition iop_profile.c:1224
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:747
static dt_aligned_pixel_t float *const const float unbounded_coeffs[3][3]
Definition iop_profile.h:252
const float l1
Definition iop_profile.h:227
cl_float * dt_ioppr_get_trc_cl(const dt_iop_order_iccprofile_info_t *const profile_info)
Definition iop_profile.c:1153
const float v
Definition iop_profile.h:221
void dt_ioppr_cleanup_profile_info(dt_iop_order_iccprofile_info_t *profile_info)
Definition iop_profile.c:599
int dt_ioppr_transform_image_colorspace_rgb_cl(const int devid, cl_mem dev_img_in, cl_mem dev_img_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)
Definition iop_profile.c:1395
cl_int dt_ioppr_build_iccprofile_params_cl(const dt_iop_order_iccprofile_info_t *const profile_info, const int devid, dt_colorspaces_iccprofile_info_cl_t **_profile_info_cl, cl_float **_profile_lut_cl, cl_mem *_dev_profile_info, cl_mem *_dev_profile_lut)
Definition iop_profile.c:1169
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:809
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:952
void dt_ioppr_init_profile_info(dt_iop_order_iccprofile_info_t *profile_info, const int lutsize)
Definition iop_profile.c:577
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:884
float *const restrict luminance
Definition luminance_mask.h:77
#define CLAMPS(A, L, H)
Definition math.h:76
float DT_ALIGNED_ARRAY dt_colormatrix_t[4][4]
Definition matrices.h:33
float dt_aligned_pixel_t[4]
Definition noiseprofile.c:28
Definition iop_profile.h:165
int kernel_colorspaces_transform_rgb_matrix_to_rgb
Definition iop_profile.h:168
int kernel_colorspaces_transform_lab_to_rgb_matrix
Definition iop_profile.h:166
int kernel_colorspaces_transform_rgb_matrix_to_lab
Definition iop_profile.h:167
Definition color_conversion.h:42
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
cl_int nonlinearlut
Definition iop_profile.h:179
cl_int lutsize
Definition iop_profile.h:176
cl_float grey
Definition iop_profile.h:180
float matrix_in[9]
Definition color_conversion.h:43
Definition pixelpipe_hb.h:96
Definition pixelpipe_hb.h:218
Definition develop.h:159
Definition imageop.h:246
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