70#include "colord-gtk.h"
75#include <gdk/gdkwin32.h>
92#include <ApplicationServices/ApplicationServices.h>
93#include <Carbon/Carbon.h>
94#include <CoreServices/CoreServices.h>
98 cmsHPROFILE profile,
const char *
name,
int in_pos,
99 int out_pos,
int display_pos,
int category_pos,
102static const cmsCIEXYZ
d65 = {0.95045471, 1.00000000, 1.08905029};
105static const cmsCIExyY
D65xyY = {0.312700492, 0.329000939, 1.0};
111static const cmsCIExyY
D50xyY = {0.3457, 0.3585, 1.0};
115 {0.6400, 0.3300, 1.0},
116 {0.3000, 0.6000, 1.0},
117 {0.1500, 0.0600, 1.0}
122 {0.7080, 0.2920, 1.0},
123 {0.1700, 0.7970, 1.0},
124 {0.1310, 0.0460, 1.0}
129 {0.6400, 0.3300, 1.0},
130 {0.3000, 0.6000, 1.0},
131 {0.1500, 0.0600, 1.0}
136 {0.6400, 0.3300, 1.0},
137 {0.2100, 0.7100, 1.0},
138 {0.1500, 0.0600, 1.0}
152 { 0.734699, 0.265301, 1.0000 },
153 { 0.159597, 0.840403, 1.0000 },
154 { 0.036598, 0.000105, 1.0000 },
159#define generate_mat3inv_body(c_type, A, B) \
160 int mat3inv_##c_type(c_type *const dst, const c_type *const src) \
163 const c_type det = A(1, 1) * (A(3, 3) * A(2, 2) - A(3, 2) * A(2, 3)) \
164 - A(2, 1) * (A(3, 3) * A(1, 2) - A(3, 2) * A(1, 3)) \
165 + A(3, 1) * (A(2, 3) * A(1, 2) - A(2, 2) * A(1, 3)); \
167 const c_type epsilon = 1e-7f; \
168 if(fabs(det) < epsilon) return 1; \
170 const c_type invDet = 1.0 / det; \
172 B(1, 1) = invDet * (A(3, 3) * A(2, 2) - A(3, 2) * A(2, 3)); \
173 B(1, 2) = -invDet * (A(3, 3) * A(1, 2) - A(3, 2) * A(1, 3)); \
174 B(1, 3) = invDet * (A(2, 3) * A(1, 2) - A(2, 2) * A(1, 3)); \
176 B(2, 1) = -invDet * (A(3, 3) * A(2, 1) - A(3, 1) * A(2, 3)); \
177 B(2, 2) = invDet * (A(3, 3) * A(1, 1) - A(3, 1) * A(1, 3)); \
178 B(2, 3) = -invDet * (A(2, 3) * A(1, 1) - A(2, 1) * A(1, 3)); \
180 B(3, 1) = invDet * (A(3, 2) * A(2, 1) - A(3, 1) * A(2, 2)); \
181 B(3, 2) = -invDet * (A(3, 2) * A(1, 1) - A(3, 1) * A(1, 2)); \
182 B(3, 3) = invDet * (A(2, 2) * A(1, 1) - A(2, 1) * A(1, 2)); \
186#define A(y, x) src[(y - 1) * 3 + (x - 1)]
187#define B(y, x) dst[(y - 1) * 3 + (x - 1)]
191 int
mat3inv(
float *const dst, const
float *const src)
199#undef generate_mat3inv_body
204 const char *filename,
209 float *lutb,
const int lutsize,
const int input)
216 if(
IS_NULL_PTR(prof) || !cmsIsMatrixShaper(prof))
return 1;
224 const int UsedDirection = input ? LCMS_USED_AS_INPUT : LCMS_USED_AS_OUTPUT;
226 if(cmsIsCLUT(prof, INTENT_PERCEPTUAL, UsedDirection)
227 || cmsIsCLUT(prof, INTENT_RELATIVE_COLORIMETRIC, UsedDirection)
228 || cmsIsCLUT(prof, INTENT_ABSOLUTE_COLORIMETRIC, UsedDirection)
229 || cmsIsCLUT(prof, INTENT_SATURATION, UsedDirection))
232 cmsToneCurve *red_curve = cmsReadTag(prof, cmsSigRedTRCTag);
233 cmsToneCurve *green_curve = cmsReadTag(prof, cmsSigGreenTRCTag);
234 cmsToneCurve *blue_curve = cmsReadTag(prof, cmsSigBlueTRCTag);
236 cmsCIEXYZ *red_color = cmsReadTag(prof, cmsSigRedColorantTag);
237 cmsCIEXYZ *green_color = cmsReadTag(prof, cmsSigGreenColorantTag);
238 cmsCIEXYZ *blue_color = cmsReadTag(prof, cmsSigBlueColorantTag);
242 dt_colormatrix_t matrix_tmp = { { red_color->X, green_color->X, blue_color->X },
243 { red_color->Y, green_color->Y, blue_color->Y },
244 { red_color->Z, green_color->Z, blue_color->Z } };
249 for(
int k1 = 0; k1 < 3; k1++)
250 for(
int k2 = 0; k2 < 3; k2++)
251 sum += matrix_tmp[k1][k2];
252 if(sum == 0.0f)
return 3;
257 if(lutr && lutg && lutb)
259 if(cmsIsToneCurveLinear(red_curve))
262 for(
int k = 0;
k <
lutsize;
k++) lutr[
k] = cmsEvalToneCurveFloat(red_curve,
k / (
lutsize - 1.0f));
263 if(cmsIsToneCurveLinear(green_curve))
266 for(
int k = 0;
k <
lutsize;
k++) lutg[
k] = cmsEvalToneCurveFloat(green_curve,
k / (
lutsize - 1.0f));
267 if(cmsIsToneCurveLinear(blue_curve))
270 for(
int k = 0;
k <
lutsize;
k++) lutb[
k] = cmsEvalToneCurveFloat(blue_curve,
k / (
lutsize - 1.0f));
281 cmsToneCurve *rev_red = cmsReverseToneCurveEx(0x8000, red_curve);
282 cmsToneCurve *rev_green = cmsReverseToneCurveEx(0x8000, green_curve);
283 cmsToneCurve *rev_blue = cmsReverseToneCurveEx(0x8000, blue_curve);
286 cmsFreeToneCurve(rev_red);
287 cmsFreeToneCurve(rev_green);
288 cmsFreeToneCurve(rev_blue);
292 if(lutr && lutg && lutb)
295 if(cmsIsToneCurveLinear(red_curve))
298 for(
int k = 0;
k <
lutsize;
k++) lutr[
k] = cmsEvalToneCurveFloat(rev_red,
k / (
lutsize - 1.0f));
299 if(cmsIsToneCurveLinear(green_curve))
302 for(
int k = 0;
k <
lutsize;
k++) lutg[
k] = cmsEvalToneCurveFloat(rev_green,
k / (
lutsize - 1.0f));
303 if(cmsIsToneCurveLinear(blue_curve))
306 for(
int k = 0;
k <
lutsize;
k++) lutb[
k] = cmsEvalToneCurveFloat(rev_blue,
k / (
lutsize - 1.0f));
309 cmsFreeToneCurve(rev_red);
310 cmsFreeToneCurve(rev_green);
311 cmsFreeToneCurve(rev_blue);
321 float *lutb,
const int lutsize)
327 float *lutb,
const int lutsize)
334 return cmsCreateLab4Profile(cmsD50_xyY());
338 const cmsCIExyYTRIPLE* primaries,
339 cmsCIEXYZTRIPLE *primaries_prequantized)
341 cmsHPROFILE profile = cmsCreateRGBProfile(whitepoint, primaries, NULL);
343 cmsCIEXYZ *
R = cmsReadTag(profile, cmsSigRedColorantTag);
344 cmsCIEXYZ *G = cmsReadTag(profile, cmsSigGreenColorantTag);
345 cmsCIEXYZ *
B = cmsReadTag(profile, cmsSigBlueColorantTag);
347 primaries_prequantized->Red.X = (
double)
R->X;
348 primaries_prequantized->Red.Y = (
double)
R->Y;
349 primaries_prequantized->Red.Z = (
double)
R->Z;
351 primaries_prequantized->Green.X = (
double)G->X;
352 primaries_prequantized->Green.Y = (
double)G->Y;
353 primaries_prequantized->Green.Z = (
double)G->Z;
355 primaries_prequantized->Blue.X = (
double)
B->X;
356 primaries_prequantized->Blue.Y = (
double)
B->Y;
357 primaries_prequantized->Blue.Z = (
double)
B->Z;
359 cmsCloseProfile(profile);
363 const cmsCIExyY *whitepoint,
const cmsCIExyYTRIPLE *primaries, cmsToneCurve *trc,
366 cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
367 cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
368 cmsMLU *mlu3 = cmsMLUalloc(NULL, 1);
369 cmsMLU *mlu4 = cmsMLUalloc(NULL, 1);
371 cmsToneCurve *out_curves[3] = { trc, trc, trc };
372 cmsHPROFILE profile = cmsCreateRGBProfile(whitepoint, primaries, out_curves);
374 if(v2) cmsSetProfileVersion(profile, 2.4);
376 cmsSetHeaderFlags(profile, cmsEmbeddedProfileTrue);
378 cmsMLUsetASCII(mlu1,
"en",
"US",
"Public Domain");
379 cmsWriteTag(profile, cmsSigCopyrightTag, mlu1);
381 cmsMLUsetASCII(mlu2,
"en",
"US", desc);
382 cmsWriteTag(profile, cmsSigProfileDescriptionTag, mlu2);
384 cmsMLUsetASCII(mlu3,
"en",
"US", dmdd);
385 cmsWriteTag(profile, cmsSigDeviceModelDescTag, mlu3);
387 cmsMLUsetASCII(mlu4,
"en",
"US",
"darktable");
388 cmsWriteTag(profile, cmsSigDeviceMfgDescTag, mlu4);
402 static const double M1 = 2610.0 / 16384.0;
403 static const double M2 = (2523.0 / 4096.0) * 128.0;
404 static const double C1 = 3424.0 / 4096.0;
405 static const double C2 = (2413.0 / 4096.0) * 32.0;
406 static const double C3 = (2392.0 / 4096.0) * 32.0;
408 if (
x == 0.0)
return 0.0;
409 const double sign =
x;
412 const double xpo = pow(
x, 1.0 / M2);
413 const double num =
MAX(xpo - C1, 0.0);
414 const double den = C2 - C3 * xpo;
415 const double res = pow(num / den, 1.0 / M1);
417 return copysign(res,
sign);
424 static const double A = 0.17883277;
425 static const double B = 0.28466892;
426 static const double C = 0.55991073;
434 const double sign =
x;
435 const double e = fabs(
x);
438 return copysign((e * e) / 3.0,
sign);
440 return copysign((exp((e -
C) /
A) +
B) / 12.0,
sign);
445 float *values = g_malloc(
sizeof(
float) *
size);
447 for (int32_t
i = 0;
i <
size; ++
i)
449 const double x = (float)
i / (
size - 1);
450 const double y =
MIN(fct(
x), 1.0f);
451 values[
i] = (float)y;
454 cmsToneCurve* result = cmsBuildTabulatedToneCurveFloat(NULL,
size, values);
461 cmsFloat64Number srgb_parameters[5] = { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 };
462 cmsToneCurve *transferFunction = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters);
467 cmsFreeToneCurve(transferFunction);
484 cmsFloat64Number srgb_parameters[5] = { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 };
485 cmsToneCurve *transferFunction = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters);
490 &
D65xyY, &BRG_Primaries, transferFunction,
TRUE);
492 cmsFreeToneCurve(transferFunction);
499 cmsFloat64Number srgb_parameters[5] = { 1/0.45, 1.0 / 1.099, 0.099 / 1.099, 1.0 / 4.5, 0.081 };
500 cmsToneCurve *transferFunction = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters);
505 cmsFreeToneCurve(transferFunction);
513 cmsToneCurve *transferFunction = cmsBuildGamma(NULL, 2.19921875);
515 cmsHPROFILE profile =
_create_lcms_profile(
"ITU-R BT.1886 (gamma 2.4 Rec709)",
"ITU-R BT.1886 (gamma 2.4 Rec709)",
518 cmsFreeToneCurve(transferFunction);
528 cmsToneCurve *transferFunction = cmsBuildGamma(NULL, 2.19921875);
533 cmsFreeToneCurve(transferFunction);
556 cmsCIExyY WP = {
preset->white[0] / wxyz,
preset->white[1] / wxyz, 1.0 };
557 cmsCIExyYTRIPLE XYZPrimaries = { {
preset->rXYZ[0] / rxyz,
preset->rXYZ[1] / rxyz, 1.0 },
558 {
preset->gXYZ[0] / gxyz,
preset->gXYZ[1] / gxyz, 1.0 },
559 {
preset->bXYZ[0] / bxyz,
preset->bXYZ[1] / bxyz, 1.0 } };
560 cmsToneCurve *Gamma[3];
563 Gamma[0] = Gamma[1] = Gamma[2] = cmsBuildGamma(NULL, 1.0);
565 hp = cmsCreateRGBProfile(&WP, &XYZPrimaries, Gamma);
566 cmsFreeToneCurve(Gamma[0]);
570 snprintf(
name,
sizeof(
name),
"darktable alternate %s", makermodel);
571 cmsSetProfileVersion(hp, 2.1);
572 cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
573 cmsMLUsetASCII(mlu0,
"en",
"US",
"(dt internal)");
574 cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
575 cmsMLUsetASCII(mlu1,
"en",
"US",
name);
576 cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
577 cmsMLUsetASCII(mlu2,
"en",
"US",
name);
578 cmsWriteTag(hp, cmsSigDeviceMfgDescTag, mlu0);
579 cmsWriteTag(hp, cmsSigDeviceModelDescTag, mlu1);
581 cmsWriteTag(hp, cmsSigProfileDescriptionTag, mlu2);
606 cmsCIExyY WP = {
preset->white[0] / wxyz,
preset->white[1] / wxyz, 1.0 };
607 cmsCIExyYTRIPLE XYZPrimaries = { {
preset->rXYZ[0] / rxyz,
preset->rXYZ[1] / rxyz, 1.0 },
608 {
preset->gXYZ[0] / gxyz,
preset->gXYZ[1] / gxyz, 1.0 },
609 {
preset->bXYZ[0] / bxyz,
preset->bXYZ[1] / bxyz, 1.0 } };
610 cmsToneCurve *Gamma[3];
613 Gamma[0] = Gamma[1] = Gamma[2] = cmsBuildGamma(NULL, 1.0);
615 hp = cmsCreateRGBProfile(&WP, &XYZPrimaries, Gamma);
616 cmsFreeToneCurve(Gamma[0]);
620 snprintf(
name,
sizeof(
name),
"darktable vendor %s", makermodel);
621 cmsSetProfileVersion(hp, 2.1);
622 cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
623 cmsMLUsetASCII(mlu0,
"en",
"US",
"(dt internal)");
624 cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
625 cmsMLUsetASCII(mlu1,
"en",
"US",
name);
626 cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
627 cmsMLUsetASCII(mlu2,
"en",
"US",
name);
628 cmsWriteTag(hp, cmsSigDeviceMfgDescTag, mlu0);
629 cmsWriteTag(hp, cmsSigDeviceModelDescTag, mlu1);
631 cmsWriteTag(hp, cmsSigProfileDescriptionTag, mlu2);
656 cmsCIExyY WP = {
preset->white[0] / wxyz,
preset->white[1] / wxyz, 1.0 };
657 cmsCIExyYTRIPLE XYZPrimaries = { {
preset->rXYZ[0] / rxyz,
preset->rXYZ[1] / rxyz, 1.0 },
658 {
preset->gXYZ[0] / gxyz,
preset->gXYZ[1] / gxyz, 1.0 },
659 {
preset->bXYZ[0] / bxyz,
preset->bXYZ[1] / bxyz, 1.0 } };
660 cmsToneCurve *Gamma[3];
663 Gamma[0] = Gamma[1] = Gamma[2] = cmsBuildGamma(NULL, 1.0);
665 hp = cmsCreateRGBProfile(&WP, &XYZPrimaries, Gamma);
666 cmsFreeToneCurve(Gamma[0]);
670 snprintf(
name,
sizeof(
name),
"darktable profiled %s", makermodel);
671 cmsSetProfileVersion(hp, 2.1);
672 cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
673 cmsMLUsetASCII(mlu0,
"en",
"US",
"(dt internal)");
674 cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
675 cmsMLUsetASCII(mlu1,
"en",
"US",
name);
676 cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
677 cmsMLUsetASCII(mlu2,
"en",
"US",
name);
678 cmsWriteTag(hp, cmsSigDeviceMfgDescTag, mlu0);
679 cmsWriteTag(hp, cmsSigDeviceModelDescTag, mlu1);
681 cmsWriteTag(hp, cmsSigProfileDescriptionTag, mlu2);
691 cmsHPROFILE hXYZ = cmsCreateXYZProfile();
692 cmsSetPCS(hXYZ, cmsSigXYZData);
693 cmsSetHeaderRenderingIntent(hXYZ, INTENT_PERCEPTUAL);
697 cmsSetProfileVersion(hXYZ, 2.1);
698 cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
699 cmsMLUsetASCII(mlu0,
"en",
"US",
"(dt internal)");
700 cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
701 cmsMLUsetASCII(mlu1,
"en",
"US",
"linear XYZ");
702 cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
703 cmsMLUsetASCII(mlu2,
"en",
"US",
"darktable linear XYZ");
704 cmsWriteTag(hXYZ, cmsSigDeviceMfgDescTag, mlu0);
705 cmsWriteTag(hXYZ, cmsSigDeviceModelDescTag, mlu1);
707 cmsWriteTag(hXYZ, cmsSigProfileDescriptionTag, mlu2);
717 cmsToneCurve *transferFunction = cmsBuildGamma(NULL, 1.0);
722 cmsFreeToneCurve(transferFunction);
729 cmsToneCurve *transferFunction = cmsBuildGamma(NULL, 1.0);
734 cmsFreeToneCurve(transferFunction);
746 cmsFreeToneCurve(transferFunction);
758 cmsFreeToneCurve(transferFunction);
770 cmsFreeToneCurve(transferFunction);
782 cmsFreeToneCurve(transferFunction);
789 cmsFloat64Number srgb_parameters[5] = { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 };
790 cmsToneCurve *transferFunction = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters);
795 cmsFreeToneCurve(transferFunction);
802 cmsToneCurve *transferFunction = cmsBuildGamma(NULL, 1.0);
807 cmsFreeToneCurve(transferFunction);
814 cmsToneCurve *transferFunction = cmsBuildGamma(NULL, 1.0);
819 cmsHPROFILE profile =
_create_lcms_profile(
"Linear Infrared BGR",
"darktable Linear Infrared BGR",
822 cmsFreeToneCurve(transferFunction);
833 for(
const GList *modules =
darktable.
iop; modules; modules = g_list_next(modules))
836 if(!strcmp(module->op,
"colorin"))
846 if(colorin && colorin->get_p)
854 "SELECT op_params FROM main.history WHERE imgid=?1 AND operation='colorin' ORDER BY num DESC LIMIT 1", -1,
858 if(sqlite3_step(stmt) == SQLITE_ROW)
861 const void *params = sqlite3_column_blob(stmt, 0);
863 char *filename = colorin->get_p(params,
"filename_work");
868 sqlite3_finalize(stmt);
884 *new_profile =
FALSE;
888 gboolean from_cache =
TRUE;
891 const gchar *cc = filename + strlen(filename);
892 for(; *cc !=
'.' && cc > filename; cc--);
893 gchar *ext = g_ascii_strdown(cc + 1, -1);
900 gboolean already_set =
FALSE;
969 else if(!strcmp(ext,
"pfm"))
986 if(!strcmp(ext,
"jpg") || !strcmp(ext,
"jpeg"))
993 else if(!strcmp(ext,
"jp2") || !strcmp(ext,
"j2k") || !strcmp(ext,
"j2c") || !strcmp(ext,
"jpc"))
998 else if((!strcmp(ext,
"tif") || !strcmp(ext,
"tiff")))
1002 else if(!strcmp(ext,
"png"))
1007 else if(!strcmp(ext,
"avif"))
1021 else if(!strcmp(ext,
"heif") || !strcmp(ext,
"heic") || !strcmp(ext,
"hif"))
1043 *new_profile =
TRUE;
1064 return color_profile;
1070 cmsHPROFILE *output,
1071 gboolean *new_profile)
1073 if(output) *output = NULL;
1074 if(new_profile) *new_profile =
FALSE;
1099 gboolean dummy_new_profile =
FALSE;
1106 cmsHPROFILE profile = NULL;
1160 if(new_profile) *new_profile =
TRUE;
1182 gboolean new_profile;
1191 char *lang = getenv(
"LANG");
1205 const char *over_filename)
1238static void dt_colorspaces_create_cmatrix(
float cmatrix[4][3],
float mat[3][3])
1241 static const dt_colormatrix_t rgb_to_xyz = { { 0.4124564f, 0.3575761f, 0.1804375f, 0.0f },
1242 { 0.2126729f, 0.7151522f, 0.0721750f, 0.0f },
1243 { 0.0193339f, 0.1191920f, 0.9503041f, 0.0f } };
1245 for(
int c = 0;
c < 3;
c++)
1247 for(
int j = 0; j < 3; j++)
1250 for(
int k = 0;
k < 3;
k++)
1252 mat[
c][j] += rgb_to_xyz[
k][j] * cmatrix[
c][
k];
1263 for(
int k = 0;
k < 3;
k++)
1265 const float norm = mat[0][
k] + mat[1][
k] + mat[2][
k];
1266 x[
k] = mat[0][
k] / norm;
1267 y[
k] = mat[1][
k] / norm;
1269 cmsCIExyYTRIPLE CameraPrimaries = { {
x[0], y[0], 1.0 }, {
x[1], y[1], 1.0 }, {
x[2], y[2], 1.0 } };
1270 cmsHPROFILE profile;
1273 cmsXYZ2xyY(&D65, &
d65);
1275 cmsToneCurve *Gamma[3];
1276 Gamma[0] = Gamma[1] = Gamma[2] = cmsBuildGamma(NULL, 1.0);
1277 profile = cmsCreateRGBProfile(&D65, &CameraPrimaries, Gamma);
1278 cmsFreeToneCurve(Gamma[0]);
1281 cmsSetProfileVersion(profile, 2.1);
1282 cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
1283 cmsMLUsetASCII(mlu0,
"en",
"US",
"(dt internal)");
1284 cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
1285 cmsMLUsetASCII(mlu1,
"en",
"US",
"color matrix built-in");
1286 cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
1287 cmsMLUsetASCII(mlu2,
"en",
"US",
"color matrix built-in");
1288 cmsWriteTag(profile, cmsSigDeviceMfgDescTag, mlu0);
1289 cmsWriteTag(profile, cmsSigDeviceModelDescTag, mlu1);
1291 cmsWriteTag(profile, cmsSigProfileDescriptionTag, mlu2);
1303 mat3inv((
float *)imat, (
float *)mat);
1309 if(profile && cmsGetColorSpace(profile) == cmsSigGrayData)
1311 cmsToneCurve *trc = cmsReadTag(profile, cmsSigGrayTRCTag);
1312 cmsCIEXYZ *wtpt = cmsReadTag(profile, cmsSigMediaWhitePointTag);
1313 cmsCIEXYZ *bkpt = cmsReadTag(profile, cmsSigMediaBlackPointTag);
1314 cmsCIEXYZ *chad = cmsReadTag(profile, cmsSigChromaticAdaptationTag);
1316 cmsMLU *cprt = cmsReadTag(profile, cmsSigCopyrightTag);
1317 cmsMLU *desc = cmsReadTag(profile, cmsSigProfileDescriptionTag);
1318 cmsMLU *dmnd = cmsReadTag(profile, cmsSigDeviceMfgDescTag);
1319 cmsMLU *dmdd = cmsReadTag(profile, cmsSigDeviceModelDescTag);
1321 cmsHPROFILE rgb_profile = cmsCreateProfilePlaceholder(0);
1323 cmsSetDeviceClass(rgb_profile, cmsSigDisplayClass);
1324 cmsSetColorSpace(rgb_profile, cmsSigRgbData);
1325 cmsSetPCS(rgb_profile, cmsSigXYZData);
1327 cmsWriteTag(rgb_profile, cmsSigCopyrightTag, cprt);
1328 cmsWriteTag(rgb_profile, cmsSigProfileDescriptionTag, desc);
1329 cmsWriteTag(rgb_profile, cmsSigDeviceMfgDescTag, dmnd);
1330 cmsWriteTag(rgb_profile, cmsSigDeviceModelDescTag, dmdd);
1332 cmsWriteTag(rgb_profile, cmsSigMediaBlackPointTag, bkpt);
1333 cmsWriteTag(rgb_profile, cmsSigMediaWhitePointTag, wtpt);
1334 cmsWriteTag(rgb_profile, cmsSigChromaticAdaptationTag, chad);
1335 cmsSetColorSpace(rgb_profile, cmsSigRgbData);
1336 cmsSetPCS(rgb_profile, cmsSigXYZData);
1344 cmsWriteTag(rgb_profile, cmsSigRedTRCTag, (
void *)trc);
1345 cmsLinkTag(rgb_profile, cmsSigGreenTRCTag, cmsSigRedTRCTag);
1346 cmsLinkTag(rgb_profile, cmsSigBlueTRCTag, cmsSigRedTRCTag);
1348 cmsCloseProfile(profile);
1349 profile = rgb_profile;
1371 cmsUInt32Number
size;
1373 wchar_t *wbuf = NULL;
1376 size = cmsGetProfileInfoASCII(
p, cmsInfoDescription, language, country, NULL, 0);
1379 buf = (
char *)calloc(
size + 1,
sizeof(
char));
1380 size = cmsGetProfileInfoASCII(
p, cmsInfoDescription, language, country, buf,
size);
1384 if(
sizeof(
wchar_t) != 4 || g_utf8_validate(buf, -1, NULL))
1385 g_strlcpy(
name, buf, len);
1388 wbuf = (
wchar_t *)calloc(
size + 1,
sizeof(
wchar_t));
1389 size = cmsGetProfileInfo(
p, cmsInfoDescription, language, country, wbuf,
sizeof(
wchar_t) *
size);
1391 utf8 = g_ucs4_to_utf8((gunichar *)wbuf, -1, NULL, NULL, NULL);
1393 g_strlcpy(
name, utf8, len);
1403 g_strlcpy(
name, buf, len);
1414 const float pmax = fmaxf(
r, fmax(
g, b));
1415 const float pmin = fminf(
r, fmin(
g, b));
1416 const float delta = (pmax - pmin);
1418 float hv = 0, sv = 0, lv = (pmin + pmax) / 2.0;
1422 sv = lv < 0.5 ?
delta / fmaxf(pmax + pmin, 1.52587890625e-05f)
1423 :
delta / fmaxf(2.0 - pmax - pmin, 1.52587890625e-05f);
1428 hv = 2.0 + (b -
r) /
delta;
1443static inline __attribute__((always_inline))
float hue2rgb(
float m1,
float m2,
float hue)
1448 return (m1 + (m2 - m1) * hue);
1452 return hue < 4.0f ? (m1 + (m2 - m1) * (4.0f - hue)) : m1;
1463 m2 = l < 0.5 ? l * (1.0 + s) : l + s - l * s;
1464 m1 = (2.0 * l - m2);
1466 rgb[0] = hue2rgb(m1, m2, h < 4.0f ? h + 2.0f : h - 4.0f);
1467 rgb[1] = hue2rgb(m1, m2, h);
1468 rgb[2] = hue2rgb(m1, m2, h > 2.0f ? h - 2.0f : h + 4.0f);
1472 cmsHPROFILE profile,
const char *
name,
int in_pos,
1473 int out_pos,
int display_pos,
int category_pos,
1508 cmsHPROFILE display_profile = display_dt_profile->
profile;
1566 for(
int y = 0; y <
height; y++)
1568 const float *
const in = image_in + (size_t)y *
width * 4;
1569 float *
const out = image_out + (size_t)y *
width * 4;
1582 for(
int y = 0; y <
height; y++)
1584 const uint8_t *
const restrict in = image_in + (size_t)y *
width * 4u;
1585 uint8_t *
const restrict
out = image_out + (size_t)y *
width * 4u;
1590 for(
int x = 0;
x <
width;
x++)
out[4 *
x + 3] = UINT8_MAX;
1596 out[4 *
x + 0] = in[4 *
x + 2];
1597 out[4 *
x + 1] = in[4 *
x + 1];
1598 out[4 *
x + 2] = in[4 *
x + 0];
1599 out[4 *
x + 3] = UINT8_MAX;
1612 cmsHPROFILE profile = cmsOpenProfileFromMem(tmp_data,
size);
1621 p->profile = profile;
1644 gchar *name_a = g_utf8_casefold(profile_a->
name, -1);
1645 gchar *name_b = g_utf8_casefold(profile_b->
name, -1);
1647 gint result = g_strcmp0(name_a, name_b);
1657 GList *temp_profiles = NULL;
1658 const gchar *d_name;
1663 char *lang = getenv(
"LANG");
1666 char *dirname = g_build_filename(confdir,
"color", subdir, NULL);
1667 if(!g_file_test(dirname, G_FILE_TEST_IS_DIR))
1670 dirname = g_build_filename(datadir,
"color", subdir, NULL);
1672 GDir *dir = g_dir_open(dirname, 0, NULL);
1675 while((d_name = g_dir_read_name(dir)))
1677 char *filename = g_build_filename(dirname, d_name, NULL);
1678 const char *cc = filename + strlen(filename);
1679 for(; *cc !=
'.' && cc > filename; cc--)
1681 if(!g_ascii_strcasecmp(cc,
".icc") || !g_ascii_strcasecmp(cc,
".icm"))
1685 if(
IS_NULL_PTR(icc_content))
goto icc_loading_done;
1688 cmsHPROFILE tmpprof =
_ensure_rgb_profile(cmsOpenProfileFromMem(icc_content,
sizeof(
char) * end));
1693 if(prof->
name[0] ==
'\0')
1694 g_strlcpy(prof->
name, _(
"(unknown name)"),
sizeof(prof->
name));
1705 temp_profiles = g_list_prepend(temp_profiles, prof);
1717 return temp_profiles;
1738 -1, ++category_pos, -1));
1741 -1, -1, ++category_pos, -1));
1745 -1, ++category_pos, -1));
1750 _(
"System display profile (recommended)"), -1, -1, ++display_pos, ++category_pos, -1));
1757 _(
"sRGB (e.g. JPG)"), ++in_pos, -1, -1, -1, -1));
1761 _(
"sRGB"), -1, ++out_pos, ++display_pos,
1762 ++category_pos, ++work_pos));
1766 _(
"Adobe RGB (compatible)"), ++in_pos, ++out_pos, ++display_pos,
1767 ++category_pos, ++work_pos));
1771 _(
"linear Rec709 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1775 _(
"gamma Rec709 RGB"), ++in_pos, ++out_pos, -1, -1,
1779 _(
"ITU-R BT.1886 (gamma 2.4 Rec709)"), ++in_pos, ++out_pos, -1, -1,
1784 _(
"linear Rec2020 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1789 _(
"PQ Rec2020 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1794 _(
"HLG Rec2020 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1799 _(
"PQ P3 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1804 _(
"HLG P3 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1809 _(
"Display P3 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1814 _(
"linear ProPhoto RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1828 _(
"linear infrared BGR"), ++in_pos, -1, -1, -1, -1));
1832 _(
"BRG (for testing)"), ++in_pos, ++out_pos, ++display_pos,
1859 GList *temp_profiles;
1863 for(GList *iter = temp_profiles; iter; iter = g_list_next(iter))
1872 for(GList *iter = temp_profiles; iter; iter = g_list_next(iter))
1883 const gboolean is_valid_matrix_profile
1888 if(is_valid_matrix_profile)
1896 "output profile `%s' color space `%c%c%c%c' not supported for work or histogram profile\n",
1934 for(GList *iter = self->
profiles; iter; iter = g_list_next(iter))
1950 const char *filename)
1961 return _(
"Adobe RGB (compatible)");
1963 return _(
"linear Rec709 RGB");
1965 return _(
"linear Rec2020 RGB");
1967 return _(
"linear XYZ");
1971 return _(
"linear infrared BGR");
1973 return _(
"System display profile (recommended)");
1975 return _(
"embedded ICC profile");
1977 return _(
"embedded matrix");
1979 return _(
"standard color matrix");
1981 return _(
"enhanced color matrix");
1983 return _(
"vendor color matrix");
1985 return _(
"alternate color matrix");
1987 return _(
"BRG (experimental)");
1989 return _(
"export profile");
1991 return _(
"softproof profile");
1993 return _(
"work profile");
1995 return _(
"Not used. Shouldn't be here.");
1997 return _(
"Rec709 RGB");
1999 return _(
"linear ProPhoto RGB");
2001 return _(
"PQ Rec2020");
2003 return _(
"HLG Rec2020");
2009 return _(
"Display P3");
2011 return _(
"ITU-R BT.1886");
2020static void dt_colorspaces_get_display_profile_colord_callback(GObject *source, GAsyncResult *res, gpointer user_data)
2025 CdWindow *
window = CD_WINDOW(source);
2026 GError *
error = NULL;
2027 CdProfile *profile = cd_window_get_profile_finish(
window, res, &
error);
2030 const gchar *filename = cd_profile_get_filename(profile);
2042 guchar *tmp_data = NULL;
2044 g_file_get_contents(filename, (gchar **)&tmp_data, &
size, NULL);
2052 "[color profile] colord gave us a new screen profile: '%s' (size: %" G_GSIZE_FORMAT
")\n", filename,
size);
2061 if(profile) g_object_unref(profile);
2070#if defined GDK_WINDOWING_X11
2071static int _gtk_get_monitor_num(GdkMonitor *monitor)
2073 GdkDisplay *display;
2076 display = gdk_monitor_get_display(monitor);
2077 n_monitors = gdk_display_get_n_monitors(display);
2078 for(
i = 0;
i < n_monitors;
i++)
2080 if(gdk_display_get_monitor(display,
i) == monitor)
return i;
2101 guint8 *buffer = NULL;
2102 gint buffer_size = 0;
2103 gchar *profile_source = NULL;
2105#if defined GDK_WINDOWING_X11
2108 gboolean use_xatom =
TRUE;
2109#if defined USE_COLORDGTK
2110 gboolean use_colord =
TRUE;
2113 if(display_profile_source)
2115 if(!strcmp(display_profile_source,
"xatom"))
2117 else if(!strcmp(display_profile_source,
"colord"))
2126 GdkWindow *
window = gtk_widget_get_window(widget);
2127 GdkScreen *screen = gtk_widget_get_screen(widget);
2128 if(
IS_NULL_PTR(screen)) screen = gdk_screen_get_default();
2130 GdkDisplay *display = gtk_widget_get_display(widget);
2131 int monitor = _gtk_get_monitor_num(gdk_display_get_monitor_at_window(display,
window));
2135 atom_name = g_strdup_printf(
"_ICC_PROFILE_%d", monitor);
2137 atom_name = g_strdup(
"_ICC_PROFILE");
2139 profile_source = g_strdup_printf(
"xatom %s", atom_name);
2141 GdkAtom
type = GDK_NONE;
2143 gdk_property_get(gdk_screen_get_root_window(screen), gdk_atom_intern(atom_name,
FALSE), GDK_NONE, 0,
2144 64 * 1024 * 1024,
FALSE, &
type, &format, &buffer_size, &buffer);
2152 CdWindow *
window = cd_window_new();
2154 cd_window_get_profile(
window, center_widget, NULL, dt_colorspaces_get_display_profile_colord_callback,
2155 GINT_TO_POINTER(profile_type));
2159#elif defined GDK_WINDOWING_QUARTZ
2162 GdkScreen *screen = gtk_widget_get_screen(widget);
2163 if(
IS_NULL_PTR(screen)) screen = gdk_screen_get_default();
2164 int monitor = gdk_screen_get_monitor_at_window(screen, gtk_widget_get_window(widget));
2166 CGDirectDisplayID ids[monitor + 1];
2168 CMProfileRef prof = NULL;
2169 if(CGGetOnlineDisplayList(monitor + 1, &ids[0], &total_ids) == kCGErrorSuccess && total_ids == monitor + 1)
2170 CMGetProfileByAVID(ids[monitor], &prof);
2174 data = CMProfileCopyICCData(NULL, prof);
2175 CMCloseProfile(prof);
2177 UInt8 *tmp_buffer = (UInt8 *)g_malloc(CFDataGetLength(data));
2178 CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), tmp_buffer);
2180 buffer = (guint8 *)tmp_buffer;
2181 buffer_size = CFDataGetLength(data);
2185 profile_source = g_strdup(
"osx color profile api");
2187#elif defined G_OS_WIN32
2190 GdkWindow *
window = gtk_widget_get_window(widget);
2191 HWND hwnd = (HWND)gdk_win32_window_get_handle(
window);
2192 HMONITOR hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
2194 MONITORINFOEX monitorInfo;
2195 monitorInfo.cbSize =
sizeof(MONITORINFOEX);
2196 if(!GetMonitorInfoW(hMonitor,(LPMONITORINFO) &monitorInfo)) {
return;}
2197 HDC hdc = CreateIC(
L"MONITOR",monitorInfo.szDevice,NULL,NULL);
2201 GetICMProfile(hdc, &len, NULL);
2202 wchar_t *wpath = g_new(
wchar_t, len);
2204 if(GetICMProfileW(hdc, &len, wpath))
2206 gchar *path = g_utf16_to_utf8(wpath, -1, NULL, NULL, NULL);
2210 g_file_get_contents(path, (gchar **)&buffer, &
size, NULL);
2218 profile_source = g_strdup(
"windows color profile api");
2226 char name[512] = { 0 };
2229 *
name ?
name :
"(unknown)", profile_source, buffer_size);
2242 const char *
f = profile;
2245 if(*
f ==
'/' || *
f ==
'\\')
return FALSE;
2253 const char*
f = profile + strlen(profile);
2254 for (;
f >= profile;
f--)
2256 if(*
f ==
'/' || *
f ==
'\\')
2509 const char *filename,
2512 for(GList *iter = self->
profiles; iter; iter = g_list_next(iter))
2530 const char *filename,
2542 for(
int i = 0;
i < 3;
i++) {
2543 for(
int j = 0; j < 6; j++)
2544 work[
i][j] = j ==
i+3;
2545 for(
int j = 0; j < 3; j++)
2547 work[
i][j] += in[
k][
i] * in[
k][j];
2549 for(
int i = 0;
i < 3;
i++) {
2550 double num = work[
i][
i];
2551 for(
int j = 0; j < 6; j++)
2553 for(
int k = 0;
k < 3;
k++) {
2556 for(
int j = 0; j < 6; j++)
2557 work[
k][j] -= work[
i][j] * num;
2561 for(
int j = 0; j < 3; j++)
2564 for(
int k = 0;
k < 3;
k++)
2565 out[
i][j] += work[j][
k+3] * in[
i][
k];
2571 if(!isnan(in_XYZ_to_CAM[0]))
2573 for(
int i = 0;
i < 9;
i++)
2574 XYZ_to_CAM[
i/3][
i%3] = (
double) in_XYZ_to_CAM[
i];
2575 for(
int i = 0;
i < 3;
i++)
2576 XYZ_to_CAM[3][
i] = 0.0f;
2580 if(isnan(adobe_XYZ_to_CAM[0][0]))
2583 for(
int i = 0;
i < 4;
i++)
2584 for(
int j = 0; j < 3; j++)
2585 XYZ_to_CAM[
i][j] = (
double)adobe_XYZ_to_CAM[
i][j];
2589 double inverse[4][3];
2591 for(
int i = 0;
i < 3;
i++)
2592 for(
int j = 0; j < 4; j++)
2593 CAM_to_XYZ[
i][j] = inverse[j][
i];
2602 double out_RGB_to_CAM[4][3],
double out_CAM_to_RGB[3][4],
2603 const float *embedded_matrix,
2606 double RGB_to_CAM[4][3];
2608 float XYZ_to_CAM[4][3];
2609 XYZ_to_CAM[0][0] = NAN;
2611 if(
IS_NULL_PTR(embedded_matrix) || isnan(embedded_matrix[0]))
2613 for(
int k=0;
k<4;
k++)
2614 for(
int i=0;
i<3;
i++)
2615 XYZ_to_CAM[
k][
i] = adobe_XYZ_to_CAM[
k][
i];
2621 XYZ_to_CAM[0][0] = embedded_matrix[0];
2622 XYZ_to_CAM[0][1] = embedded_matrix[1];
2623 XYZ_to_CAM[0][2] = embedded_matrix[2];
2625 XYZ_to_CAM[1][0] = embedded_matrix[3];
2626 XYZ_to_CAM[1][1] = embedded_matrix[4];
2627 XYZ_to_CAM[1][2] = embedded_matrix[5];
2629 XYZ_to_CAM[2][0] = embedded_matrix[6];
2630 XYZ_to_CAM[2][1] = embedded_matrix[7];
2631 XYZ_to_CAM[2][2] = embedded_matrix[8];
2634 if(isnan(XYZ_to_CAM[0][0]))
2637 const double RGB_to_XYZ[3][3] = {
2639 { 0.412453, 0.357580, 0.180423 },
2640 { 0.212671, 0.715160, 0.072169 },
2641 { 0.019334, 0.119193, 0.950227 },
2645 for(
int i = 0;
i < 4;
i++)
2646 for(
int j = 0; j < 3; j++)
2648 RGB_to_CAM[
i][j] = 0.0f;
2649 for(
int k = 0;
k < 3;
k++)
2650 RGB_to_CAM[
i][j] += XYZ_to_CAM[
i][
k] * RGB_to_XYZ[
k][j];
2654 for(
int i = 0;
i < 4;
i++) {
2656 for(
int j = 0; j < 3; j++)
2657 num += RGB_to_CAM[
i][j];
2658 for(
int j = 0; j < 3; j++)
2659 RGB_to_CAM[
i][j] /= num;
2660 if(mul) mul[
i] = 1.0f / num;
2664 for(
int i = 0;
i < 4;
i++)
2665 for(
int j = 0; j < 3; j++)
2666 out_RGB_to_CAM[
i][j] = RGB_to_CAM[
i][j];
2671 double inverse[4][3];
2673 for(
int i = 0;
i < 3;
i++)
2674 for(
int j = 0; j < 4; j++)
2675 out_CAM_to_RGB[
i][j] = inverse[j][
i];
2685 double CAM_to_RGB_WB[3][4];
2686 for (
int a=0; a<3; a++)
2687 for (
int b=0; b<4; b++)
2688 CAM_to_RGB_WB[a][b] = CAM_to_RGB[a][b] * coeffs[b];
2691 double RGB_to_RGB_WB[3][3];
2692 for (
int a=0; a<3; a++)
2693 for (
int b=0; b<3; b++) {
2694 RGB_to_RGB_WB[a][b] = 0.0f;
2695 for (
int c=0; c<4; c++)
2696 RGB_to_RGB_WB[a][b] += CAM_to_RGB_WB[a][c] * RGB_to_CAM[c][b];
2699 for(
int i = 0;
i < num;
i++)
2701 const float *inpos = &in[
i*4];
2702 float *outpos = &
out[
i*4];
2703 outpos[0]=outpos[1]=outpos[2] = 0.0f;
2704 for (
int a=0; a<3; a++)
2705 for (
int b=0; b<3; b++)
2706 outpos[a] += RGB_to_RGB_WB[a][b] * inpos[b];
2714 for(
int i = 0;
i < num;
i++)
2716 float *in = &
out[
i*4];
2718 for(
int c = 0; c < 3; c++)
2719 for(
int k = 0;
k < 4;
k++)
2720 o[c] += CAM_to_RGB[c][
k] * in[
k];
2721 for(
int c = 0; c < 3; c++)
2729 for(
int i = 0;
i < num;
i++)
2731 float *in = &
out[
i*3];
2733 for(
int c = 0; c < 4; c++)
2734 for(
int k = 0;
k < 3;
k++)
2735 o[c] += RGB_to_CAM[c][
k] * in[
k];
2736 for(
int c = 0; c < 4; c++)
static void error(char *msg)
uint32_t container(dt_lib_module_t *self)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
static void transform(float *x, float *o, const float *m, const float t_h, const float t_v)
static void profile_changed(GtkWidget *widget, gpointer user_data)
static dt_profiled_colormatrix_t dt_profiled_colormatrices[]
static dt_profiled_colormatrix_t dt_vendor_colormatrices[]
static dt_profiled_colormatrix_t dt_alternate_colormatrices[]
static const int dt_vendor_colormatrix_cnt
static const int dt_alternate_colormatrix_cnt
static const int dt_profiled_colormatrix_cnt
static cmsHPROFILE dt_colorspaces_create_gamma_rec709_rgb_profile(void)
static const cmsCIExyYTRIPLE Rec2020_Primaries
static const char * _colorspaces_get_base_name(const char *profile)
cmsHPROFILE dt_colorspaces_create_xyzimatrix_profile(float mat[3][3])
static cmsHPROFILE dt_colorspaces_create_linear_rec709_rgb_profile(void)
#define generate_mat3inv_body(c_type, A, B)
__DT_CLONE_TARGETS__ int dt_colorspaces_conversion_matrices_rgb(const float adobe_XYZ_to_CAM[4][3], double out_RGB_to_CAM[4][3], double out_CAM_to_RGB[3][4], const float *embedded_matrix, double mul[4])
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)
static cmsHPROFILE dt_colorspaces_create_itur_bt1886_rgb_profile(void)
void dt_colorspaces_rgb_to_cygm(float *out, int num, double RGB_to_CAM[4][3])
dt_colorspaces_color_profile_type_t dt_colorspaces_get_input_profile_from_image(int32_t imgid, dt_colorspaces_color_profile_type_t requested, cmsHPROFILE *output, gboolean *new_profile)
Resolve an embedded/matrix input profile for a given image, honoring the requested type when possible...
static const dt_colorspaces_color_profile_t * _get_profile(dt_colorspaces_t *self, dt_colorspaces_color_profile_type_t type, const char *filename, dt_colorspaces_profile_direction_t direction)
static const cmsCIExyYTRIPLE ProPhoto_Primaries
void rgb2hsl(const dt_aligned_pixel_t rgb, float *h, float *s, float *l)
static cmsHPROFILE dt_colorspaces_create_lab_profile()
static void _update_display_profile(guchar *tmp_data, gsize size, char *name, size_t name_size)
static cmsHPROFILE dt_colorspaces_create_pq_rec2020_rgb_profile(void)
static const cmsCIExyY D65xyY
static cmsHPROFILE dt_colorspaces_create_xyzmatrix_profile(const float mat[3][3])
static const cmsCIExyYTRIPLE Rec709_Primaries
const dt_colorspaces_color_profile_t * _build_embedded_profile(const int32_t imgid, dt_colorspaces_color_profile_type_t *type)
const dt_colorspaces_color_profile_t * dt_colorspaces_get_output_profile(const int32_t imgid, dt_colorspaces_color_profile_type_t *over_type, const char *over_filename)
__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)
int dt_colorspaces_get_matrix_from_output_profile(cmsHPROFILE prof, dt_colormatrix_t matrix, float *lutr, float *lutg, float *lutb, const int lutsize)
cmsCIEXYZTRIPLE Rec709_Primaries_Prequantized
void dt_colorspaces_update_display_transforms()
static cmsHPROFILE dt_colorspaces_create_linear_infrared_profile(void)
static cmsHPROFILE dt_colorspaces_create_hlg_p3_rgb_profile(void)
static cmsHPROFILE _create_lcms_profile(const char *desc, const char *dmdd, const cmsCIExyY *whitepoint, const cmsCIExyYTRIPLE *primaries, cmsToneCurve *trc, gboolean v2)
static dt_colorspaces_color_profile_t * _create_profile(dt_colorspaces_color_profile_type_t type, cmsHPROFILE profile, const char *name, int in_pos, int out_pos, int display_pos, int category_pos, int work_pos)
static cmsHPROFILE dt_colorspaces_create_srgb_profile()
static cmsHPROFILE dt_colorspaces_create_hlg_rec2020_rgb_profile(void)
const cmsHPROFILE dt_colorspaces_get_embedded_profile(const int32_t imgid, dt_colorspaces_color_profile_type_t *type, gboolean *new_profile)
static cmsHPROFILE dt_colorspaces_create_xyz_profile(void)
static cmsHPROFILE dt_colorspaces_create_display_p3_rgb_profile(void)
cmsHPROFILE dt_colorspaces_create_vendor_profile(const char *makermodel)
static double _PQ_fct(double x)
int dt_colorspaces_get_matrix_from_input_profile(cmsHPROFILE prof, dt_colormatrix_t matrix, float *lutr, float *lutg, float *lutb, const int lutsize)
static void cms_error_handler(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *text)
static cmsHPROFILE dt_colorspaces_create_linear_prophoto_rgb_profile(void)
static gboolean _colorspaces_is_base_name(const char *profile)
int mat3inv(float *const dst, const float *const src)
static __DT_CLONE_TARGETS__ void dt_colorspaces_pseudoinverse(double(*in)[3], double(*out)[3], int size)
void dt_colorspaces_cleanup(dt_colorspaces_t *self)
cmsHPROFILE dt_colorspaces_create_darktable_profile(const char *makermodel)
int dt_colorspaces_conversion_matrices_xyz(const float adobe_XYZ_to_CAM[4][3], float in_XYZ_to_CAM[9], double XYZ_to_CAM[4][3], double CAM_to_XYZ[3][4])
__DT_CLONE_TARGETS__ void dt_colorspaces_cygm_to_rgb(float *out, int num, double CAM_to_RGB[3][4])
static gint _sort_profiles(gconstpointer a, gconstpointer b)
static const cmsCIExyY D50xyY
void dt_colorspaces_cleanup_profile(cmsHPROFILE p)
dt_colorspaces_color_profile_type_t dt_image_find_best_color_profile(int32_t imgid, cmsHPROFILE *output, gboolean *new_profile)
Best effort to find a suitable (input) color profile for a given image, using embedded ICC or EXIF wh...
const dt_colorspaces_color_profile_t * dt_colorspaces_get_work_profile(const int32_t imgid)
static cmsHPROFILE dt_colorspaces_create_adobergb_profile(void)
static cmsHPROFILE dt_colorspaces_create_srgb_profile_v4()
static cmsToneCurve * _colorspaces_create_transfer(int32_t size, double(*fct)(double))
dt_colorspaces_t * dt_colorspaces_init()
cmsHPROFILE dt_colorspaces_get_rgb_profile_from_mem(uint8_t *data, uint32_t size)
static cmsHPROFILE dt_colorspaces_create_linear_rec2020_rgb_profile(void)
static cmsHPROFILE dt_colorspaces_create_pq_p3_rgb_profile(void)
const char * dt_colorspaces_get_name(dt_colorspaces_color_profile_type_t type, const char *filename)
static GList * load_profile_from_dir(const char *subdir)
static void _update_display_transforms(dt_colorspaces_t *self)
static const cmsCIExyYTRIPLE P3_Primaries
static cmsHPROFILE _colorspaces_create_srgb_profile(gboolean v2)
void dt_colorspaces_get_profile_name(cmsHPROFILE p, const char *language, const char *country, char *name, size_t len)
static const cmsCIExyYTRIPLE sRGB_Primaries
static __DT_CLONE_TARGETS__ int dt_colorspaces_get_matrix_from_profile(cmsHPROFILE prof, dt_colormatrix_t matrix, float *lutr, float *lutg, float *lutb, const int lutsize, const int input)
void dt_colorspaces_set_display_profile(const dt_colorspaces_color_profile_type_t profile_type)
cmsHPROFILE dt_colorspaces_create_alternate_profile(const char *makermodel)
static const cmsCIExyYTRIPLE Adobe_Primaries
void hsl2rgb(dt_aligned_pixel_t rgb, float h, float s, float l)
static const cmsCIEXYZ d65
gboolean dt_colorspaces_is_profile_equal(const char *fullname, const char *filename)
static cmsHPROFILE _ensure_rgb_profile(cmsHPROFILE profile)
dt_colorspaces_color_profile_type_t dt_colorspaces_cicp_to_type(const dt_colorspaces_cicp_t *cicp, const char *filename)
void dt_colorspaces_transform_rgba8_to_bgra8(const cmsHTRANSFORM transform, const uint8_t *image_in, uint8_t *image_out, const int width, const int height)
void dt_colorspaces_cygm_apply_coeffs_to_rgb(float *out, const float *in, int num, double RGB_to_CAM[4][3], double CAM_to_RGB[3][4], dt_aligned_pixel_t coeffs)
int mat3inv_float(float *const dst, const float *const src)
static double _HLG_fct(double x)
void dt_colorspaces_transform_rgba_float_row(const cmsHTRANSFORM transform, const float *in, float *out, const int width)
static cmsHPROFILE dt_colorspaces_create_brg_profile()
static void _compute_prequantized_primaries(const cmsCIExyY *whitepoint, const cmsCIExyYTRIPLE *primaries, cmsCIEXYZTRIPLE *primaries_prequantized)
dt_colorspaces_color_profile_type_t
@ DT_COLORSPACE_PROPHOTO_RGB
@ DT_COLORSPACE_EMBEDDED_MATRIX
@ DT_COLORSPACE_EMBEDDED_ICC
@ DT_COLORSPACE_PQ_REC2020
@ DT_COLORSPACE_HLG_REC2020
@ DT_COLORSPACE_ENHANCED_MATRIX
@ DT_COLORSPACE_LIN_REC2020
@ DT_COLORSPACE_DISPLAY_P3
@ DT_COLORSPACE_STANDARD_MATRIX
@ DT_COLORSPACE_VENDOR_MATRIX
@ DT_COLORSPACE_SOFTPROOF
@ DT_COLORSPACE_ITUR_BT1886
@ DT_COLORSPACE_LIN_REC709
@ DT_COLORSPACE_ALTERNATE_MATRIX
dt_colorspaces_profile_direction_t
@ DT_PROFILE_DIRECTION_IN
@ DT_PROFILE_DIRECTION_OUT
@ DT_PROFILE_DIRECTION_DISPLAY
@ DT_PROFILE_DIRECTION_WORK
@ DT_CICP_TRANSFER_CHARACTERISTICS_UNSPECIFIED
@ DT_CICP_TRANSFER_CHARACTERISTICS_LINEAR
@ DT_CICP_TRANSFER_CHARACTERISTICS_HLG
@ DT_CICP_TRANSFER_CHARACTERISTICS_REC2020_12B
@ DT_CICP_TRANSFER_CHARACTERISTICS_REC709
@ DT_CICP_TRANSFER_CHARACTERISTICS_PQ
@ DT_CICP_TRANSFER_CHARACTERISTICS_REC2020_10B
@ DT_CICP_TRANSFER_CHARACTERISTICS_REC601
@ DT_CICP_TRANSFER_CHARACTERISTICS_SRGB
@ DT_CICP_COLOR_PRIMARIES_REC2020
@ DT_CICP_COLOR_PRIMARIES_UNSPECIFIED
@ DT_CICP_COLOR_PRIMARIES_P3
@ DT_CICP_COLOR_PRIMARIES_REC709
@ DT_CICP_COLOR_PRIMARIES_XYZ
@ DT_CICP_MATRIX_COEFFICIENTS_REC601
@ DT_CICP_MATRIX_COEFFICIENTS_REC2020_NCL
@ DT_CICP_MATRIX_COEFFICIENTS_UNSPECIFIED
@ DT_CICP_MATRIX_COEFFICIENTS_IDENTITY
@ DT_CICP_MATRIX_COEFFICIENTS_SYCC
@ DT_CICP_MATRIX_COEFFICIENTS_REC709
@ DT_CICP_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL
static dt_aligned_pixel_t rgb
const dt_aligned_pixel_t f
const dt_colormatrix_t dt_aligned_pixel_t out
static const float const float C
const dt_colormatrix_t matrix
gboolean dt_image_is_matrix_correction_supported(const dt_image_t *img)
gboolean dt_image_is_monochrome(const dt_image_t *img)
void dt_image_full_path(const int32_t imgid, char *pathname, size_t pathname_len, gboolean *from_cache, const char *calling_func)
Get the full path of an image out of the database.
int dt_conf_get_bool(const char *name)
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
void dt_conf_set_string(const char *name, const char *val)
const char * dt_conf_get_string_const(const char *name)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
static void dt_free_gpointer(gpointer ptr)
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...
static const dt_aligned_pixel_simd_t sign
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR__(...)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
sqlite3 * dt_database_get(const dt_database_t *db)
#define DT_DEBUG_SQLITE3_PREPARE_V2(a, b, c, d, e)
#define DT_DEBUG_SQLITE3_BIND_INT(a, b, c)
void dt_loc_get_datadir(char *datadir, size_t bufsize)
void dt_loc_get_user_config_dir(char *configdir, size_t bufsize)
GtkWidget * dt_ui_center(dt_ui_t *ui)
get the center drawable widget
@ DT_IMAGE_COLORSPACE_ADOBE_RGB
@ DT_IMAGE_COLORSPACE_SRGB
void dt_image_cache_read_release(dt_image_cache_t *cache, const dt_image_t *img)
dt_image_t * dt_image_cache_get(dt_image_cache_t *cache, const int32_t imgid, char mode)
void dt_image_cache_write_release(dt_image_cache_t *cache, dt_image_t *img, dt_image_cache_write_mode_t mode)
int dt_imageio_avif_read_profile(const char *filename, uint8_t **out, dt_colorspaces_cicp_t *cicp)
int dt_imageio_heif_read_profile(const char *filename, uint8_t **out, dt_colorspaces_cicp_t *cicp)
int dt_imageio_j2k_read_profile(const char *filename, uint8_t **out)
int dt_imageio_jpeg_read_profile(dt_imageio_jpeg_t *jpg, uint8_t **out)
int dt_imageio_jpeg_read_header(const char *filename, dt_imageio_jpeg_t *jpg)
int dt_imageio_png_read_profile(const char *filename, uint8_t **out)
int dt_imageio_tiff_read_profile(const char *filename, uint8_t **out)
struct dt_iop_tonecurve_params_t preset
const float const int lutsize
float *const restrict const size_t k
float DT_ALIGNED_ARRAY dt_colormatrix_t[4][4]
static int mat3SSEinv(dt_colormatrix_t dst, const dt_colormatrix_t src)
dt_colorspaces_color_profile_type_t color_space
float dt_aligned_pixel_t[4]
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
@ DT_SIGNAL_CONTROL_PROFILE_CHANGED
This signal is raised when the screen profile has changed no param, no returned value.
struct _GtkWidget GtkWidget
struct dt_gui_gtk_t * gui
struct dt_colorspaces_t * color_profiles
const struct dt_database_t * db
struct dt_control_signal_t * signals
struct dt_image_cache_t * image_cache
struct dt_develop_t * develop
dt_colorspaces_cicp_matrix_coefficients_t matrix_coefficients
dt_colorspaces_cicp_transfer_characteristics_t transfer_characteristics
dt_colorspaces_cicp_color_primaries_t color_primaries
dt_colorspaces_color_profile_type_t type
cmsHTRANSFORM transform_adobe_rgb_to_display
dt_colorspaces_color_profile_type_t softproof_type
gchar * colord_profile_file
cmsHTRANSFORM transform_display_to_adobe_rgb
cmsHTRANSFORM transform_srgb_to_display
cmsHTRANSFORM transform_xyz_to_display
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 softproof_intent
dt_iop_color_intent_t display_intent
float d65_color_matrix[9]
dt_image_colorspace_t colorspace
float adobe_XYZ_to_CAM[4][3]
typedef double((*spd)(unsigned long int wavelength, double TempK))
char * dt_read_file(const char *const filename, size_t *filesize)