58#include <glib/gi18n.h>
86 for(
int i = 0;
i < 3;
i++)
95 const char *filename,
const int intent,
const int direction)
97 cmsHTRANSFORM *xform =
NULL;
115 fprintf(
stderr,
"working profile color space `%c%c%c%c' not supported\n",
126 fprintf(
stderr,
_(
"unsupported working profile %s has been replaced by Rec2020 RGB!\n"), filename);
160 fprintf(
stderr,
"[_transform_from_to_rgb_lab_lcms2] cannot create transform\n");
171 cmsHTRANSFORM *xform =
NULL;
196 fprintf(
stderr,
"[_transform_rgb_to_rgb_lcms2] invalid from profile\n");
205 fprintf(
stderr,
"[_transform_rgb_to_rgb_lcms2] invalid to profile\n");
213 fprintf(
stderr,
"[_transform_rgb_to_rgb_lcms2] profile color space `%c%c%c%c' not supported\n",
224 fprintf(
stderr,
"[_transform_rgb_to_rgb_lcms2] profile color space `%c%c%c%c' not supported\n",
252 fprintf(
stderr,
"[_transform_rgb_to_rgb_lcms2] cannot create transform\n");
274 "[dt_ioppr_transform_lcms2] transfoming from RGB to Lab (%s %s)\n", op, multi_name);
281 "[dt_ioppr_transform_lcms2] transfoming from Lab to RGB (%s %s)\n", op, multi_name);
306 int nonlinearlut = 0;
310 for(
int k = 0;
k < 3;
k++)
313 if(
lut[
k][0] >= 0.0f)
348 if((
lut[0][0] >= 0.0f) && (
lut[1][0] >= 0.0f) && (
lut[2][0] >= 0.0f))
351 for(
size_t k = 0;
k < stride;
k +=
ch)
353 for(
int c = 0; c < 3; c++)
359 else if((
lut[0][0] >= 0.0f) || (
lut[1][0] >= 0.0f) || (
lut[2][0] >= 0.0f))
362 for(
size_t k = 0;
k < stride;
k +=
ch)
364 for(
int c = 0; c < 3; c++)
366 if(
lut[c][0] >= 0.0f)
396 for(
size_t y = 0; y < stride; y +=
ch)
408 for(
size_t y = 0; y < stride; y +=
ch)
435 for(
size_t y = 0; y < stride; y +=
ch)
441 const float alpha =
in[3];
497 for(
size_t y = 0; y < stride; y += 4)
506 for(
size_t c = 0; c < 3; c++)
528 for(
size_t c = 0; c < 3; c++)
553 for(
size_t y = 0; y < stride; y += 4)
599#define DT_IOPPR_LUT_SAMPLES 0x10000
613 for(
int i = 0;
i < 3;
i++)
622#undef DT_IOPPR_LUT_SAMPLES
633 for(
int i = 0;
i < 3;
i++)
636 (*profile_info)->lut_in[
i] =
NULL;
638 (*profile_info)->lut_out[
i] =
NULL;
675 fprintf(
stderr,
"image colorspace transform RGB-->RGB took %.3f secs (%.3f CPU) [%s]\n",
686 fprintf(
stderr,
"image colorspace transform RGB-->RGB took %.3f secs (%.3f lcms2) [%s]\n",
704 const int program = 23;
706 g->kernel_colorspaces_transform_rgb_matrix_to_lab =
dt_opencl_create_kernel(program,
"colorspaces_transform_rgb_matrix_to_lab");
707 g->kernel_colorspaces_transform_rgb_matrix_to_rgb
728 for(
int i = 0;
i < 9;
i++)
734 for(
int i = 0;
i < 3;
i++)
736 for(
int j = 0;
j < 3;
j++)
752 for(
int c = 0; c < 3; c++)
755 for(
int c = 0; c < 3; c++)
782 fprintf(
stderr,
"[dt_ioppr_build_iccprofile_params_cl] error allocating memory 5\n");
790 fprintf(
stderr,
"[dt_ioppr_build_iccprofile_params_cl] error allocating memory 6\n");
802 fprintf(
stderr,
"[dt_ioppr_build_iccprofile_params_cl] error allocating memory 7\n");
857 size_t origin[] = { 0, 0, 0 };
864 "[dt_ioppr_transform_image_colorspace_rgb_cl] error on copy image for color transformation\n");
899 size_t origin[] = { 0, 0, 0 };
920 "[dt_ioppr_transform_image_colorspace_rgb_cl] error allocating memory for color transformation 4\n");
929 "[dt_ioppr_transform_image_colorspace_rgb_cl] error on copy image for color transformation\n");
943 "[dt_ioppr_transform_image_colorspace_rgb_cl] error allocating memory for color transformation 5\n");
951 "[dt_ioppr_transform_image_colorspace_rgb_cl] error allocating memory for color transformation 6\n");
961 "[dt_ioppr_transform_image_colorspace_rgb_cl] error allocating memory for color transformation 7\n");
969 "[dt_ioppr_transform_image_colorspace_rgb_cl] error allocating memory for color transformation 8\n");
979 "[dt_ioppr_transform_image_colorspace_rgb_cl] error allocating memory for color transformation 7\n");
999 "[dt_ioppr_transform_image_colorspace_rgb_cl] error %i enqueue kernel for color transformation\n",
1007 fprintf(
stderr,
"image colorspace transform RGB-->RGB took %.3f secs (%.3f GPU) [%s]\n",
1019 "[dt_ioppr_transform_image_colorspace_rgb_cl] error allocating memory for color transformation 1\n");
1028 "[dt_ioppr_transform_image_colorspace_rgb_cl] error allocating memory for color transformation 2\n");
1040 "[dt_ioppr_transform_image_colorspace_rgb_cl] error allocating memory for color transformation 3\n");
1064#undef DT_IOP_ORDER_PROFILE
1165 fprintf(
stderr,
"working profile color space `%c%c%c%c' not supported\n",
1337 fprintf(
stderr,
"image colorspace transform %s-->%s took %.3f secs (%.3f CPU) [%s %s]\n",
1350 fprintf(
stderr,
"image colorspace transform %s-->%s took %.3f secs (%.3f lcms2) [%s %s]\n",
1394 const size_t ch = 4;
1433 fprintf(
stderr,
"[dt_colorspaces_apply_profile_cl] error allocating memory for color transformation 5\n");
1440 fprintf(
stderr,
"[dt_colorspaces_apply_profile_cl] error allocating memory for color transformation 6\n");
1456 fprintf(
stderr,
"[dt_colorspaces_apply_profile_cl] error %i enqueue kernel for color transformation\n",
err);
1465 fprintf(
stderr,
"image colorspace transform %s-->%s took %.3f secs (%.3f GPU) [%s %s]\n",
1477 fprintf(
stderr,
"[dt_colorspaces_apply_profile_cl] error allocating memory for color transformation 1\n");
1485 fprintf(
stderr,
"[dt_colorspaces_apply_profile_cl] error allocating memory for color transformation 2\n");
1496 fprintf(
stderr,
"[dt_colorspaces_apply_profile_cl] error allocating memory for color transformation 3\n");
void cleanup(dt_imageio_module_format_t *self)
void output_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
void input_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
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)
static dt_colorspaces_cl_global_t * _colorspaces_cl_global
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.
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.
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 ca...
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)
#define DT_IOPPR_LUT_SAMPLES
void dt_colorspaces_init_cl_global(void)
Compile the colorspace kernels. Called once by common/opencl.c at device init.
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.
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)
static int _generate_profile_info(dt_iop_order_iccprofile_info_t *profile_info, const int type, const char *filename, const int intent)
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.
__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...
static pthread_mutex_t _profile_info_lock
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.
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 GList * _profile_info_memo
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_colorspaces_free_cl_global(void)
Release the kernels and the struct from dt_colorspaces_init_cl_global(). NULL-safe.
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.
__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 _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)
void dt_colorspaces_invalidate_display_profile_memo(void)
Drop the memoised DT_COLORSPACE_DISPLAY entry, whose source profile this module replaces on a monitor...
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.
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)
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().
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_colorspaces_flush_profile_memo(void)
Drop every memoised entry. Called by dt_colorprofiles_cleanup().
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.
The colour-profile struct and the maths over it: the derived matrix/LUT engine.
static dt_aligned_pixel_t float *const const float unbounded_coeffs[3][3]
const float const int lutsize
void dt_colorspaces_unlock_profile(const dt_colorspaces_color_profile_t *const profile)
__DT_CLONE_TARGETS__ void dt_colorspaces_transform_rgba_float_image(const cmsHTRANSFORM transform, const float *image_in, float *image_out, const int width, const int height)
Run a caller-owned LCMS transform over a whole RGBA float image, one OpenMP task per row.
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_lock_profile(const dt_colorspaces_color_profile_t *const profile)
The colour-profile module's API: which profiles exist, and how to apply one.
static dt_aligned_pixel_t rgb
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
void * dt_alloc_align(size_t size)
static void dt_iop_estimate_exp(const float *const x, const float *const y, const int num, float *coeff)
_lib_location_type_t type
int32_t dt_get_debug_flags(void)
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 pack_3xSSE_to_3x4(const dt_colormatrix_t input, float output[12])
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)
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
int dt_opencl_copy_device_to_host(const int devid, void *host, void *device, const int width, const int height, const int bpp)
void * dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
int dt_opencl_create_kernel(const int prog, const char *name)
void * dt_opencl_copy_host_to_device_constant(const int devid, const size_t size, void *host)
int dt_opencl_enqueue_copy_image(const int devid, cl_mem src, cl_mem dst, size_t *orig_src, size_t *orig_dst, size_t *region)
void dt_opencl_free_kernel(const int kernel)
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
void * dt_opencl_copy_host_to_device(const int devid, void *host, const int width, const int height, const int bpp)
void dt_opencl_release_mem_object(cl_mem mem)
int dt_opencl_write_host_to_device(const int devid, void *host, void *device, const int width, const int height, const int bpp)
#define dt_omploop_sfence()
#define __OMP_PARALLEL_FOR__(...)
#define __OMP_PARALLEL_FOR_SIMD__(...)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
dt_colorspaces_color_profile_type_t
@ DT_COLORSPACE_DISPLAY
The monitor profile – the one list entry that mutates after init.
@ DT_COLORSPACE_NONE
No profile / "take it from the image settings". Never matches a list entry.
@ DT_COLORSPACE_LIN_REC2020
@ DT_PROFILE_ROLE_WORKING
Listed in the working-profile combo (colorin).
@ DT_PROFILE_ROLE_ANY
All four roles, in registration order.
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
#define for_each_channel(_var,...)
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...
The three colorspace kernels, compiled once and held by common/opencl.c.
int kernel_colorspaces_transform_rgb_matrix_to_rgb
int kernel_colorspaces_transform_lab_to_rgb_matrix
int kernel_colorspaces_transform_rgb_matrix_to_lab
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
The device-side view of a dt_iop_order_iccprofile_info_t: the scalar fields only.
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__
static void dt_get_times(dt_times_t *t)