summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmsvirt.c117
1 files changed, 114 insertions, 3 deletions
diff --git a/src/cmsvirt.c b/src/cmsvirt.c
index 951a8ee..d3b6ab2 100644
--- a/src/cmsvirt.c
+++ b/src/cmsvirt.c
@@ -672,6 +672,117 @@ cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfile(void)
return cmsCreate_sRGBProfileTHR(NULL);
}
+/**
+* Oklab colorspace profile (experimental)
+*
+* This virtual profile cannot be saved as an ICC file
+*/
+cmsHPROFILE cmsCreate_OkLabProfile(cmsContext ctx)
+{
+ cmsStage* XYZPCS = _cmsStageNormalizeFromXyzFloat(ctx);
+ cmsStage* PCSXYZ = _cmsStageNormalizeToXyzFloat(ctx);
+
+ const double M_D65_D50[] =
+ {
+ 1.047886, 0.022919, -0.050216,
+ 0.029582, 0.990484, -0.017079,
+ -0.009252, 0.015073, 0.751678
+ };
+
+ const double M_D50_D65[] =
+ {
+ 0.955513, -0.0230732, 0.063309,
+ -0.0283249, 1.00994, 0.0210548,
+ 0.0123289, -0.0205358, 1.33071
+ };
+
+ cmsStage* D65toD50 = cmsStageAllocMatrix(ctx, 3, 3, M_D65_D50, NULL);
+ cmsStage* D50toD65 = cmsStageAllocMatrix(ctx, 3, 3, M_D50_D65, NULL);
+
+ const double M_D65_LMS[] =
+ {
+ 0.8189330101, 0.3618667424, -0.1288597137,
+ 0.0329845436, 0.9293118715, 0.0361456387,
+ 0.0482003018, 0.2643662691, 0.6338517070
+ };
+
+ const double M_LMS_D65[] =
+ {
+ 1.22701, -0.5578, 0.281256,
+ -0.0405802, 1.11226, -0.0716767,
+ -0.0763813, -0.421482, 1.58616
+ };
+
+ cmsStage* D65toLMS = cmsStageAllocMatrix(ctx, 3, 3, M_D65_LMS, NULL);
+ cmsStage* LMStoD65 = cmsStageAllocMatrix(ctx, 3, 3, M_LMS_D65, NULL);
+
+ cmsToneCurve* CubeRoot = cmsBuildGamma(ctx, 1.0 / 3.0);
+ cmsToneCurve* Cube = cmsBuildGamma(ctx, 3.0);
+
+ cmsToneCurve* Roots[3] = { CubeRoot, CubeRoot, CubeRoot };
+ cmsToneCurve* Cubes[3] = { Cube, Cube, Cube };
+
+ cmsStage* NonLinearityFw = cmsStageAllocToneCurves(ctx, 3, Roots);
+ cmsStage* NonLinearityRv = cmsStageAllocToneCurves(ctx, 3, Cubes);
+
+ const double M_LMSprime_OkLab[] =
+ {
+ 0.2104542553, 0.7936177850, -0.0040720468,
+ 1.9779984951, -2.4285922050, 0.4505937099,
+ 0.0259040371, 0.7827717662, -0.8086757660
+ };
+
+ const double M_OkLab_LMSprime[] =
+ {
+ 1.0, 0.396338, 0.215804,
+ 1.0, -0.105561, -0.0638542,
+ 1.0, -0.0894842, -1.29149
+ };
+
+ cmsStage* LMSprime_OkLab = cmsStageAllocMatrix(ctx, 3, 3, M_LMSprime_OkLab, NULL);
+ cmsStage* OkLab_LMSprime = cmsStageAllocMatrix(ctx, 3, 3, M_OkLab_LMSprime, NULL);
+
+ cmsPipeline* AToB = cmsPipelineAlloc(ctx, 3, 3);
+ cmsPipeline* BToA = cmsPipelineAlloc(ctx, 3, 3);
+
+ cmsHPROFILE hProfile = cmsCreateProfilePlaceholder(ctx);
+
+ cmsSetProfileVersion(hProfile, 4.4);
+
+ cmsSetDeviceClass(hProfile, cmsSigColorSpaceClass);
+ cmsSetColorSpace(hProfile, cmsSig3colorData);
+ cmsSetPCS(hProfile, cmsSigXYZData);
+
+ cmsSetHeaderRenderingIntent(hProfile, INTENT_RELATIVE_COLORIMETRIC);
+
+ /**
+ * Conversion PCS (XYZ/D50) to OkLab
+ */
+ cmsPipelineInsertStage(BToA, cmsAT_END, PCSXYZ);
+ cmsPipelineInsertStage(BToA, cmsAT_END, D50toD65);
+ cmsPipelineInsertStage(BToA, cmsAT_END, D65toLMS);
+ cmsPipelineInsertStage(BToA, cmsAT_END, NonLinearityFw);
+ cmsPipelineInsertStage(BToA, cmsAT_END, LMSprime_OkLab);
+
+ cmsWriteTag(hProfile, cmsSigBToA0Tag, BToA);
+
+ cmsPipelineInsertStage(AToB, cmsAT_END, OkLab_LMSprime);
+ cmsPipelineInsertStage(AToB, cmsAT_END, NonLinearityRv);
+ cmsPipelineInsertStage(AToB, cmsAT_END, LMStoD65);
+ cmsPipelineInsertStage(AToB, cmsAT_END, D65toD50);
+ cmsPipelineInsertStage(AToB, cmsAT_END, XYZPCS);
+
+ cmsWriteTag(hProfile, cmsSigAToB0Tag, AToB);
+
+ cmsPipelineFree(BToA);
+ cmsPipelineFree(AToB);
+
+ cmsFreeToneCurve(CubeRoot);
+ cmsFreeToneCurve(Cube);
+
+ return hProfile;
+}
+
typedef struct {
@@ -1062,9 +1173,9 @@ const cmsAllowedLUT* FindCombination(const cmsPipeline* Lut, cmsBool IsV4, cmsTa
cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags)
{
cmsHPROFILE hProfile = NULL;
- cmsUInt32Number FrmIn, FrmOut;
- cmsInt32Number ChansIn, ChansOut;
- int ColorSpaceBitsIn, ColorSpaceBitsOut;
+ cmsUInt32Number FrmIn, FrmOut;
+ cmsInt32Number ChansIn, ChansOut;
+ int ColorSpaceBitsIn, ColorSpaceBitsOut;
_cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
cmsPipeline* LUT = NULL;
cmsStage* mpe;