// Create the ICC virtual profile for sRGB space cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID) { cmsCIExyY D65 = { 0.3127, 0.3290, 1.0 }; cmsCIExyYTRIPLE Rec709Primaries = { {0.6400, 0.3300, 1.0}, {0.3000, 0.6000, 1.0}, {0.1500, 0.0600, 1.0} }; cmsToneCurve* Gamma22[3]; cmsHPROFILE hsRGB; // cmsWhitePointFromTemp(&D65, 6504); Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(ContextID); if (Gamma22[0] == NULL) return NULL; hsRGB = cmsCreateRGBProfileTHR(ContextID, &D65, &Rec709Primaries, Gamma22); cmsFreeToneCurve(Gamma22[0]); if (hsRGB == NULL) return NULL; if (!SetTextTags(hsRGB, L"sRGB built-in")) { cmsCloseProfile(hsRGB); return NULL; } return hsRGB; }
// Creates a fake XYZ identity cmsHPROFILE CMSEXPORT cmsCreateXYZProfileTHR(cmsContext ContextID) { cmsHPROFILE hProfile; cmsPipeline* LUT = NULL; hProfile = cmsCreateRGBProfileTHR(ContextID, cmsD50_xyY(), NULL, NULL); if (hProfile == NULL) return NULL; cmsSetProfileVersion(hProfile, 4.3); cmsSetDeviceClass(hProfile, cmsSigAbstractClass); cmsSetColorSpace(hProfile, cmsSigXYZData); cmsSetPCS(hProfile, cmsSigXYZData); if (!SetTextTags(hProfile, L"XYZ identity built-in")) goto Error; // An identity LUT is all we need LUT = cmsPipelineAlloc(ContextID, 3, 3); if (LUT == NULL) goto Error; if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3))) goto Error; if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error; cmsPipelineFree(LUT); return hProfile; Error: if (LUT != NULL) cmsPipelineFree(LUT); if (hProfile != NULL) cmsCloseProfile(hProfile); return NULL; }
// Creates a fake Lab identity. cmsHPROFILE CMSEXPORT cmsCreateLab2ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint) { cmsHPROFILE hProfile; cmsPipeline* LUT = NULL; hProfile = cmsCreateRGBProfileTHR(ContextID, WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL); if (hProfile == NULL) return NULL; cmsSetProfileVersion(hProfile, 2.1); cmsSetDeviceClass(hProfile, cmsSigAbstractClass); cmsSetColorSpace(hProfile, cmsSigLabData); cmsSetPCS(hProfile, cmsSigLabData); if (!SetTextTags(hProfile, L"Lab identity built-in")) return NULL; // An identity LUT is all we need LUT = cmsPipelineAlloc(ContextID, 3, 3); if (LUT == NULL) goto Error; if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCLut(ContextID, 3))) goto Error; if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error; cmsPipelineFree(LUT); return hProfile; Error: if (LUT != NULL) cmsPipelineFree(LUT); if (hProfile != NULL) cmsCloseProfile(hProfile); return NULL; }
cmsHPROFILE CMSEXPORT cmsCreateRGBProfile(const cmsCIExyY* WhitePoint, const cmsCIExyYTRIPLE* Primaries, cmsToneCurve* const TransferFunction[3]) { return cmsCreateRGBProfileTHR(NULL, WhitePoint, Primaries, TransferFunction); }
/** * cd_util_create_standard_space: **/ static gboolean cd_util_create_standard_space (CdUtilPrivate *priv, CdDom *dom, const GNode *root, GError **error) { CdColorYxy yxy; cmsCIExyYTRIPLE primaries; cmsCIExyY white; cmsToneCurve *transfer[3] = { NULL, NULL, NULL}; const gchar *data; const GNode *tmp; gboolean ret; gdouble curve_gamma; /* parse gamma */ tmp = cd_dom_get_node (dom, root, "gamma"); if (tmp == NULL) { ret = FALSE; g_set_error_literal (error, 1, 0, "XML error, expected gamma"); goto out; } data = cd_dom_get_node_data (tmp); if (g_strcmp0 (data, "sRGB") == 0) { transfer[0] = cd_util_build_srgb_gamma (); transfer[1] = transfer[0]; transfer[2] = transfer[0]; } else if (g_strcmp0 (data, "L*") == 0) { transfer[0] = cd_util_build_lstar_gamma (); transfer[1] = transfer[0]; transfer[2] = transfer[0]; } else if (g_strcmp0 (data, "Rec709") == 0) { transfer[0] = cd_util_build_rec709_gamma (); transfer[1] = transfer[0]; transfer[2] = transfer[0]; } else { curve_gamma = cd_dom_get_node_data_as_double (tmp); if (curve_gamma == G_MAXDOUBLE) { ret = FALSE; g_set_error (error, 1, 0, "failed to parse gamma: '%s'", data); goto out; } transfer[0] = cmsBuildGamma (NULL, curve_gamma); transfer[1] = transfer[0]; transfer[2] = transfer[0]; } /* values taken from https://en.wikipedia.org/wiki/Standard_illuminant */ tmp = cd_dom_get_node (dom, root, "whitepoint"); if (tmp == NULL) { ret = FALSE; g_set_error_literal (error, 1, 0, "XML error, expected whitepoint"); goto out; } data = cd_dom_get_node_data (tmp); white.Y = 1.0f; if (g_strcmp0 (data, "C") == 0) { white.x = 0.31006; white.y = 0.31616; } else if (g_strcmp0 (data, "E") == 0) { white.x = 0.33333; white.y = 0.33333; } else if (g_strcmp0 (data, "D50") == 0) { white.x = 0.345703; white.y = 0.358539; } else if (g_strcmp0 (data, "D65") == 0) { cmsWhitePointFromTemp (&white, 6504); } else { ret = FALSE; g_set_error_literal (error, 1, 0, "unknown illuminant, expected C, E, D50 or D65"); goto out; } /* get red primary */ tmp = cd_dom_get_node (dom, root, "primaries/red"); if (tmp == NULL) { ret = FALSE; g_set_error_literal (error, 1, 0, "XML error, expected primaries/red"); goto out; } ret = cd_dom_get_node_yxy (tmp, &yxy); if (!ret) { g_set_error_literal (error, 1, 0, "XML error, invalid primaries/red"); goto out; } primaries.Red.x = yxy.x; primaries.Red.y = yxy.y; primaries.Red.Y = yxy.Y; /* get green primary */ tmp = cd_dom_get_node (dom, root, "primaries/green"); if (tmp == NULL) { ret = FALSE; g_set_error_literal (error, 1, 0, "XML error, expected primaries/green"); goto out; } ret = cd_dom_get_node_yxy (tmp, &yxy); if (!ret) { g_set_error_literal (error, 1, 0, "XML error, invalid primaries/green"); goto out; } primaries.Green.x = yxy.x; primaries.Green.y = yxy.y; primaries.Green.Y = yxy.Y; /* get blue primary */ tmp = cd_dom_get_node (dom, root, "primaries/blue"); if (tmp == NULL) { ret = FALSE; g_set_error_literal (error, 1, 0, "XML error, expected primaries/blue"); goto out; } ret = cd_dom_get_node_yxy (tmp, &yxy); if (!ret) { g_set_error_literal (error, 1, 0, "XML error, invalid primaries/blue"); goto out; } primaries.Blue.x = yxy.x; primaries.Blue.y = yxy.y; primaries.Blue.Y = yxy.Y; /* create profile */ priv->lcms_profile = cmsCreateRGBProfileTHR (cd_icc_get_context (priv->icc), &white, &primaries, transfer); ret = TRUE; out: cmsFreeToneCurve (transfer[0]); return ret; }