Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
iop_profile.c File Reference
#include "colorprofiles/colorspaces.h"
#include "caches/pixelpipe_cache_alloc.h"
#include "colorprofiles/iop_profile.h"
#include "math/matrices.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "system/target_clones.h"
#include "common/times.h"
+ Include dependency graph for colorprofiles/iop_profile.c:

Go to the source code of this file.

Macros

#define DT_IOPPR_LUT_SAMPLES   0x10000
 

Functions

 __attribute__ ((always_inline))
 
__DT_CLONE_TARGETS__ void dt_ioppr_clear_lut_curves (dt_iop_order_iccprofile_info_t *const profile_info)
 Mark all six tone curves linear, by writing -1.0 into entry 0 of each.
 
static void _transform_from_to_rgb_lab_lcms2 (const float *const image_in, float *const image_out, const int width, const int height, const dt_colorspaces_color_profile_type_t type, const char *filename, const int intent, const int direction)
 
void dt_ioppr_transform_lcms2 (const char *op, const char *multi_name, const float *const image_in, float *const image_out, const int width, const int height, const dt_iop_colorspace_type_t cst_from, const dt_iop_colorspace_type_t cst_to, dt_iop_colorspace_type_t *converted_cst, const dt_iop_order_iccprofile_info_t *const profile_info)
 The lcms2 branch of dt_colorspaces_apply_profile(): RGB <-> Lab via cmsDoTransform.
 
int dt_ioppr_init_unbounded_coeffs (float *const lutr, float *const lutg, float *const lutb, float *const unbounded_coeffsr, float *const unbounded_coeffsg, float *const unbounded_coeffsb, const int lutsize)
 Fit the power-law continuation of three tone curves past white.
 
static void _apply_tonecurves (const float *const image_in, float *const image_out, const int width, const int height, const float *const restrict lutr, const float *const restrict lutg, const float *const restrict lutb, const float *const restrict unbounded_coeffsr, const float *const restrict unbounded_coeffsg, const float *const restrict unbounded_coeffsb, const int lutsize)
 
static __DT_CLONE_TARGETS__ void _transform_rgb_to_lab_matrix (const float *const restrict image_in, float *const restrict image_out, const int width, const int height, const dt_iop_order_iccprofile_info_t *const profile_info)
 
static __DT_CLONE_TARGETS__ void _transform_lab_to_rgb_matrix (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)
 
static __DT_CLONE_TARGETS__ void _transform_matrix_rgb (const float *const restrict image_in, float *const restrict 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)
 
void dt_ioppr_transform_matrix (const char *op, const char *multi_name, const float *const restrict image_in, float *const restrict image_out, const int width, const int height, const dt_iop_colorspace_type_t cst_from, const dt_iop_colorspace_type_t cst_to, dt_iop_colorspace_type_t *converted_cst, const dt_iop_order_iccprofile_info_t *const profile_info)
 
__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 using profile_info, default lutsize = 0.
 
void dt_ioppr_cleanup_profile_info (dt_iop_order_iccprofile_info_t **profile_info)
 Release a profile info: its tone-curve LUTs, the struct itself, and the caller's pointer – must be called when done with profile_info.
 
void dt_ioppr_transform_image_colorspace_rgb (const float *const restrict image_in, float *const restrict 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)
 
void dt_colorspaces_init_cl_global (void)
 Compile the colorspace kernels. Called once by common/opencl.c at device init.
 
void dt_colorspaces_free_cl_global (void)
 Release the kernels and the struct from dt_colorspaces_init_cl_global(). NULL-safe.
 
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)
 sets profile_info_cl using profile_info, to be used as a parameter when calling opencl.
 
cl_float * dt_ioppr_get_trc_cl (const dt_iop_order_iccprofile_info_t *const profile_info)
 returns the profile_info trc, to be used as a parameter when calling opencl.
 
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)
 build the required parameters for a kernel that uses a profile info.
 
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)
 free parameters build with the previous function.
 
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)
 OpenCL counterpart of dt_ioppr_transform_image_colorspace_rgb().
 
void dt_colorspaces_flush_profile_memo (void)
 Drop every memoised entry. Called by dt_colorprofiles_cleanup().
 
void dt_colorspaces_invalidate_display_profile_memo (void)
 Drop the memoised DT_COLORSPACE_DISPLAY entry, whose source profile this module replaces on a monitor change.
 
static int _generate_profile_info (dt_iop_order_iccprofile_info_t *profile_info, const int type, const char *filename, const int intent)
 
static dt_iop_order_iccprofile_info_t_get_profile_info_from_list (const dt_colorspaces_color_profile_type_t profile_type, const char *profile_filename, const int intent)
 
dt_iop_order_iccprofile_info_tdt_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.
 
void dt_colorspaces_apply_profile (const char *const op_name, const char *const instance_name, 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)
 Convert a 4-channel float buffer between RGB and Lab through one profile.
 
int dt_colorspaces_apply_profile_cl (const char *const op_name, const char *const instance_name, 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)
 OpenCL counterpart of dt_colorspaces_apply_profile(), same contract.
 

Variables

static dt_colorspaces_cl_global_t_colorspaces_cl_global = NULL
 
static GList_profile_info_memo = NULL
 
static pthread_mutex_t _profile_info_lock = PTHREAD_MUTEX_INITIALIZER
 

Macro Definition Documentation

◆ DT_IOPPR_LUT_SAMPLES

#define DT_IOPPR_LUT_SAMPLES   0x10000

Definition at line 599 of file colorprofiles/iop_profile.c.

Function Documentation

◆ __attribute__()

__attribute__ ( (always_inline )
inline

Definition at line 75 of file colorprofiles/iop_profile.c.

References L.

◆ _apply_tonecurves()

static void _apply_tonecurves ( const float *const  image_in,
float *const  image_out,
const int  width,
const int  height,
const float *const restrict  lutr,
const float *const restrict  lutg,
const float *const restrict  lutb,
const float *const restrict  unbounded_coeffsr,
const float *const restrict  unbounded_coeffsg,
const float *const restrict  unbounded_coeffsb,
const int  lutsize 
)
inlinestatic

◆ _generate_profile_info()

◆ _get_profile_info_from_list()

static dt_iop_order_iccprofile_info_t * _get_profile_info_from_list ( const dt_colorspaces_color_profile_type_t  profile_type,
const char *  profile_filename,
const int  intent 
)
static

Definition at line 1224 of file colorprofiles/iop_profile.c.

References _profile_info_memo, and L.

Referenced by dt_colorspaces_add_profile().

◆ _transform_from_to_rgb_lab_lcms2()

◆ _transform_lab_to_rgb_matrix()

static __DT_CLONE_TARGETS__ void _transform_lab_to_rgb_matrix ( 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 
)
inlinestatic
Todo:
: maybe optimize that path like _transform_matrix_rgb

Definition at line 423 of file colorprofiles/iop_profile.c.

References __OMP_PARALLEL_FOR__, _apply_tonecurves(), ch, dt_Lab_to_XYZ(), dt_omploop_sfence, dt_store_simd_aligned(), height, L, out, rgb, and width.

Referenced by dt_ioppr_transform_matrix().

◆ _transform_matrix_rgb()

static __DT_CLONE_TARGETS__ void _transform_matrix_rgb ( const float *const restrict  image_in,
float *const restrict  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 
)
inlinestatic

◆ _transform_rgb_to_lab_matrix()

static __DT_CLONE_TARGETS__ void _transform_rgb_to_lab_matrix ( const float *const restrict  image_in,
float *const restrict  image_out,
const int  width,
const int  height,
const dt_iop_order_iccprofile_info_t *const  profile_info 
)
inlinestatic
Todo:
: maybe optimize that path like _transform_matrix_rgb

Definition at line 377 of file colorprofiles/iop_profile.c.

References __OMP_PARALLEL_FOR_SIMD__, _apply_tonecurves(), ch, dt_store_simd_aligned(), dt_XYZ_to_Lab(), height, L, out, and width.

Referenced by dt_ioppr_transform_matrix().

◆ dt_colorspaces_add_profile()

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.

Deriving matrices and curves from a profile costs two 65536-entry extractions and is a pure function of (type, filename, intent), so the result is kept in a process-wide memo. The lookup and the append are ONE critical section under the module's own mutex: this is reached from the pipeline worker (iop/lut3d.c and iop/tonecurve.c call it from process()/process_cl(), once per tile) and from the GUI thread (iop/colorin.c), and two threads missing the same key concurrently would otherwise each build an entry – 1.5 MB of tone-curve LUTs apiece – and append both. Building the DT_COLORSPACE_DISPLAY entry additionally takes dt_colorspaces_lock_profiles() internally, for the whole span from resolving the handle to the last extraction, because that handle is the one datum in the profile list that is replaced at runtime.

Parameters
profile_typeprofile identity; half of the memo key.
profile_filenameICC file name, "" for built-ins; the other half of the key.
intentrendering intent; the third part of the key. It is stored in the entry and read back by the lcms2 transform path, so a memo that ignored it handed the second caller a transform built for the first caller's intent – silently, and depending on which module happened to commit first. Two intents for one profile now cost two entries, which is 1.5 MB each; that is the price of the answer being right.
Returns
A pointer the MODULE owns, valid until dt_colorspaces_flush_profile_memo() (or, for DT_COLORSPACE_DISPLAY, dt_colorspaces_invalidate_display_profile_memo()). Never free it, and never write through it – the entry is shared by every caller asking for the same identity, including concurrent pipes. NULL only if the allocation failed or the profile could not be derived.
Warning
NOT for the image-derived types, DT_COLORSPACE_EMBEDDED_ICC (9) through DT_COLORSPACE_ALTERNATE_MATRIX (14). Those are not registered in the profile list and cannot be resolved by identity at all: their matrices come from the image's own camera data via iop/colorin.c. Keyed on (type, "") they would all collide on one entry and stomp each other across images. They live on the pipe that built them instead (dt_dev_pixelpipe_t.owned_input_profile_info); see dt_ioppr_set_pipe_input_profile_info() in develop/iop_profile.c.

Definition at line 1248 of file colorprofiles/iop_profile.c.

References _generate_profile_info(), _get_profile_info_from_list(), _profile_info_lock, _profile_info_memo, dt_alloc_align(), dt_ioppr_cleanup_profile_info(), dt_ioppr_init_profile_info(), IS_NULL_PTR, and L.

Referenced by _filmic_get_output_profile(), _refresh_slider_gradients(), _update_gui_lut_cache(), _update_gui_lut_cache(), commit_params(), dt_ioppr_get_iop_work_profile_info(), dt_ioppr_set_pipe_input_profile_info(), dt_ioppr_set_pipe_output_profile_info(), dt_ioppr_set_pipe_work_profile_info(), process(), process(), process_cl(), and workicc_changed().

◆ dt_colorspaces_apply_profile()

void dt_colorspaces_apply_profile ( const char *const  op_name,
const char *const  instance_name,
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 
)

Convert a 4-channel float buffer between RGB and Lab through one profile.

THE entry point for the RGB <-> Lab leg of the pipeline, called by develop/pixelpipe_cpu.c around every module that wants a different working space than the one the pipe carries. It dispatches on the profile itself, not on a caller's request: if the profile reduced to real matrices (!isnan(matrix_in[0][0])) it runs dt_ioppr_transform_matrix() – our own vectorised matrix + tone-curve LUT loop, with power-law extrapolation above white; otherwise (a CLUT profile, a v4 parametric curve lcms2 will not reduce) it falls back to dt_ioppr_transform_lcms2(), which builds a cmsHTRANSFORM and runs cmsDoTransform. Callers do not choose, and do not see which ran except in the -d perf trace.

The lcms2 branch resolves and pins the profile handle itself – it takes dt_colorspaces_lock_profiles() around resolve-through-cmsCreateTransform when the profile is DT_COLORSPACE_DISPLAY – so callers neither take that lock nor need to know the branch exists.

Parameters
op_namemodule op string, for the -d perf trace ONLY.
instance_namemodule multi_name string, same.
image_insource, 4 floats per pixel, 16-byte aligned. May equal image_out (in-place is supported and used).
image_outdestination, same layout. Alpha (the 4th float) is preserved by the matrix paths.
widthpixels per row.
heightrows.
cst_fromsource colorspace, a dt_iop_colorspace_type_t passed as plain int.
cst_todestination colorspace, same.
converted_cstout: set to cst_to when the buffer was converted, and left at cst_from when it was NOT – which is how the caller learns the buffer is still in its original space. This is the only failure report; there is no return value.
Warning
Refuses (leaving *converted_cst == cst_from) on a NULL profile_info or one whose type is DT_COLORSPACE_NONE, and prints to stderr on an unsupported pair.
RGB -> RGB is a NO-OP here: it reports success (*converted_cst = cst_to) and copies nothing, not even between two different RGB profiles. Converting between two RGB spaces is dt_ioppr_transform_image_colorspace_rgb()'s job.
See also
dt_ioppr_transform_image_colorspace_rgb() for the RGB -> RGB leg.

Definition at line 1300 of file colorprofiles/iop_profile.c.

References DT_COLORSPACE_NONE, DT_DEBUG_PERF, dt_get_debug_flags(), dt_get_times(), dt_iop_colorspace_is_rgb(), dt_ioppr_transform_lcms2(), dt_ioppr_transform_matrix(), height, IS_NULL_PTR, L, and width.

Referenced by _draw_color_picker(), _refresh_preview_module_histogram_for_hash(), _retouch_blur(), dt_colorspaces_apply_profile_cl(), pixelpipe_process_on_CPU(), and pixelpipe_process_on_GPU().

◆ dt_colorspaces_apply_profile_cl()

int dt_colorspaces_apply_profile_cl ( const char *const  op_name,
const char *const  instance_name,
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 
)

OpenCL counterpart of dt_colorspaces_apply_profile(), same contract.

Same internal branch, different fallback cost: a matrix profile is uploaded (the scalar fields as a constant buffer, the six curves as a 256 x 1536 float image) and converted by the colorspaces_transform_* kernels; a non-matrix profile has no kernel, so the buffer is read back to host memory, run through dt_colorspaces_apply_profile() on the CPU in place, and written back to the device.

Parameters
devidOpenCL device.
dev_img_insource device image.
dev_img_outdestination device image.
converted_cstout: same "did it actually convert" report as the CPU version, and still meaningful on a FALSE return.
Returns
TRUE on success, FALSE on any OpenCL error or refusal – an int, not a cl_int. Callers must fall back to the CPU path on FALSE.
Warning
Asserts that both images are non-NULL and DISTINCT: unlike the CPU version, this one cannot run in place.

Definition at line 1362 of file colorprofiles/iop_profile.c.

References _colorspaces_cl_global, ch, cleanup(), DT_COLORSPACE_NONE, dt_colorspaces_apply_profile(), DT_DEBUG_PERF, dt_free, dt_get_debug_flags(), dt_get_times(), dt_iop_colorspace_is_rgb(), dt_ioppr_get_profile_info_cl(), dt_ioppr_get_trc_cl(), dt_opencl_copy_device_to_host(), dt_opencl_copy_host_to_device(), dt_opencl_copy_host_to_device_constant(), dt_opencl_enqueue_kernel_2d(), dt_opencl_release_mem_object(), dt_opencl_set_kernel_arg(), dt_opencl_write_host_to_device(), dt_pixelpipe_cache_alloc_align_float_cache, dt_pixelpipe_cache_free_align, FALSE, height, IOP_CS_LAB, IS_NULL_PTR, dt_colorspaces_cl_global_t::kernel_colorspaces_transform_lab_to_rgb_matrix, dt_colorspaces_cl_global_t::kernel_colorspaces_transform_rgb_matrix_to_lab, L, ROUNDUPDHT, ROUNDUPDWD, TRUE, and width.

Referenced by pixelpipe_process_on_GPU().

◆ dt_colorspaces_flush_profile_memo()

void dt_colorspaces_flush_profile_memo ( void  )

Drop every memoised entry. Called by dt_colorprofiles_cleanup().

Frees each entry with dt_ioppr_cleanup_profile_info(), so it invalidates every pointer ever returned by dt_colorspaces_add_profile(). Only legitimate at shutdown, once no pipe can still be holding one.

Definition at line 1096 of file colorprofiles/iop_profile.c.

References _profile_info_lock, _profile_info_memo, dt_ioppr_cleanup_profile_info(), and L.

Referenced by dt_colorprofiles_cleanup().

◆ dt_colorspaces_free_cl_global()

void dt_colorspaces_free_cl_global ( void  )

Release the kernels and the struct from dt_colorspaces_init_cl_global(). NULL-safe.

Definition at line 712 of file colorprofiles/iop_profile.c.

References _colorspaces_cl_global, dt_free, dt_opencl_free_kernel(), g, IS_NULL_PTR, and L.

Referenced by dt_opencl_cleanup().

◆ dt_colorspaces_init_cl_global()

void dt_colorspaces_init_cl_global ( void  )

Compile the colorspace kernels. Called once by common/opencl.c at device init.

Returns
A malloced struct the caller owns; release with dt_colorspaces_free_cl_global().

Definition at line 700 of file colorprofiles/iop_profile.c.

References _colorspaces_cl_global, dt_opencl_create_kernel(), g, dt_colorspaces_cl_global_t::kernel_colorspaces_transform_lab_to_rgb_matrix, and L.

Referenced by dt_opencl_init().

◆ dt_colorspaces_invalidate_display_profile_memo()

void dt_colorspaces_invalidate_display_profile_memo ( void  )

Drop the memoised DT_COLORSPACE_DISPLAY entry, whose source profile this module replaces on a monitor change.

Nothing invalidated it before, so a session kept the previous monitor's matrices and tone curves for as long as the memo lived. That was already wrong when the memo hung off one image; now that it is process-wide it would persist for the whole run. Dropped rather than rebuilt: the next caller that wants it will build it, and rebuilding here would mean deriving a profile under the memo lock from inside the profile-changed handler.

Warning
Called from colorprofiles/colorspaces.c when the display profile changes. Any pointer a caller cached from a previous dt_colorspaces_add_profile(DISPLAY, ...) is freed by this – resolve the display profile per use, do not hold it.

Definition at line 1108 of file colorprofiles/iop_profile.c.

References _profile_info_lock, _profile_info_memo, DT_COLORSPACE_DISPLAY, dt_ioppr_cleanup_profile_info(), L, and dt_iop_order_iccprofile_info_t::type.

Referenced by _notify_profile_changed().

◆ dt_ioppr_build_iccprofile_params_cl()

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 
)

build the required parameters for a kernel that uses a profile info.

Packs the profile for the device in one call: the scalars into a constant buffer and the six curves into a 256 x 1536 float image. Everything it allocates – host and device – comes back through the four out-parameters, and is released as a set by dt_ioppr_free_iccprofile_params_cl().

Parameters
profile_infoprofile to upload, or NULL. NULL is a supported "this kernel takes a profile argument but there is no profile" case: it uploads a 6-float dummy LUT and leaves *_dev_profile_info NULL while still returning CL_SUCCESS. Callers that pass a profile conditionally (develop/blend.c does) must therefore not assume a successful return means a valid device buffer.
devidOpenCL device.
_profile_info_clout: host-side packed struct, always allocated.
_profile_lut_clout: host-side flattened curves.
_dev_profile_infoout: device constant buffer, or NULL as described above.
_dev_profile_lutout: device image holding the curves.
Returns
CL_SUCCESS, or a cl_int error. On error the out-parameters still carry whatever was allocated before the failure, so the free function must be called either way.
Warning
The device LUT image is hardcoded 256 x (256*6), which equals 6 * lutsize ONLY for the default lutsize of 65536. A profile built with a different lutsize would upload the wrong amount of data with no diagnostic.

Definition at line 762 of file colorprofiles/iop_profile.c.

References cleanup(), dt_ioppr_get_profile_info_cl(), dt_ioppr_get_trc_cl(), dt_opencl_copy_host_to_device(), dt_opencl_copy_host_to_device_constant(), IS_NULL_PTR, and L.

Referenced by dt_develop_blend_process_cl(), and process_cl().

◆ dt_ioppr_cleanup_profile_info()

void dt_ioppr_cleanup_profile_info ( dt_iop_order_iccprofile_info_t **  profile_info)

Release a profile info: its tone-curve LUTs, the struct itself, and the caller's pointer – must be called when done with profile_info.

This owns the WHOLE teardown, not just the LUTs. A dt_iop_order_iccprofile_info_t owns six aligned float arrays, so releasing one is "free the curves, free the struct, drop the pointer" – three steps every caller used to open-code, and three chances to free the struct while leaving 1.5 MB of curves behind.

Parameters
profile_infoaddress OF the caller's pointer. Taken by address, not by value, so the caller's variable is NULLed here and cannot be left dangling. A NULL address, or an address holding NULL, is a no-op.
Warning
The struct is released with dt_free_align, so only a struct obtained from dt_alloc_align may be passed. Never pass a stack copy or a shallow memcpy of another instance – develop/blend.c makes exactly such a copy, and its aliased LUT pointers belong to the original.

Definition at line 624 of file colorprofiles/iop_profile.c.

References dt_free_align, i, IS_NULL_PTR, and L.

Referenced by dt_colorspaces_add_profile(), dt_colorspaces_flush_profile_memo(), dt_colorspaces_invalidate_display_profile_memo(), and dt_dev_pixelpipe_cleanup().

◆ dt_ioppr_clear_lut_curves()

__DT_CLONE_TARGETS__ void dt_ioppr_clear_lut_curves ( dt_iop_order_iccprofile_info_t profile_info)

Mark all six tone curves linear, by writing -1.0 into entry 0 of each.

The curve equivalent of the NaN matrix sentinel. Requires the six LUT arrays to be allocated already, i.e. dt_ioppr_init_profile_info() must have run.

Parameters
profile_infoprofile to clear. Dereferenced unguarded.

Definition at line 84 of file colorprofiles/iop_profile.c.

References i, and L.

Referenced by _generate_profile_info().

◆ dt_ioppr_free_iccprofile_params_cl()

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 
)

free parameters build with the previous function.

Releases both host allocations and both device buffers and NULLs all four caller variables, so it is idempotent and safe on a partially-built set (which is what an error return from dt_ioppr_build_iccprofile_params_cl() leaves behind).

Warning
Dereferences all four addresses unguarded – pass addresses of real variables, never NULL.

Definition at line 817 of file colorprofiles/iop_profile.c.

References dt_free, dt_opencl_release_mem_object(), and L.

Referenced by dt_develop_blend_process_cl(), and process_cl().

◆ dt_ioppr_get_profile_info_cl()

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 
)

sets profile_info_cl using profile_info, to be used as a parameter when calling opencl.

Parameters
profile_infosource, host side. Dereferenced unguarded.
profile_info_cldestination, caller-provided storage (a stack struct is the usual case). Every field is written, so it needs no prior initialisation.
Note
Copies the scalars only. The tone curves are dt_ioppr_get_trc_cl()'s job.

Definition at line 726 of file colorprofiles/iop_profile.c.

References i, and L.

Referenced by dt_colorspaces_apply_profile_cl(), dt_ioppr_build_iccprofile_params_cl(), and dt_ioppr_transform_image_colorspace_rgb_cl().

◆ dt_ioppr_get_trc_cl()

cl_float * dt_ioppr_get_trc_cl ( const dt_iop_order_iccprofile_info_t *const  profile_info)

returns the profile_info trc, to be used as a parameter when calling opencl.

Flattens the six tone curves into one contiguous array, lut_in[0..2] then lut_out[0..2], profile_info->lutsize floats each.

Returns
A newly malloced array of 6 * lutsize floats that the CALLER owns and frees with dt_free (the CL param helpers below do it for you). NULL if the allocation failed – which callers in this file do not check.

Definition at line 746 of file colorprofiles/iop_profile.c.

References L, and x.

Referenced by dt_colorspaces_apply_profile_cl(), dt_ioppr_build_iccprofile_params_cl(), and dt_ioppr_transform_image_colorspace_rgb_cl().

◆ dt_ioppr_init_profile_info()

__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 using profile_info, default lutsize = 0.

Sets type = DT_COLORSPACE_NONE, marks the matrices non-matrix (NaN) and the six curves linear ([0] = -1), and ALLOCATES the six LUT arrays with dt_alloc_align_float – so this is not a cheap "zero the struct" call: it is where the ~1.5 MB comes from, and it must be paired with dt_ioppr_cleanup_profile_info() or every byte of it leaks.

Parameters
profile_infostruct to initialise. Not NULL-checked, and not allocated here: the caller allocates (with dt_alloc_align, since teardown uses dt_free_align).
lutsizeentries per tone curve, or 0 for the default of 65536. Every caller in the tree passes 0, which is also what the OpenCL upload path assumes.
Warning
Do not call this twice on the same struct: it overwrites the six LUT pointers without freeing the previous arrays.

Definition at line 602 of file colorprofiles/iop_profile.c.

References dt_alloc_align_float(), DT_COLORSPACE_NONE, DT_INTENT_PERCEPTUAL, DT_IOPPR_LUT_SAMPLES, i, L, and lutsize.

Referenced by dt_colorspaces_add_profile(), and dt_ioppr_set_pipe_input_profile_info().

◆ dt_ioppr_init_unbounded_coeffs()

int dt_ioppr_init_unbounded_coeffs ( float *  lutr,
float *  lutg,
float *  lutb,
float *  unbounded_coeffsr,
float *  unbounded_coeffsg,
float *  unbounded_coeffsb,
const int  lutsize 
)
inline

Fit the power-law continuation of three tone curves past white.

For each channel whose curve is not marked linear, samples it at x = 0.7, 0.8, 0.9, 1.0 and fits b * (a*x)^c, which eval_exp() then evaluates above 1.0. This is what makes the pipeline able to carry values above white through an encoding curve defined only on [0,1].

Parameters
lutr,lutg,lutbthe three curves, lutsize entries each. A curve whose [0] is negative is skipped and its coefficients marked -1.
unbounded_coeffsr,unbounded_coeffsg,unbounded_coeffsbout: three floats each.
lutsizeentry count.
Returns
the COUNT (0..3) of channels that actually got a fit – which is what callers store into profile_info->nonlinearlut and then read as a boolean.

Definition at line 303 of file colorprofiles/iop_profile.c.

References dt_iop_estimate_exp(), k, L, lut, lutsize, unbounded_coeffs, and x.

Referenced by _generate_profile_info(), and dt_colorspaces_prepare_conversion().

◆ dt_ioppr_transform_image_colorspace_rgb()

◆ dt_ioppr_transform_image_colorspace_rgb_cl()

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 
)

OpenCL counterpart of dt_ioppr_transform_image_colorspace_rgb().

Same dispatch: both profiles reduced to matrices means one pre-multiplied matrix and the colorspaces_transform_rgb_matrix_to_rgb kernel; otherwise the buffer is read back, converted on the CPU by dt_ioppr_transform_image_colorspace_rgb(), and written back. Unlike dt_colorspaces_apply_profile_cl(), in-place IS supported: when dev_img_in == dev_img_out it allocates a device scratch image and copies through it.

Returns
TRUE on success. FALSE on any OpenCL error AND on the "either profile is DT_COLORSPACE_NONE" refusal – so a FALSE does not distinguish a device failure from a caller passing an unset profile. Identical source and destination profiles return TRUE after a device-side image copy.
Warning
Both profile pointers are dereferenced unguarded.

Definition at line 840 of file colorprofiles/iop_profile.c.

References _colorspaces_cl_global, ch, cleanup(), dt_colormatrix_mul(), DT_COLORSPACE_NONE, DT_DEBUG_PERF, dt_free, dt_get_debug_flags(), dt_get_times(), dt_ioppr_get_profile_info_cl(), dt_ioppr_get_trc_cl(), dt_ioppr_transform_image_colorspace_rgb(), dt_opencl_alloc_device(), dt_opencl_copy_device_to_host(), dt_opencl_copy_host_to_device(), dt_opencl_copy_host_to_device_constant(), dt_opencl_enqueue_copy_image(), dt_opencl_enqueue_kernel_2d(), dt_opencl_release_mem_object(), dt_opencl_set_kernel_arg(), dt_opencl_write_host_to_device(), dt_pixelpipe_cache_alloc_align_float_cache, dt_pixelpipe_cache_free_align, FALSE, height, IS_NULL_PTR, dt_colorspaces_cl_global_t::kernel_colorspaces_transform_rgb_matrix_to_rgb, L, matrix, pack_3xSSE_to_3x4(), ROUNDUPDHT, ROUNDUPDWD, TRUE, and width.

Referenced by process_cl().

◆ dt_ioppr_transform_lcms2()

void dt_ioppr_transform_lcms2 ( const char *  op,
const char *  multi_name,
const float *const  image_in,
float *const  image_out,
const int  width,
const int  height,
const dt_iop_colorspace_type_t  cst_from,
const dt_iop_colorspace_type_t  cst_to,
dt_iop_colorspace_type_t converted_cst,
const dt_iop_order_iccprofile_info_t *const  profile_info 
)

The lcms2 branch of dt_colorspaces_apply_profile(): RGB <-> Lab via cmsDoTransform.

Resolves the profile by identity out of the shared list, builds a cmsHTRANSFORM, runs it over the buffer and deletes it – so the transform is rebuilt on EVERY call, which is why this is the fallback and not the default. It takes dt_colorspaces_lock_profiles() itself, across resolve-through-cmsCreateTransform, when the profile is DT_COLORSPACE_DISPLAY, because that handle can be closed and replaced by a monitor change mid-flight.

Parameters
opmodule op string, for the -d dev trace only.
multi_namemodule multi_name string, same.
image_in,image_out4-float pixels; may be the same buffer.
width,heightbuffer geometry.
cst_from,cst_tosource and destination colorspaces. Only RGB <-> Lab is supported; anything else leaves *converted_cst == cst_from and logs to stderr.
converted_cstout: cst_to on success, cst_from on refusal.
profile_infoprofile identity to resolve. Only type, filename and intent are read – the matrices and LUTs are ignored on this path. A type of DT_COLORSPACE_NONE silently substitutes linear Rec2020 here, unlike dt_colorspaces_apply_profile(), which refuses it before ever getting this far.

Definition at line 257 of file colorprofiles/iop_profile.c.

References _transform_from_to_rgb_lab_lcms2(), DT_DEBUG_DEV, dt_iop_colorspace_is_rgb(), dt_print(), height, IOP_CS_LAB, L, and width.

Referenced by dt_colorspaces_apply_profile().

◆ dt_ioppr_transform_matrix()

void dt_ioppr_transform_matrix ( const char *  op,
const char *  multi_name,
const float *const restrict  image_in,
float *const restrict  image_out,
const int  width,
const int  height,
const dt_iop_colorspace_type_t  cst_from,
const dt_iop_colorspace_type_t  cst_to,
dt_iop_colorspace_type_t converted_cst,
const dt_iop_order_iccprofile_info_t *const  profile_info 
)
inline

Variable Documentation

◆ _colorspaces_cl_global

◆ _profile_info_lock

◆ _profile_info_memo