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;
254 if(input && lutr && lutg && lutb)
257 if(cmsIsToneCurveLinear(red_curve))
260 for(
int k = 0;
k <
lutsize;
k++) lutr[
k] = cmsEvalToneCurveFloat(red_curve,
k / (
lutsize - 1.0f));
261 if(cmsIsToneCurveLinear(green_curve))
264 for(
int k = 0;
k <
lutsize;
k++) lutg[
k] = cmsEvalToneCurveFloat(green_curve,
k / (
lutsize - 1.0f));
265 if(cmsIsToneCurveLinear(blue_curve))
268 for(
int k = 0;
k <
lutsize;
k++) lutb[
k] = cmsEvalToneCurveFloat(blue_curve,
k / (
lutsize - 1.0f));
278 cmsToneCurve *rev_red = cmsReverseToneCurveEx(0x8000, red_curve);
279 cmsToneCurve *rev_green = cmsReverseToneCurveEx(0x8000, green_curve);
280 cmsToneCurve *rev_blue = cmsReverseToneCurveEx(0x8000, blue_curve);
283 cmsFreeToneCurve(rev_red);
284 cmsFreeToneCurve(rev_green);
285 cmsFreeToneCurve(rev_blue);
289 if(lutr && lutg && lutb)
292 if(cmsIsToneCurveLinear(red_curve))
295 for(
int k = 0;
k <
lutsize;
k++) lutr[
k] = cmsEvalToneCurveFloat(rev_red,
k / (
lutsize - 1.0f));
296 if(cmsIsToneCurveLinear(green_curve))
299 for(
int k = 0;
k <
lutsize;
k++) lutg[
k] = cmsEvalToneCurveFloat(rev_green,
k / (
lutsize - 1.0f));
300 if(cmsIsToneCurveLinear(blue_curve))
303 for(
int k = 0;
k <
lutsize;
k++) lutb[
k] = cmsEvalToneCurveFloat(rev_blue,
k / (
lutsize - 1.0f));
306 cmsFreeToneCurve(rev_red);
307 cmsFreeToneCurve(rev_green);
308 cmsFreeToneCurve(rev_blue);
318 float *lutb,
const int lutsize)
324 float *lutb,
const int lutsize)
331 return cmsCreateLab4Profile(cmsD50_xyY());
335 const cmsCIExyYTRIPLE* primaries,
336 cmsCIEXYZTRIPLE *primaries_prequantized)
338 cmsHPROFILE profile = cmsCreateRGBProfile(whitepoint, primaries, NULL);
340 cmsCIEXYZ *
R = cmsReadTag(profile, cmsSigRedColorantTag);
341 cmsCIEXYZ *G = cmsReadTag(profile, cmsSigGreenColorantTag);
342 cmsCIEXYZ *
B = cmsReadTag(profile, cmsSigBlueColorantTag);
344 primaries_prequantized->Red.X = (
double)
R->X;
345 primaries_prequantized->Red.Y = (
double)
R->Y;
346 primaries_prequantized->Red.Z = (
double)
R->Z;
348 primaries_prequantized->Green.X = (
double)G->X;
349 primaries_prequantized->Green.Y = (
double)G->Y;
350 primaries_prequantized->Green.Z = (
double)G->Z;
352 primaries_prequantized->Blue.X = (
double)
B->X;
353 primaries_prequantized->Blue.Y = (
double)
B->Y;
354 primaries_prequantized->Blue.Z = (
double)
B->Z;
356 cmsCloseProfile(profile);
360 const cmsCIExyY *whitepoint,
const cmsCIExyYTRIPLE *primaries, cmsToneCurve *trc,
363 cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
364 cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
365 cmsMLU *mlu3 = cmsMLUalloc(NULL, 1);
366 cmsMLU *mlu4 = cmsMLUalloc(NULL, 1);
368 cmsToneCurve *out_curves[3] = { trc, trc, trc };
369 cmsHPROFILE profile = cmsCreateRGBProfile(whitepoint, primaries, out_curves);
371 if(v2) cmsSetProfileVersion(profile, 2.4);
373 cmsSetHeaderFlags(profile, cmsEmbeddedProfileTrue);
375 cmsMLUsetASCII(mlu1,
"en",
"US",
"Public Domain");
376 cmsWriteTag(profile, cmsSigCopyrightTag, mlu1);
378 cmsMLUsetASCII(mlu2,
"en",
"US", desc);
379 cmsWriteTag(profile, cmsSigProfileDescriptionTag, mlu2);
381 cmsMLUsetASCII(mlu3,
"en",
"US", dmdd);
382 cmsWriteTag(profile, cmsSigDeviceModelDescTag, mlu3);
384 cmsMLUsetASCII(mlu4,
"en",
"US",
"darktable");
385 cmsWriteTag(profile, cmsSigDeviceMfgDescTag, mlu4);
399 static const double M1 = 2610.0 / 16384.0;
400 static const double M2 = (2523.0 / 4096.0) * 128.0;
401 static const double C1 = 3424.0 / 4096.0;
402 static const double C2 = (2413.0 / 4096.0) * 32.0;
403 static const double C3 = (2392.0 / 4096.0) * 32.0;
405 if (
x == 0.0)
return 0.0;
406 const double sign =
x;
409 const double xpo = pow(
x, 1.0 / M2);
410 const double num =
MAX(xpo - C1, 0.0);
411 const double den = C2 - C3 * xpo;
412 const double res = pow(num / den, 1.0 / M1);
414 return copysign(res,
sign);
421 static const double A = 0.17883277;
422 static const double B = 0.28466892;
423 static const double C = 0.55991073;
431 const double sign =
x;
432 const double e = fabs(
x);
435 return copysign((e * e) / 3.0,
sign);
437 return copysign((exp((e -
C) /
A) +
B) / 12.0,
sign);
442 float *values = g_malloc(
sizeof(
float) *
size);
444 for (int32_t
i = 0;
i <
size; ++
i)
446 const double x = (float)
i / (
size - 1);
447 const double y =
MIN(fct(
x), 1.0f);
448 values[
i] = (float)y;
451 cmsToneCurve* result = cmsBuildTabulatedToneCurveFloat(NULL,
size, values);
458 cmsFloat64Number srgb_parameters[5] = { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 };
459 cmsToneCurve *transferFunction = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters);
464 cmsFreeToneCurve(transferFunction);
481 cmsFloat64Number srgb_parameters[5] = { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 };
482 cmsToneCurve *transferFunction = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters);
487 &
D65xyY, &BRG_Primaries, transferFunction,
TRUE);
489 cmsFreeToneCurve(transferFunction);
496 cmsFloat64Number srgb_parameters[5] = { 1/0.45, 1.0 / 1.099, 0.099 / 1.099, 1.0 / 4.5, 0.081 };
497 cmsToneCurve *transferFunction = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters);
502 cmsFreeToneCurve(transferFunction);
510 cmsToneCurve *transferFunction = cmsBuildGamma(NULL, 2.19921875);
512 cmsHPROFILE profile =
_create_lcms_profile(
"ITU-R BT.1886 (gamma 2.4 Rec709)",
"ITU-R BT.1886 (gamma 2.4 Rec709)",
515 cmsFreeToneCurve(transferFunction);
525 cmsToneCurve *transferFunction = cmsBuildGamma(NULL, 2.19921875);
530 cmsFreeToneCurve(transferFunction);
553 cmsCIExyY WP = {
preset->white[0] / wxyz,
preset->white[1] / wxyz, 1.0 };
554 cmsCIExyYTRIPLE XYZPrimaries = { {
preset->rXYZ[0] / rxyz,
preset->rXYZ[1] / rxyz, 1.0 },
555 {
preset->gXYZ[0] / gxyz,
preset->gXYZ[1] / gxyz, 1.0 },
556 {
preset->bXYZ[0] / bxyz,
preset->bXYZ[1] / bxyz, 1.0 } };
557 cmsToneCurve *Gamma[3];
560 Gamma[0] = Gamma[1] = Gamma[2] = cmsBuildGamma(NULL, 1.0);
562 hp = cmsCreateRGBProfile(&WP, &XYZPrimaries, Gamma);
563 cmsFreeToneCurve(Gamma[0]);
567 snprintf(
name,
sizeof(
name),
"darktable alternate %s", makermodel);
568 cmsSetProfileVersion(hp, 2.1);
569 cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
570 cmsMLUsetASCII(mlu0,
"en",
"US",
"(dt internal)");
571 cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
572 cmsMLUsetASCII(mlu1,
"en",
"US",
name);
573 cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
574 cmsMLUsetASCII(mlu2,
"en",
"US",
name);
575 cmsWriteTag(hp, cmsSigDeviceMfgDescTag, mlu0);
576 cmsWriteTag(hp, cmsSigDeviceModelDescTag, mlu1);
578 cmsWriteTag(hp, cmsSigProfileDescriptionTag, mlu2);
603 cmsCIExyY WP = {
preset->white[0] / wxyz,
preset->white[1] / wxyz, 1.0 };
604 cmsCIExyYTRIPLE XYZPrimaries = { {
preset->rXYZ[0] / rxyz,
preset->rXYZ[1] / rxyz, 1.0 },
605 {
preset->gXYZ[0] / gxyz,
preset->gXYZ[1] / gxyz, 1.0 },
606 {
preset->bXYZ[0] / bxyz,
preset->bXYZ[1] / bxyz, 1.0 } };
607 cmsToneCurve *Gamma[3];
610 Gamma[0] = Gamma[1] = Gamma[2] = cmsBuildGamma(NULL, 1.0);
612 hp = cmsCreateRGBProfile(&WP, &XYZPrimaries, Gamma);
613 cmsFreeToneCurve(Gamma[0]);
617 snprintf(
name,
sizeof(
name),
"darktable vendor %s", makermodel);
618 cmsSetProfileVersion(hp, 2.1);
619 cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
620 cmsMLUsetASCII(mlu0,
"en",
"US",
"(dt internal)");
621 cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
622 cmsMLUsetASCII(mlu1,
"en",
"US",
name);
623 cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
624 cmsMLUsetASCII(mlu2,
"en",
"US",
name);
625 cmsWriteTag(hp, cmsSigDeviceMfgDescTag, mlu0);
626 cmsWriteTag(hp, cmsSigDeviceModelDescTag, mlu1);
628 cmsWriteTag(hp, cmsSigProfileDescriptionTag, mlu2);
653 cmsCIExyY WP = {
preset->white[0] / wxyz,
preset->white[1] / wxyz, 1.0 };
654 cmsCIExyYTRIPLE XYZPrimaries = { {
preset->rXYZ[0] / rxyz,
preset->rXYZ[1] / rxyz, 1.0 },
655 {
preset->gXYZ[0] / gxyz,
preset->gXYZ[1] / gxyz, 1.0 },
656 {
preset->bXYZ[0] / bxyz,
preset->bXYZ[1] / bxyz, 1.0 } };
657 cmsToneCurve *Gamma[3];
660 Gamma[0] = Gamma[1] = Gamma[2] = cmsBuildGamma(NULL, 1.0);
662 hp = cmsCreateRGBProfile(&WP, &XYZPrimaries, Gamma);
663 cmsFreeToneCurve(Gamma[0]);
667 snprintf(
name,
sizeof(
name),
"darktable profiled %s", makermodel);
668 cmsSetProfileVersion(hp, 2.1);
669 cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
670 cmsMLUsetASCII(mlu0,
"en",
"US",
"(dt internal)");
671 cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
672 cmsMLUsetASCII(mlu1,
"en",
"US",
name);
673 cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
674 cmsMLUsetASCII(mlu2,
"en",
"US",
name);
675 cmsWriteTag(hp, cmsSigDeviceMfgDescTag, mlu0);
676 cmsWriteTag(hp, cmsSigDeviceModelDescTag, mlu1);
678 cmsWriteTag(hp, cmsSigProfileDescriptionTag, mlu2);
688 cmsHPROFILE hXYZ = cmsCreateXYZProfile();
689 cmsSetPCS(hXYZ, cmsSigXYZData);
690 cmsSetHeaderRenderingIntent(hXYZ, INTENT_PERCEPTUAL);
694 cmsSetProfileVersion(hXYZ, 2.1);
695 cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
696 cmsMLUsetASCII(mlu0,
"en",
"US",
"(dt internal)");
697 cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
698 cmsMLUsetASCII(mlu1,
"en",
"US",
"linear XYZ");
699 cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
700 cmsMLUsetASCII(mlu2,
"en",
"US",
"darktable linear XYZ");
701 cmsWriteTag(hXYZ, cmsSigDeviceMfgDescTag, mlu0);
702 cmsWriteTag(hXYZ, cmsSigDeviceModelDescTag, mlu1);
704 cmsWriteTag(hXYZ, cmsSigProfileDescriptionTag, mlu2);
714 cmsToneCurve *transferFunction = cmsBuildGamma(NULL, 1.0);
719 cmsFreeToneCurve(transferFunction);
726 cmsToneCurve *transferFunction = cmsBuildGamma(NULL, 1.0);
731 cmsFreeToneCurve(transferFunction);
743 cmsFreeToneCurve(transferFunction);
755 cmsFreeToneCurve(transferFunction);
767 cmsFreeToneCurve(transferFunction);
779 cmsFreeToneCurve(transferFunction);
786 cmsFloat64Number srgb_parameters[5] = { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 };
787 cmsToneCurve *transferFunction = cmsBuildParametricToneCurve(NULL, 4, srgb_parameters);
792 cmsFreeToneCurve(transferFunction);
799 cmsToneCurve *transferFunction = cmsBuildGamma(NULL, 1.0);
804 cmsFreeToneCurve(transferFunction);
811 cmsToneCurve *transferFunction = cmsBuildGamma(NULL, 1.0);
816 cmsHPROFILE profile =
_create_lcms_profile(
"Linear Infrared BGR",
"darktable Linear Infrared BGR",
819 cmsFreeToneCurve(transferFunction);
830 for(
const GList *modules =
darktable.
iop; modules; modules = g_list_next(modules))
833 if(!strcmp(module->op,
"colorin"))
843 if(colorin && colorin->get_p)
851 "SELECT op_params FROM main.history WHERE imgid=?1 AND operation='colorin' ORDER BY num DESC LIMIT 1", -1,
855 if(sqlite3_step(stmt) == SQLITE_ROW)
858 const void *params = sqlite3_column_blob(stmt, 0);
860 char *filename = colorin->get_p(params,
"filename_work");
865 sqlite3_finalize(stmt);
881 *new_profile =
FALSE;
885 gboolean from_cache =
TRUE;
888 const gchar *cc = filename + strlen(filename);
889 for(; *cc !=
'.' && cc > filename; cc--);
890 gchar *ext = g_ascii_strdown(cc + 1, -1);
897 gboolean already_set =
FALSE;
966 else if(!strcmp(ext,
"pfm"))
983 if(!strcmp(ext,
"jpg") || !strcmp(ext,
"jpeg"))
990 else if(!strcmp(ext,
"jp2") || !strcmp(ext,
"j2k") || !strcmp(ext,
"j2c") || !strcmp(ext,
"jpc"))
995 else if((!strcmp(ext,
"tif") || !strcmp(ext,
"tiff")))
999 else if(!strcmp(ext,
"png"))
1004 else if(!strcmp(ext,
"avif"))
1018 else if(!strcmp(ext,
"heif") || !strcmp(ext,
"heic") || !strcmp(ext,
"hif"))
1040 *new_profile =
TRUE;
1061 return color_profile;
1067 cmsHPROFILE *output,
1068 gboolean *new_profile)
1070 if(output) *output = NULL;
1071 if(new_profile) *new_profile =
FALSE;
1096 gboolean dummy_new_profile =
FALSE;
1103 cmsHPROFILE profile = NULL;
1157 if(new_profile) *new_profile =
TRUE;
1179 gboolean new_profile;
1188 char *lang = getenv(
"LANG");
1202 const char *over_filename)
1235static void dt_colorspaces_create_cmatrix(
float cmatrix[4][3],
float mat[3][3])
1238 static const dt_colormatrix_t rgb_to_xyz = { { 0.4124564f, 0.3575761f, 0.1804375f, 0.0f },
1239 { 0.2126729f, 0.7151522f, 0.0721750f, 0.0f },
1240 { 0.0193339f, 0.1191920f, 0.9503041f, 0.0f } };
1242 for(
int c = 0;
c < 3;
c++)
1244 for(
int j = 0; j < 3; j++)
1247 for(
int k = 0;
k < 3;
k++)
1249 mat[
c][j] += rgb_to_xyz[
k][j] * cmatrix[
c][
k];
1260 for(
int k = 0;
k < 3;
k++)
1262 const float norm = mat[0][
k] + mat[1][
k] + mat[2][
k];
1263 x[
k] = mat[0][
k] / norm;
1264 y[
k] = mat[1][
k] / norm;
1266 cmsCIExyYTRIPLE CameraPrimaries = { {
x[0], y[0], 1.0 }, {
x[1], y[1], 1.0 }, {
x[2], y[2], 1.0 } };
1267 cmsHPROFILE profile;
1270 cmsXYZ2xyY(&D65, &
d65);
1272 cmsToneCurve *Gamma[3];
1273 Gamma[0] = Gamma[1] = Gamma[2] = cmsBuildGamma(NULL, 1.0);
1274 profile = cmsCreateRGBProfile(&D65, &CameraPrimaries, Gamma);
1275 cmsFreeToneCurve(Gamma[0]);
1278 cmsSetProfileVersion(profile, 2.1);
1279 cmsMLU *mlu0 = cmsMLUalloc(NULL, 1);
1280 cmsMLUsetASCII(mlu0,
"en",
"US",
"(dt internal)");
1281 cmsMLU *mlu1 = cmsMLUalloc(NULL, 1);
1282 cmsMLUsetASCII(mlu1,
"en",
"US",
"color matrix built-in");
1283 cmsMLU *mlu2 = cmsMLUalloc(NULL, 1);
1284 cmsMLUsetASCII(mlu2,
"en",
"US",
"color matrix built-in");
1285 cmsWriteTag(profile, cmsSigDeviceMfgDescTag, mlu0);
1286 cmsWriteTag(profile, cmsSigDeviceModelDescTag, mlu1);
1288 cmsWriteTag(profile, cmsSigProfileDescriptionTag, mlu2);
1300 mat3inv((
float *)imat, (
float *)mat);
1306 if(profile && cmsGetColorSpace(profile) == cmsSigGrayData)
1308 cmsToneCurve *trc = cmsReadTag(profile, cmsSigGrayTRCTag);
1309 cmsCIEXYZ *wtpt = cmsReadTag(profile, cmsSigMediaWhitePointTag);
1310 cmsCIEXYZ *bkpt = cmsReadTag(profile, cmsSigMediaBlackPointTag);
1311 cmsCIEXYZ *chad = cmsReadTag(profile, cmsSigChromaticAdaptationTag);
1313 cmsMLU *cprt = cmsReadTag(profile, cmsSigCopyrightTag);
1314 cmsMLU *desc = cmsReadTag(profile, cmsSigProfileDescriptionTag);
1315 cmsMLU *dmnd = cmsReadTag(profile, cmsSigDeviceMfgDescTag);
1316 cmsMLU *dmdd = cmsReadTag(profile, cmsSigDeviceModelDescTag);
1318 cmsHPROFILE rgb_profile = cmsCreateProfilePlaceholder(0);
1320 cmsSetDeviceClass(rgb_profile, cmsSigDisplayClass);
1321 cmsSetColorSpace(rgb_profile, cmsSigRgbData);
1322 cmsSetPCS(rgb_profile, cmsSigXYZData);
1324 cmsWriteTag(rgb_profile, cmsSigCopyrightTag, cprt);
1325 cmsWriteTag(rgb_profile, cmsSigProfileDescriptionTag, desc);
1326 cmsWriteTag(rgb_profile, cmsSigDeviceMfgDescTag, dmnd);
1327 cmsWriteTag(rgb_profile, cmsSigDeviceModelDescTag, dmdd);
1329 cmsWriteTag(rgb_profile, cmsSigMediaBlackPointTag, bkpt);
1330 cmsWriteTag(rgb_profile, cmsSigMediaWhitePointTag, wtpt);
1331 cmsWriteTag(rgb_profile, cmsSigChromaticAdaptationTag, chad);
1332 cmsSetColorSpace(rgb_profile, cmsSigRgbData);
1333 cmsSetPCS(rgb_profile, cmsSigXYZData);
1341 cmsWriteTag(rgb_profile, cmsSigRedTRCTag, (
void *)trc);
1342 cmsLinkTag(rgb_profile, cmsSigGreenTRCTag, cmsSigRedTRCTag);
1343 cmsLinkTag(rgb_profile, cmsSigBlueTRCTag, cmsSigRedTRCTag);
1345 cmsCloseProfile(profile);
1346 profile = rgb_profile;
1368 cmsUInt32Number
size;
1370 wchar_t *wbuf = NULL;
1373 size = cmsGetProfileInfoASCII(
p, cmsInfoDescription, language, country, NULL, 0);
1376 buf = (
char *)calloc(
size + 1,
sizeof(
char));
1377 size = cmsGetProfileInfoASCII(
p, cmsInfoDescription, language, country, buf,
size);
1381 if(
sizeof(
wchar_t) != 4 || g_utf8_validate(buf, -1, NULL))
1382 g_strlcpy(
name, buf, len);
1385 wbuf = (
wchar_t *)calloc(
size + 1,
sizeof(
wchar_t));
1386 size = cmsGetProfileInfo(
p, cmsInfoDescription, language, country, wbuf,
sizeof(
wchar_t) *
size);
1388 utf8 = g_ucs4_to_utf8((gunichar *)wbuf, -1, NULL, NULL, NULL);
1390 g_strlcpy(
name, utf8, len);
1400 g_strlcpy(
name, buf, len);
1411 const float pmax = fmaxf(
r, fmax(
g, b));
1412 const float pmin = fminf(
r, fmin(
g, b));
1413 const float delta = (pmax - pmin);
1415 float hv = 0, sv = 0, lv = (pmin + pmax) / 2.0;
1419 sv = lv < 0.5 ?
delta / fmaxf(pmax + pmin, 1.52587890625e-05f)
1420 :
delta / fmaxf(2.0 - pmax - pmin, 1.52587890625e-05f);
1425 hv = 2.0 + (b -
r) /
delta;
1440static inline __attribute__((always_inline))
float hue2rgb(
float m1,
float m2,
float hue)
1445 return (m1 + (m2 - m1) * hue);
1449 return hue < 4.0f ? (m1 + (m2 - m1) * (4.0f - hue)) : m1;
1460 m2 = l < 0.5 ? l * (1.0 + s) : l + s - l * s;
1461 m1 = (2.0 * l - m2);
1463 rgb[0] = hue2rgb(m1, m2, h < 4.0f ? h + 2.0f : h - 4.0f);
1464 rgb[1] = hue2rgb(m1, m2, h);
1465 rgb[2] = hue2rgb(m1, m2, h > 2.0f ? h - 2.0f : h + 4.0f);
1469 cmsHPROFILE profile,
const char *
name,
int in_pos,
1470 int out_pos,
int display_pos,
int category_pos,
1505 cmsHPROFILE display_profile = display_dt_profile->
profile;
1563 for(
int y = 0; y <
height; y++)
1565 const float *
const in = image_in + (size_t)y *
width * 4;
1566 float *
const out = image_out + (size_t)y *
width * 4;
1579 for(
int y = 0; y <
height; y++)
1581 const uint8_t *
const restrict in = image_in + (size_t)y *
width * 4u;
1582 uint8_t *
const restrict
out = image_out + (size_t)y *
width * 4u;
1587 for(
int x = 0;
x <
width;
x++)
out[4 *
x + 3] = UINT8_MAX;
1593 out[4 *
x + 0] = in[4 *
x + 2];
1594 out[4 *
x + 1] = in[4 *
x + 1];
1595 out[4 *
x + 2] = in[4 *
x + 0];
1596 out[4 *
x + 3] = UINT8_MAX;
1609 cmsHPROFILE profile = cmsOpenProfileFromMem(tmp_data,
size);
1618 p->profile = profile;
1641 gchar *name_a = g_utf8_casefold(profile_a->
name, -1);
1642 gchar *name_b = g_utf8_casefold(profile_b->
name, -1);
1644 gint result = g_strcmp0(name_a, name_b);
1654 GList *temp_profiles = NULL;
1655 const gchar *d_name;
1660 char *lang = getenv(
"LANG");
1663 char *dirname = g_build_filename(confdir,
"color", subdir, NULL);
1664 if(!g_file_test(dirname, G_FILE_TEST_IS_DIR))
1667 dirname = g_build_filename(datadir,
"color", subdir, NULL);
1669 GDir *dir = g_dir_open(dirname, 0, NULL);
1672 while((d_name = g_dir_read_name(dir)))
1674 char *filename = g_build_filename(dirname, d_name, NULL);
1675 const char *cc = filename + strlen(filename);
1676 for(; *cc !=
'.' && cc > filename; cc--)
1678 if(!g_ascii_strcasecmp(cc,
".icc") || !g_ascii_strcasecmp(cc,
".icm"))
1682 if(
IS_NULL_PTR(icc_content))
goto icc_loading_done;
1685 cmsHPROFILE tmpprof =
_ensure_rgb_profile(cmsOpenProfileFromMem(icc_content,
sizeof(
char) * end));
1690 if(prof->
name[0] ==
'\0')
1691 g_strlcpy(prof->
name, _(
"(unknown name)"),
sizeof(prof->
name));
1702 temp_profiles = g_list_prepend(temp_profiles, prof);
1714 return temp_profiles;
1735 -1, ++category_pos, -1));
1738 -1, -1, ++category_pos, -1));
1742 -1, ++category_pos, -1));
1747 _(
"System display profile (recommended)"), -1, -1, ++display_pos, ++category_pos, -1));
1754 _(
"sRGB (e.g. JPG)"), ++in_pos, -1, -1, -1, -1));
1758 _(
"sRGB"), -1, ++out_pos, ++display_pos,
1759 ++category_pos, ++work_pos));
1763 _(
"Adobe RGB (compatible)"), ++in_pos, ++out_pos, ++display_pos,
1764 ++category_pos, ++work_pos));
1768 _(
"linear Rec709 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1772 _(
"gamma Rec709 RGB"), ++in_pos, ++out_pos, -1, -1,
1776 _(
"ITU-R BT.1886 (gamma 2.4 Rec709)"), ++in_pos, ++out_pos, -1, -1,
1781 _(
"linear Rec2020 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1786 _(
"PQ Rec2020 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1791 _(
"HLG Rec2020 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1796 _(
"PQ P3 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1801 _(
"HLG P3 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1806 _(
"Display P3 RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1811 _(
"linear ProPhoto RGB"), ++in_pos, ++out_pos, ++display_pos, ++category_pos,
1825 _(
"linear infrared BGR"), ++in_pos, -1, -1, -1, -1));
1829 _(
"BRG (for testing)"), ++in_pos, ++out_pos, ++display_pos,
1856 GList *temp_profiles;
1860 for(GList *iter = temp_profiles; iter; iter = g_list_next(iter))
1869 for(GList *iter = temp_profiles; iter; iter = g_list_next(iter))
1880 const gboolean is_valid_matrix_profile
1885 if(is_valid_matrix_profile)
1893 "output profile `%s' color space `%c%c%c%c' not supported for work or histogram profile\n",
1931 for(GList *iter = self->
profiles; iter; iter = g_list_next(iter))
1947 const char *filename)
1958 return _(
"Adobe RGB (compatible)");
1960 return _(
"linear Rec709 RGB");
1962 return _(
"linear Rec2020 RGB");
1964 return _(
"linear XYZ");
1968 return _(
"linear infrared BGR");
1970 return _(
"System display profile (recommended)");
1972 return _(
"embedded ICC profile");
1974 return _(
"embedded matrix");
1976 return _(
"standard color matrix");
1978 return _(
"enhanced color matrix");
1980 return _(
"vendor color matrix");
1982 return _(
"alternate color matrix");
1984 return _(
"BRG (experimental)");
1986 return _(
"export profile");
1988 return _(
"softproof profile");
1990 return _(
"work profile");
1992 return _(
"Not used. Shouldn't be here.");
1994 return _(
"Rec709 RGB");
1996 return _(
"linear ProPhoto RGB");
1998 return _(
"PQ Rec2020");
2000 return _(
"HLG Rec2020");
2006 return _(
"Display P3");
2008 return _(
"ITU-R BT.1886");
2017static void dt_colorspaces_get_display_profile_colord_callback(GObject *source, GAsyncResult *res, gpointer user_data)
2022 CdWindow *window = CD_WINDOW(source);
2023 GError *
error = NULL;
2024 CdProfile *profile = cd_window_get_profile_finish(window, res, &
error);
2027 const gchar *filename = cd_profile_get_filename(profile);
2039 guchar *tmp_data = NULL;
2041 g_file_get_contents(filename, (gchar **)&tmp_data, &
size, NULL);
2049 "[color profile] colord gave us a new screen profile: '%s' (size: %" G_GSIZE_FORMAT
")\n", filename,
size);
2058 if(profile) g_object_unref(profile);
2059 g_object_unref(window);
2067#if defined GDK_WINDOWING_X11
2068static int _gtk_get_monitor_num(GdkMonitor *monitor)
2070 GdkDisplay *display;
2073 display = gdk_monitor_get_display(monitor);
2074 n_monitors = gdk_display_get_n_monitors(display);
2075 for(
i = 0;
i < n_monitors;
i++)
2077 if(gdk_display_get_monitor(display,
i) == monitor)
return i;
2098 guint8 *buffer = NULL;
2099 gint buffer_size = 0;
2100 gchar *profile_source = NULL;
2102#if defined GDK_WINDOWING_X11
2105 gboolean use_xatom =
TRUE;
2106#if defined USE_COLORDGTK
2107 gboolean use_colord =
TRUE;
2110 if(display_profile_source)
2112 if(!strcmp(display_profile_source,
"xatom"))
2114 else if(!strcmp(display_profile_source,
"colord"))
2123 GdkWindow *window = gtk_widget_get_window(widget);
2124 GdkScreen *screen = gtk_widget_get_screen(widget);
2125 if(
IS_NULL_PTR(screen)) screen = gdk_screen_get_default();
2127 GdkDisplay *display = gtk_widget_get_display(widget);
2128 int monitor = _gtk_get_monitor_num(gdk_display_get_monitor_at_window(display, window));
2132 atom_name = g_strdup_printf(
"_ICC_PROFILE_%d", monitor);
2134 atom_name = g_strdup(
"_ICC_PROFILE");
2136 profile_source = g_strdup_printf(
"xatom %s", atom_name);
2138 GdkAtom
type = GDK_NONE;
2140 gdk_property_get(gdk_screen_get_root_window(screen), gdk_atom_intern(atom_name,
FALSE), GDK_NONE, 0,
2141 64 * 1024 * 1024,
FALSE, &
type, &format, &buffer_size, &buffer);
2149 CdWindow *window = cd_window_new();
2151 cd_window_get_profile(window, center_widget, NULL, dt_colorspaces_get_display_profile_colord_callback,
2152 GINT_TO_POINTER(profile_type));
2156#elif defined GDK_WINDOWING_QUARTZ
2159 GdkScreen *screen = gtk_widget_get_screen(widget);
2160 if(
IS_NULL_PTR(screen)) screen = gdk_screen_get_default();
2161 int monitor = gdk_screen_get_monitor_at_window(screen, gtk_widget_get_window(widget));
2163 CGDirectDisplayID ids[monitor + 1];
2165 CMProfileRef prof = NULL;
2166 if(CGGetOnlineDisplayList(monitor + 1, &ids[0], &total_ids) == kCGErrorSuccess && total_ids == monitor + 1)
2167 CMGetProfileByAVID(ids[monitor], &prof);
2171 data = CMProfileCopyICCData(NULL, prof);
2172 CMCloseProfile(prof);
2174 UInt8 *tmp_buffer = (UInt8 *)g_malloc(CFDataGetLength(data));
2175 CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), tmp_buffer);
2177 buffer = (guint8 *)tmp_buffer;
2178 buffer_size = CFDataGetLength(data);
2182 profile_source = g_strdup(
"osx color profile api");
2184#elif defined G_OS_WIN32
2187 GdkWindow *window = gtk_widget_get_window(widget);
2188 HWND hwnd = (HWND)gdk_win32_window_get_handle(window);
2189 HMONITOR hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
2191 MONITORINFOEX monitorInfo;
2192 monitorInfo.cbSize =
sizeof(MONITORINFOEX);
2193 if(!GetMonitorInfoW(hMonitor,(LPMONITORINFO) &monitorInfo)) {
return;}
2194 HDC hdc = CreateIC(
L"MONITOR",monitorInfo.szDevice,NULL,NULL);
2198 GetICMProfile(hdc, &len, NULL);
2199 wchar_t *wpath = g_new(
wchar_t, len);
2201 if(GetICMProfileW(hdc, &len, wpath))
2203 gchar *path = g_utf16_to_utf8(wpath, -1, NULL, NULL, NULL);
2207 g_file_get_contents(path, (gchar **)&buffer, &
size, NULL);
2215 profile_source = g_strdup(
"windows color profile api");
2223 char name[512] = { 0 };
2226 *
name ?
name :
"(unknown)", profile_source, buffer_size);
2239 const char *
f = profile;
2242 if(*
f ==
'/' || *
f ==
'\\')
return FALSE;
2250 const char*
f = profile + strlen(profile);
2251 for (;
f >= profile;
f--)
2253 if(*
f ==
'/' || *
f ==
'\\')
2506 const char *filename,
2509 for(GList *iter = self->
profiles; iter; iter = g_list_next(iter))
2527 const char *filename,
2539 for(
int i = 0;
i < 3;
i++) {
2540 for(
int j = 0; j < 6; j++)
2541 work[
i][j] = j ==
i+3;
2542 for(
int j = 0; j < 3; j++)
2544 work[
i][j] += in[
k][
i] * in[
k][j];
2546 for(
int i = 0;
i < 3;
i++) {
2547 double num = work[
i][
i];
2548 for(
int j = 0; j < 6; j++)
2550 for(
int k = 0;
k < 3;
k++) {
2553 for(
int j = 0; j < 6; j++)
2554 work[
k][j] -= work[
i][j] * num;
2558 for(
int j = 0; j < 3; j++)
2561 for(
int k = 0;
k < 3;
k++)
2562 out[
i][j] += work[j][
k+3] * in[
i][
k];
2568 if(!isnan(in_XYZ_to_CAM[0]))
2570 for(
int i = 0;
i < 9;
i++)
2571 XYZ_to_CAM[
i/3][
i%3] = (
double) in_XYZ_to_CAM[
i];
2572 for(
int i = 0;
i < 3;
i++)
2573 XYZ_to_CAM[3][
i] = 0.0f;
2577 if(isnan(adobe_XYZ_to_CAM[0][0]))
2580 for(
int i = 0;
i < 4;
i++)
2581 for(
int j = 0; j < 3; j++)
2582 XYZ_to_CAM[
i][j] = (
double)adobe_XYZ_to_CAM[
i][j];
2586 double inverse[4][3];
2588 for(
int i = 0;
i < 3;
i++)
2589 for(
int j = 0; j < 4; j++)
2590 CAM_to_XYZ[
i][j] = inverse[j][
i];
2599 double out_RGB_to_CAM[4][3],
double out_CAM_to_RGB[3][4],
2600 const float *embedded_matrix,
2603 double RGB_to_CAM[4][3];
2605 float XYZ_to_CAM[4][3];
2606 XYZ_to_CAM[0][0] = NAN;
2608 if(
IS_NULL_PTR(embedded_matrix) || isnan(embedded_matrix[0]))
2610 for(
int k=0;
k<4;
k++)
2611 for(
int i=0;
i<3;
i++)
2612 XYZ_to_CAM[
k][
i] = adobe_XYZ_to_CAM[
k][
i];
2618 XYZ_to_CAM[0][0] = embedded_matrix[0];
2619 XYZ_to_CAM[0][1] = embedded_matrix[1];
2620 XYZ_to_CAM[0][2] = embedded_matrix[2];
2622 XYZ_to_CAM[1][0] = embedded_matrix[3];
2623 XYZ_to_CAM[1][1] = embedded_matrix[4];
2624 XYZ_to_CAM[1][2] = embedded_matrix[5];
2626 XYZ_to_CAM[2][0] = embedded_matrix[6];
2627 XYZ_to_CAM[2][1] = embedded_matrix[7];
2628 XYZ_to_CAM[2][2] = embedded_matrix[8];
2631 if(isnan(XYZ_to_CAM[0][0]))
2634 const double RGB_to_XYZ[3][3] = {
2636 { 0.412453, 0.357580, 0.180423 },
2637 { 0.212671, 0.715160, 0.072169 },
2638 { 0.019334, 0.119193, 0.950227 },
2642 for(
int i = 0;
i < 4;
i++)
2643 for(
int j = 0; j < 3; j++)
2645 RGB_to_CAM[
i][j] = 0.0f;
2646 for(
int k = 0;
k < 3;
k++)
2647 RGB_to_CAM[
i][j] += XYZ_to_CAM[
i][
k] * RGB_to_XYZ[
k][j];
2651 for(
int i = 0;
i < 4;
i++) {
2653 for(
int j = 0; j < 3; j++)
2654 num += RGB_to_CAM[
i][j];
2655 for(
int j = 0; j < 3; j++)
2656 RGB_to_CAM[
i][j] /= num;
2657 if(mul) mul[
i] = 1.0f / num;
2661 for(
int i = 0;
i < 4;
i++)
2662 for(
int j = 0; j < 3; j++)
2663 out_RGB_to_CAM[
i][j] = RGB_to_CAM[
i][j];
2668 double inverse[4][3];
2670 for(
int i = 0;
i < 3;
i++)
2671 for(
int j = 0; j < 4; j++)
2672 out_CAM_to_RGB[
i][j] = inverse[j][
i];
2682 double CAM_to_RGB_WB[3][4];
2683 for (
int a=0; a<3; a++)
2684 for (
int b=0; b<4; b++)
2685 CAM_to_RGB_WB[a][b] = CAM_to_RGB[a][b] * coeffs[b];
2688 double RGB_to_RGB_WB[3][3];
2689 for (
int a=0; a<3; a++)
2690 for (
int b=0; b<3; b++) {
2691 RGB_to_RGB_WB[a][b] = 0.0f;
2692 for (
int c=0; c<4; c++)
2693 RGB_to_RGB_WB[a][b] += CAM_to_RGB_WB[a][c] * RGB_to_CAM[c][b];
2696 for(
int i = 0;
i < num;
i++)
2698 const float *inpos = &in[
i*4];
2699 float *outpos = &
out[
i*4];
2700 outpos[0]=outpos[1]=outpos[2] = 0.0f;
2701 for (
int a=0; a<3; a++)
2702 for (
int b=0; b<3; b++)
2703 outpos[a] += RGB_to_RGB_WB[a][b] * inpos[b];
2711 for(
int i = 0;
i < num;
i++)
2713 float *in = &
out[
i*4];
2715 for(
int c = 0; c < 3; c++)
2716 for(
int k = 0;
k < 4;
k++)
2717 o[c] += CAM_to_RGB[c][
k] * in[
k];
2718 for(
int c = 0; c < 3; c++)
2726 for(
int i = 0;
i < num;
i++)
2728 float *in = &
out[
i*3];
2730 for(
int c = 0; c < 4; c++)
2731 for(
int k = 0;
k < 3;
k++)
2732 o[c] += RGB_to_CAM[c][
k] * in[
k];
2733 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)