78#include <gdk/gdkkeysyms.h>
85#define DT_IOP_COLOR_ICC_LEN 512
86#define LUT_SAMPLES 0x10000
116 return _(
"output color profile");
123 "using color profiles to remap RGB values"),
125 _(
"linear or non-linear, RGB or Lab, display-referred"),
126 _(
"defined by profile"),
127 _(
"non-linear, RGB or Lab, display-referred"));
185 void *new_params,
const int new_version)
187#define DT_IOP_COLOR_ICC_LEN_V4 100
196 if((old_version == 2 || old_version == 3) && new_version == 5)
198 typedef struct dt_iop_colorout_params_v3_t
204 char softproof_enabled;
207 } dt_iop_colorout_params_v3_t;
210 dt_iop_colorout_params_v3_t *o = (dt_iop_colorout_params_v3_t *)old_params;
214 if(!strcmp(o->iccprofile,
"sRGB"))
216 else if(!strcmp(o->iccprofile,
"linear_rec709_rgb") || !strcmp(o->iccprofile,
"linear_rgb"))
218 else if(!strcmp(o->iccprofile,
"linear_rec2020_rgb"))
220 else if(!strcmp(o->iccprofile,
"adobergb"))
222 else if(!strcmp(o->iccprofile,
"X profile"))
227 g_strlcpy(
n->filename, o->iccprofile,
sizeof(
n->filename));
230 n->intent = o->intent;
234 if(old_version == 4 && new_version == 5)
236 typedef struct dt_iop_colorout_params_v4_t
241 } dt_iop_colorout_params_v4_t;
244 dt_iop_colorout_params_v4_t *o = (dt_iop_colorout_params_v4_t *)old_params;
249 g_strlcpy(
n->filename, o->filename,
sizeof(
n->filename));
250 n->intent = o->intent;
256#undef DT_IOP_COLOR_ICC_LEN_V4
261 const int program = 2;
278 float *
const restrict
out,
const size_t npixels)
280 const int run_lut0 =
d->lut[0][0] >= 0.0f;
281 const int run_lut1 =
d->lut[1][0] >= 0.0f;
282 const int run_lut2 =
d->lut[2][0] >= 0.0f;
283 if(!(run_lut0 || run_lut1 || run_lut2))
return;
285 const float *
const lut0 =
d->lut[0];
286 const float *
const lut1 =
d->lut[1];
287 const float *
const lut2 =
d->lut[2];
288 const float *
const coeff0 =
d->unbounded_coeffs[0];
289 const float *
const coeff1 =
d->unbounded_coeffs[1];
290 const float *
const coeff2 =
d->unbounded_coeffs[2];
292 if(run_lut0 && run_lut1 && run_lut2)
295 for(
size_t k = 0;
k < npixels;
k++)
297 const size_t idx = 4 *
k;
306 for(
size_t k = 0;
k < npixels;
k++)
308 const size_t idx = 4 *
k;
309 if(run_lut0)
out[idx + 0] = dt_ioppr_eval_trc(
out[idx + 0], lut0, coeff0,
LUT_SAMPLES);
310 if(run_lut1)
out[idx + 1] = dt_ioppr_eval_trc(
out[idx + 1], lut1, coeff1,
LUT_SAMPLES);
311 if(run_lut2)
out[idx + 2] = dt_ioppr_eval_trc(
out[idx + 2], lut2, coeff2,
LUT_SAMPLES);
322 cl_mem dev_m = NULL, dev_r = NULL, dev_g = NULL, dev_b = NULL, dev_coeffs = NULL;
325 const int devid = pipe->
devid;
331 size_t origin[] = { 0, 0, 0 };
332 size_t region[] = { roi_in->
width, roi_in->
height, 1 };
334 if(err != CL_SUCCESS)
goto error;
363 if(err != CL_SUCCESS)
goto error;
385 const size_t npixels,
386 const dt_aligned_pixel_simd_t cm0,
387 const dt_aligned_pixel_simd_t cm1,
388 const dt_aligned_pixel_simd_t cm2,
389 const int use_nontemporal)
392 for(
size_t k = 0;
k < npixels;
k++)
394 const size_t idx = 4 *
k;
395 const dt_aligned_pixel_simd_t vin = dt_load_simd_aligned(in + idx);
396 const dt_aligned_pixel_simd_t vout = dt_mat3x4_mul_vec4(vin, cm0, cm1, cm2);
398 dt_store_simd_nontemporal(
out + idx, vout);
414 const size_t npixels = (size_t)roi_out->
width * roi_out->
height;
415 float *
const restrict
out = (
float *)
ovoid;
421 else if(!isnan(
d->cmatrix[0][0]))
425 const int use_nontemporal
426 = (
d->lut[0][0] < 0.0f) && (
d->lut[1][0] < 0.0f) && (
d->lut[2][0] < 0.0f);
429 const dt_aligned_pixel_simd_t cm0 = dt_colormatrix_row_to_simd(cmatrix, 0);
430 const dt_aligned_pixel_simd_t cm1 = dt_colormatrix_row_to_simd(cmatrix, 1);
431 const dt_aligned_pixel_simd_t cm2 = dt_colormatrix_row_to_simd(cmatrix, 2);
441 const cmsHTRANSFORM xform =
d->xform;
445 const float *in = ((
float *)ivoid) + (size_t)4 *
k * roi_out->
width;
446 float *
const restrict outp =
out + (size_t)4 *
k * roi_out->
width;
452 for(
int j = 0; j < roi_out->
width; j++)
454 if(outp[4*j+0] < 0.0f || outp[4*j+1] < 0.0f || outp[4*j+2] < 0.0f)
472 cmsUInt32Number
size;
473 cmsHPROFILE old_profile = profile;
476 if(old_profile && cmsSaveProfileToMem(old_profile, NULL, &
size))
478 char *data = malloc(
size);
480 if(cmsSaveProfileToMem(old_profile, data, &
size))
481 profile = cmsOpenProfileFromMem(data,
size);
497 const int force_lcms2 =
dt_conf_get_bool(
"plugins/lighttable/export/force_lcms2");
500 gchar *out_filename = NULL;
504 const char *work_filename =
"";
506 cmsHPROFILE input = NULL;
507 cmsHPROFILE output = NULL;
508 cmsHPROFILE softproof = NULL;
520 cmsDeleteTransform(
d->xform);
523 d->cmatrix[0][0] = NAN;
524 d->lut[0][0] = -1.0f;
525 d->lut[1][0] = -1.0f;
526 d->lut[2][0] = -1.0f;
545 p->type = icc_input->
type;
546 g_strlcpy(
p->filename, icc_input->
filename,
sizeof(
p->filename));
559 if(icc_input)
p->intent = icc_input->
intent;
563 out_filename =
p->filename;
564 out_intent =
p->intent;
600 work_type = work_profile->
type;
601 work_filename = work_profile->
filename;
611 uint32_t transformFlags = 0;
630 gboolean new_profile;
642 dt_control_log(_(
"missing output profile has been replaced by sRGB!"));
643 fprintf(stderr,
"missing output profile `%s' has been replaced by sRGB!\n",
651 if(in_profile) input = in_profile->
profile;
657 "[colorout] could not resolve pipeline work profile, assuming input is already in output profile\n");
676 dt_control_log(_(
"missing softproof profile has been replaced by sRGB!"));
677 fprintf(stderr,
"missing softproof profile `%s' has been replaced by sRGB!\n",
691 transformFlags |= cmsFLAGS_SOFTPROOFING | cmsFLAGS_NOCACHE | cmsFLAGS_BLACKPOINTCOMPENSATION;
709 && !isnan(work_profile->
matrix_in[0][0]));
712 if(can_use_fast_matrix)
719 d->cmatrix[0][0] = NAN;
722 if(isnan(
d->cmatrix[0][0]))
724 d->cmatrix[0][0] = NAN;
726 d->xform = cmsCreateProofingTransform(input, TYPE_RGBA_FLT, output,
output_format, softproof,
727 out_intent, INTENT_RELATIVE_COLORIMETRIC, transformFlags);
733 const char *
const unsupported_name
735 dt_control_log(_(
"unsupported output profile has been replaced by sRGB!"));
736 fprintf(stderr,
"unsupported output profile `%s' has been replaced by sRGB!\n", unsupported_name);
739 if(can_use_fast_matrix)
746 d->cmatrix[0][0] = NAN;
749 if(isnan(
d->cmatrix[0][0]))
751 d->cmatrix[0][0] = NAN;
754 d->xform = cmsCreateProofingTransform(input, TYPE_RGBA_FLT, output,
output_format, softproof,
755 out_intent, INTENT_RELATIVE_COLORIMETRIC, transformFlags);
766 for(
int k = 0;
k < 3;
k++)
769 if(
d->lut[
k][0] >= 0.0f)
771 const float x[4] = { 0.7f, 0.8f, 0.9f, 1.0f };
772 const float y[4] = { extrapolate_lut(
d->lut[
k],
x[0],
LUT_SAMPLES),
779 d->unbounded_coeffs[
k][0] = -1.0f;
808 cmsDeleteTransform(
d->xform);
821 module->hide_enable_button = 1;
822 module->default_enabled = 1;
833 self->
widget = gtk_label_new(NULL);
834 gtk_label_set_markup(GTK_LABEL(self->
widget),_(
"Convert images to the display or export RGB color space. "
835 "The color profile is set in the export module or in the display preferences. "));
836 gtk_widget_set_halign(self->
widget, GTK_ALIGN_START);
837 gtk_label_set_xalign (GTK_LABEL(self->
widget), 0.0f);
838 gtk_label_set_line_wrap(GTK_LABEL(self->
widget),
TRUE);
static void error(char *msg)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void init(dt_iop_module_t *module)
const char ** description(struct dt_iop_module_t *self)
static dt_iop_colorspace_type_t _colorout_input_format_cst(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe)
__DT_CLONE_TARGETS__ int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
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)
#define DT_IOP_COLOR_ICC_LEN
void gui_init(dt_iop_module_t *self)
static dt_iop_colorspace_type_t _colorout_output_format_cst(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe)
void cleanup_global(dt_iop_module_so_t *module)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
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)
dt_iop_colorout_gui_data_t dummy
static __DT_CLONE_TARGETS__ void process_fastpath_matrix(const float *const restrict in, float *const restrict out, const size_t npixels, const dt_aligned_pixel_simd_t cm0, const dt_aligned_pixel_simd_t cm1, const dt_aligned_pixel_simd_t cm2, const int use_nontemporal)
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void init_global(dt_iop_module_so_t *module)
static cmsHPROFILE _make_clipping_profile(cmsHPROFILE profile)
static __DT_CLONE_TARGETS__ void process_fastpath_apply_tonecurves(const dt_iop_colorout_data_t *const d, float *const restrict out, const size_t npixels)
int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
#define DT_IOP_COLOR_ICC_LEN_V4
gboolean runtime_data_hash(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
const dt_colorspaces_color_profile_t * dt_colorspaces_get_profile(dt_colorspaces_color_profile_type_t type, const char *filename, dt_colorspaces_profile_direction_t direction)
int dt_colorspaces_get_matrix_from_output_profile(cmsHPROFILE prof, dt_colormatrix_t matrix, float *lutr, float *lutg, float *lutb, const int lutsize)
const cmsHPROFILE dt_colorspaces_get_embedded_profile(const int32_t imgid, dt_colorspaces_color_profile_type_t *type, gboolean *new_profile)
void dt_colorspaces_cleanup_profile(cmsHPROFILE p)
const char * dt_colorspaces_get_name(dt_colorspaces_color_profile_type_t type, const char *filename)
void dt_colorspaces_transform_rgba_float_row(const cmsHTRANSFORM transform, const float *in, float *out, const int width)
dt_colorspaces_color_profile_type_t
@ DT_COLORSPACE_LIN_REC2020
@ DT_COLORSPACE_LIN_REC709
@ DT_PROFILE_DIRECTION_OUT
@ DT_PROFILE_DIRECTION_DISPLAY
@ DT_PROFILE_DIRECTION_ANY
dt_colorspaces_color_mode_t
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)))
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
int dt_conf_get_bool(const char *name)
void dt_control_log(const char *msg,...)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_free_align(ptr)
static void * dt_calloc_align(size_t size)
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR__(...)
#define __OMP_PARALLEL_FOR_SIMD__(...)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
static void dt_iop_image_copy_by_size(float *const __restrict__ out, const float *const __restrict__ in, const size_t width, const size_t height, const size_t ch)
void dt_iop_default_init(dt_iop_module_t *module)
const char ** dt_iop_set_description(dt_iop_module_t *module, const char *main_text, const char *purpose, const char *input, const char *process, const char *output)
void dt_iop_set_cache_bypass(dt_iop_module_t *module, gboolean state)
#define dt_omploop_sfence()
@ IOP_FLAGS_NO_HISTORY_STACK
#define IOP_GUI_ALLOC(module)
static void dt_iop_estimate_exp(const float *const x, const float *const y, const int num, float *coeff)
void dt_ioppr_get_work_profile_type(struct dt_develop_t *dev, dt_colorspaces_color_profile_type_t *profile_type, const char **profile_filename)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_work_profile_info(const struct dt_dev_pixelpipe_t *pipe)
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)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_input_profile_info(const struct dt_dev_pixelpipe_t *pipe)
static dt_aligned_pixel_t float *const const float unbounded_coeffs[3][3]
float *const restrict const size_t k
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)
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
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)
@ DT_DEV_PIXELPIPE_THUMBNAIL
@ DT_DEV_PIXELPIPE_EXPORT
struct dt_colorspaces_t * color_profiles
dt_colorspaces_color_profile_type_t softproof_type
pthread_rwlock_t xprofile_lock
dt_colorspaces_color_mode_t mode
char softproof_filename[512]
dt_colorspaces_color_profile_type_t display_type
char display_filename[512]
dt_iop_color_intent_t display_intent
struct dt_iop_module_t *void * data
dt_colorspaces_color_profile_type_t icc_type
dt_iop_color_intent_t icc_intent
dt_dev_pixelpipe_type_t type
struct dt_develop_t * dev
struct dt_dev_pixelpipe_t * virtual_pipe
dt_iop_buffer_type_t datatype
dt_colorspaces_color_mode_t mode
dt_colorspaces_color_profile_type_t type
dt_iop_color_intent_t intent
dt_colorspaces_color_profile_type_t type
dt_iop_global_data_t * data
struct dt_develop_t * dev
dt_iop_global_data_t * global_data
dt_iop_color_intent_t intent
dt_colorspaces_color_profile_type_t type
char filename[DT_IOP_COLOR_ICC_LEN]
dt_colormatrix_t matrix_in
Region of interest passed through the pixelpipe.