155 for(
int c = 0; c < 3; c++)
166 for(
int c = 0; c < 3; c++)
398 v[0] =
CLAMP(
v[0], 0.0f, 1.0f);
399 v[1] =
CLAMP(
v[1], 0.0f, 1.0f);
400 v[2] =
CLAMP(
v[2], 0.0f, 1.0f);
417 const float *
const coeff0 = c->coeffs_target[0];
418 const float *
const coeff1 = c->coeffs_target[1];
419 const float *
const coeff2 = c->coeffs_target[2];
426 const size_t idx = 4 *
k;
437 const size_t idx = 4 *
k;
470 const gboolean
decode = !
IS_NULL_PTR(c->lut_source[0]) && c->nonlinear_source > 0;
471 const gboolean
encode = !
IS_NULL_PTR(c->lut_target[0]) && c->nonlinear_target > 0;
472 const gboolean
clipping = c->has_clipping;
483 const size_t idx = 4 *
k;
494 const size_t idx = 4 *
k;
550 const cmsHTRANSFORM xform = c->xform;
551 const cmsHTRANSFORM clip_xform = c->clip_xform;
552 const gboolean
clipping = c->has_clipping;
553 const gboolean gamutcheck = c->gamutcheck;
568 hook(source + 4 *
j, target + 4 *
j);
569 target[4 *
j + 3] = 0.0f;
593 if(target[4 *
j + 0] < 0.0f || target[4 *
j + 1] < 0.0f || target[4 *
j + 2] < 0.0f)
595 target[4 *
j + 0] = 0.0f;
596 target[4 *
j + 1] = 1.0f;
597 target[4 *
j + 2] = 1.0f;
605 const float *
const in,
float *
const out,
const size_t width,
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.
The colour-profile struct and the maths over it: the derived matrix/LUT engine.
void dt_colorspaces_unlock_profile(const dt_colorspaces_color_profile_t *const profile)
const dt_colorspaces_color_profile_t * dt_colorspaces_get_profile(dt_colorspaces_color_profile_type_t type, const char *filename, dt_colorspaces_profile_role_t role)
Resolve a profile identity to its registered entry.
int dt_colorspaces_get_matrix_from_output_profile(cmsHPROFILE prof, dt_colormatrix_t matrix, float *lutr, float *lutg, float *lutb, const int lutsize)
Extract the XYZ->profile matrix and the inverse tone curves from an OUTPUT profile.
int dt_colorspaces_get_matrix_from_input_profile(cmsHPROFILE prof, dt_colormatrix_t matrix, float *lutr, float *lutg, float *lutb, const int lutsize)
Extract the profile->XYZ matrix and the per-channel tone curves from an INPUT profile.
void dt_colorspaces_cleanup_profile(cmsHPROFILE p)
Close a profile created by any of the dt_colorspaces_create_* / dt_colorspaces_get_rgb_profile_from_m...
void dt_colorspaces_lock_profile(const dt_colorspaces_color_profile_t *const profile)
void dt_colorspaces_transform_rgba_float_row(const cmsHTRANSFORM transform, const float *in, float *out, const int width)
Run a caller-owned LCMS transform over one row of RGBA float pixels.
The colour-profile module's API: which profiles exist, and how to apply one.
#define TYPE_XYZA_FLT
lcms2 pixel format for float XYZ + one extra channel.
const dt_colormatrix_t dt_aligned_pixel_t out
dt_store_simd_aligned(out, dt_mat3x4_mul_vec4(vin, dt_colormatrix_row_to_simd(matrix, 0), dt_colormatrix_row_to_simd(matrix, 1), dt_colormatrix_row_to_simd(matrix, 2)))
const dt_colormatrix_t matrix
static cmsHPROFILE _resolve_endpoint(const dt_colorspaces_endpoint_t *const endpoint, const dt_colorspaces_color_profile_t **entry)
const float * dt_colorspaces_conversion_source_coeffs(const dt_colorspaces_conversion_t *const conversion)
The 3x3 power-law fits extrapolating the source curves past white, as one flat array of 9 floats in c...
static gboolean _allocate_curves(float *lut[3])
void dt_colorspaces_apply_conversion_hooked(const dt_colorspaces_conversion_t *const conversion, const float *const in, float *const out, const size_t width, const size_t height, const dt_colorspaces_conversion_hook_t hook)
dt_colorspaces_apply_conversion() with a per-pixel hook. See dt_colorspaces_conversion_hook_t for why...
gboolean dt_colorspaces_conversion_has_clipping(const dt_colorspaces_conversion_t *const conversion)
Whether the conversion has a gamut-clipping stage, i.e. whether a clip endpoint was given AND survive...
gboolean dt_colorspaces_conversion_matrix(const dt_colorspaces_conversion_t *const conversion, dt_colormatrix_t matrix)
The composed source-to-target matrix, row-major.
const float * dt_colorspaces_conversion_target_curve(const dt_colorspaces_conversion_t *const conversion, const int channel)
One channel of the target encoding curves. Same contract as dt_colorspaces_conversion_source_curve().
static __DT_CLONE_TARGETS__ void _apply_target_curves(const dt_colorspaces_conversion_t *const c, float *const restrict out, const size_t npixels)
gboolean dt_colorspaces_conversion_is_matrix(const dt_colorspaces_conversion_t *const conversion)
Whether the conversion reduced to matrices and curves, and can therefore be run by a device kernel at...
const float * dt_colorspaces_conversion_target_coeffs(const dt_colorspaces_conversion_t *const conversion)
The same fits for the target curves. Same contract.
static __DT_CLONE_TARGETS__ void _apply_matrix(const dt_colorspaces_conversion_t *const c, const float *const restrict in, float *const restrict out, const size_t npixels, const dt_colorspaces_conversion_hook_t hook)
static __DT_CLONE_TARGETS__ void _apply_lcms2(const dt_colorspaces_conversion_t *const c, const float *const in, float *const out, const size_t width, const size_t height, const dt_colorspaces_conversion_hook_t hook)
static cmsUInt32Number _format_for(cmsHPROFILE profile, gboolean *supported)
gboolean dt_colorspaces_conversion_source_matrix(const dt_colorspaces_conversion_t *const conversion, dt_colormatrix_t matrix)
The SOURCE profile's own RGB -> XYZ (D50) matrix, before composition.
static void _free_curves(float *lut[3])
const float * dt_colorspaces_conversion_source_curve(const dt_colorspaces_conversion_t *const conversion, const int channel)
One channel of the source decoding curves, DT_CONVERSION_LUT_SAMPLES entries.
static cmsHPROFILE _quantise_profile(cmsHPROFILE profile)
void dt_colorspaces_free_conversion(dt_colorspaces_conversion_t **conversion)
Release a conversion and NULL the caller's pointer.
gboolean dt_colorspaces_conversion_clip_matrix(const dt_colorspaces_conversion_t *const conversion, dt_colormatrix_t matrix)
The clip-to-target matrix, the second leg of a clipping conversion.
dt_colorspaces_conversion_t * dt_colorspaces_prepare_conversion(const dt_colorspaces_endpoint_t *const from, const dt_colorspaces_endpoint_t *const to, const dt_colorspaces_endpoint_t *const clip, const dt_colorspaces_endpoint_t *const proof, const dt_iop_color_intent_t intent, const dt_colorspaces_conversion_flags_t flags)
Build a conversion from from to to. The expensive call; do it once.
void dt_colorspaces_apply_conversion(const dt_colorspaces_conversion_t *const conversion, const float *const in, float *const out, const size_t width, const size_t height)
Convert a 4-channel float image through a prepared conversion.
A PREPARED CONVERSION: everything needed to turn pixels in one colour space into pixels in another,...
dt_colorspaces_conversion_flags_t
What the caller wants, and what the caller can consume.
@ DT_CONVERSION_FORCE_LCMS2
Never take the matrix path, even when both profiles reduce to matrices. Backs the plugins/lighttable/...
@ DT_CONVERSION_SOURCE_CURVES
The caller can apply the SOURCE profile's decoding curves before the matrix. Without this,...
@ DT_CONVERSION_GAMUTCHECK
Mark out-of-gamut pixels rather than merely proofing them. Requires a soft-proof endpoint,...
@ DT_CONVERSION_TARGET_CURVES
The caller can apply the TARGET profile's encoding curves after the matrix. Without this,...
void(* dt_colorspaces_conversion_hook_t)(const float *const in, float *const out)
A per-pixel hook run between the source curves and the colour conversion proper.
#define DT_CONVERSION_LUT_SAMPLES
Entries per tone curve. Callers that upload the curves to a device need this to size the buffer; the ...
int supported(struct dt_imageio_module_storage_t *storage, struct dt_imageio_module_format_t *format)
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
float DT_ALIGNED_ARRAY dt_colormatrix_t[4][4]
static void transpose_3xSSE(const dt_colormatrix_t input, dt_colormatrix_t output)
static void dt_colormatrix_mul(dt_colormatrix_t dst, const dt_colormatrix_t m1, const dt_colormatrix_t m2)
#define dt_free_align(ptr)
static float * dt_alloc_align_float(size_t pixels)
dt_mipmap_buffer_dsc_flags flags
#define __OMP_SIMD__(...)
#define dt_omploop_sfence()
#define __OMP_PARALLEL_FOR__(...)
#define __OMP_PARALLEL_FOR_SIMD__(...)
dt_iop_color_intent_t
ICC rendering intent, as stored in iop params and in conf.
dt_colorspaces_color_profile_type_t
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
One registered profile: its identity, its LCMS handle, and where it sits in each combo box.
cmsHPROFILE profile
the actual profile; NULL for the three category entries
dt_colormatrix_t clip_matrix
clip -> target; meaningless unless has_clipping
dt_colormatrix_t source_matrix
gboolean have_source_matrix
dt_colorspaces_color_profile_type_t from_type
float coeffs_target[3][3]
dt_colormatrix_t matrix
source -> target, or source -> clip when clipping
cmsHTRANSFORM clip_xform
clip -> target; NULL unless has_clipping
float coeffs_source[3][3]
9 contiguous floats: what the kernels upload verbatim
cmsHTRANSFORM xform
source -> target, or source -> clip when clipping
float * lut_source[3]
NULL when this conversion has no source curve stage.
dt_colorspaces_color_profile_type_t to_type
One end of a conversion: a profile, named either by identity or by handing over one this module alrea...
#define __DT_CLONE_TARGETS__