static cmsHPROFILE * gimp_color_profile_new_d50_gray_lab_trc_internal (void) { cmsHPROFILE profile; /* white point is D50 from the ICC profile illuminant specs */ cmsCIExyY whitepoint = {0.345702915, 0.358538597, 1.0}; cmsFloat64Number lab_parameters[5] = { 3.0, 1.0 / 1.16, 0.16 / 1.16, 2700.0 / 24389.0, 0.08000 }; cmsToneCurve *curve = cmsBuildParametricToneCurve (NULL, 4, lab_parameters); profile = cmsCreateGrayProfile (&whitepoint, curve); cmsFreeToneCurve (curve); gimp_color_profile_set_tag (profile, cmsSigProfileDescriptionTag, "GIMP built-in D50 Grayscale with LAB L TRC"); gimp_color_profile_set_tag (profile, cmsSigDeviceMfgDescTag, "GIMP"); gimp_color_profile_set_tag (profile, cmsSigDeviceModelDescTag, "D50 Grayscale with LAB L TRC"); gimp_color_profile_set_tag (profile, cmsSigCopyrightTag, "Public Domain"); return profile; }
static cmsHPROFILE * gimp_color_profile_new_d65_gray_srgb_trc_internal (void) { cmsHPROFILE profile; /* white point is D65 from the sRGB specs */ cmsCIExyY whitepoint = { 0.3127, 0.3290, 1.0 }; cmsFloat64Number srgb_parameters[5] = { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 }; cmsToneCurve *curve = cmsBuildParametricToneCurve (NULL, 4, srgb_parameters); profile = cmsCreateGrayProfile (&whitepoint, curve); cmsFreeToneCurve (curve); gimp_color_profile_set_tag (profile, cmsSigProfileDescriptionTag, "GIMP built-in D65 Grayscale with sRGB TRC"); gimp_color_profile_set_tag (profile, cmsSigDeviceMfgDescTag, "GIMP"); gimp_color_profile_set_tag (profile, cmsSigDeviceModelDescTag, "D65 Grayscale with sRGB TRC"); gimp_color_profile_set_tag (profile, cmsSigCopyrightTag, "Public Domain"); return profile; }
static cmsHPROFILE * gimp_color_profile_new_rgb_srgb_internal (void) { cmsHPROFILE profile; /* white point is D65 from the sRGB specs */ cmsCIExyY whitepoint = { 0.3127, 0.3290, 1.0 }; /* primaries are ITU‐R BT.709‐5 (xYY), which are also the primaries * from the sRGB specs, modified to properly account for hexadecimal * quantization during the profile making process. */ cmsCIExyYTRIPLE primaries = { /* R { 0.6400, 0.3300, 1.0 }, */ /* G { 0.3000, 0.6000, 1.0 }, */ /* B { 0.1500, 0.0600, 1.0 } */ /* R */ { 0.639998686, 0.330010138, 1.0 }, /* G */ { 0.300003784, 0.600003357, 1.0 }, /* B */ { 0.150002046, 0.059997204, 1.0 } }; cmsFloat64Number srgb_parameters[5] = { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 }; cmsToneCurve *curve[3]; /* sRGB curve */ curve[0] = curve[1] = curve[2] = cmsBuildParametricToneCurve (NULL, 4, srgb_parameters); profile = cmsCreateRGBProfile (&whitepoint, &primaries, curve); cmsFreeToneCurve (curve[0]); gimp_color_profile_set_tag (profile, cmsSigProfileDescriptionTag, "GIMP built-in sRGB"); gimp_color_profile_set_tag (profile, cmsSigDeviceMfgDescTag, "GIMP"); gimp_color_profile_set_tag (profile, cmsSigDeviceModelDescTag, "sRGB"); gimp_color_profile_set_tag (profile, cmsSigCopyrightTag, "Public Domain"); /* The following line produces a V2 profile with a point curve TRC. * Profiles with point curve TRCs can't be used in LCMS2 unbounded * mode ICC profile conversions. A V2 profile might be appropriate * for embedding in sRGB images saved to disk, if the image is to be * opened by an image editing application that doesn't understand V4 * profiles. * * cmsSetProfileVersion (srgb_profile, 2.1); */ return profile; }
static cmsToneCurve* build_linear_gamma(void) { double Parameters[2]; Parameters[0] = 1.0; Parameters[1] = 0; return cmsBuildParametricToneCurve(0, 1, Parameters); }
/** * cd_util_build_rec709_gamma: **/ static cmsToneCurve * cd_util_build_rec709_gamma (void) { cmsFloat64Number params[5]; params[0] = 1.0 / 0.45; params[1] = 1.099; params[2] = 0.099; params[3] = 4.500; params[4] = 0.018; return cmsBuildParametricToneCurve (NULL, LCMS_CURVE_PLUGIN_TYPE_REC709, params); }
/** * cd_util_build_lstar_gamma: **/ static cmsToneCurve * cd_util_build_lstar_gamma (void) { cmsFloat64Number params[5]; params[0] = 3.000000; params[1] = 0.862076; params[2] = 0.137924; params[3] = 0.110703; params[4] = 0.080002; return cmsBuildParametricToneCurve (NULL, 4, params); }
/** * cd_util_build_srgb_gamma: * * Values taken from lcms2. **/ static cmsToneCurve * cd_util_build_srgb_gamma (void) { cmsFloat64Number params[5]; params[0] = 2.4; params[1] = 1. / 1.055; params[2] = 0.055 / 1.055; params[3] = 1. / 12.92; params[4] = 0.04045; return cmsBuildParametricToneCurve (NULL, 4, params); }
static cmsToneCurve* build_adobergb_gamma(void) { // this is wrong, this should be a TRC not a table gamma double Parameters[2]; Parameters[0] = 2.2; Parameters[1] = 0; return cmsBuildParametricToneCurve(NULL, 1, Parameters); }
static cmsToneCurve* Build_sRGBGamma(cmsContext ContextID) { cmsFloat64Number Parameters[5]; Parameters[0] = 2.4; Parameters[1] = 1. / 1.055; Parameters[2] = 0.055 / 1.055; Parameters[3] = 1. / 12.92; Parameters[4] = 0.04045; return cmsBuildParametricToneCurve(ContextID, 4, Parameters); }
static cmsToneCurve* build_srgb_gamma(void) { double Parameters[5]; Parameters[0] = 2.4; Parameters[1] = 1. / 1.055; Parameters[2] = 0.055 / 1.055; Parameters[3] = 1. / 12.92; Parameters[4] = 0.04045; // d return cmsBuildParametricToneCurve(NULL, 4, Parameters); }
static GimpColorProfile gimp_lcms_create_srgb_profile_internal (void) { cmsHPROFILE srgb_profile; cmsCIExyY d65_srgb_specs = { 0.3127, 0.3290, 1.0 }; cmsCIExyYTRIPLE srgb_primaries_pre_quantized = { { 0.639998686, 0.330010138, 1.0 }, { 0.300003784, 0.600003357, 1.0 }, { 0.150002046, 0.059997204, 1.0 } }; cmsFloat64Number srgb_parameters[5] = { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 }; cmsToneCurve *srgb_parametric_curve = cmsBuildParametricToneCurve (NULL, 4, srgb_parameters); cmsToneCurve *tone_curve[3]; tone_curve[0] = tone_curve[1] = tone_curve[2] = srgb_parametric_curve; srgb_profile = cmsCreateRGBProfile (&d65_srgb_specs, &srgb_primaries_pre_quantized, tone_curve); cmsFreeToneCurve (srgb_parametric_curve); gimp_lcms_profile_set_tag (srgb_profile, cmsSigProfileDescriptionTag, "GIMP built-in sRGB"); gimp_lcms_profile_set_tag (srgb_profile, cmsSigDeviceMfgDescTag, "GIMP"); gimp_lcms_profile_set_tag (srgb_profile, cmsSigDeviceModelDescTag, "sRGB"); gimp_lcms_profile_set_tag (srgb_profile, cmsSigCopyrightTag, "Public Domain"); /** * The following line produces a V2 profile with a point curve TRC. * Profiles with point curve TRCs can't be used in LCMS2 unbounded * mode ICC profile conversions. A V2 profile might be appropriate * for embedding in sRGB images saved to disk, if the image is to be * opened by an image editing application that doesn't understand V4 * profiles. * * cmsSetProfileVersion (srgb_profile, 2.1); **/ return srgb_profile; }
static void init(void) { cmsCIEXYZ D65_XYZ = {0.95047, 1.0, 1.08883 }; cmsCIExyY D65; cmsXYZ2xyY(&D65, &D65_XYZ); cmsToneCurve *linear = cmsBuildGamma(NULL, 1.0); cmsToneCurve *linrgb[3] = {linear,linear,linear}; cmsCIExyYTRIPLE primaries = { {0.64, 0.33, 1.0}, {0.30, 0.60, 1.0}, {0.15, 0.06, 1.0} }; cmsFloat64Number P[5] = { 2.4, 1. / 1.055, 0.055 / 1.055, 1. / 12.92, 0.04045 }; cmsToneCurve *srgb = cmsBuildParametricToneCurve(NULL, 4, P); cmsToneCurve *srgbcurve[3] = {srgb,srgb,srgb}; cmsHPROFILE hsRGB = cmsCreateRGBProfile(&D65, &primaries, srgbcurve); cmsHPROFILE hLab = cmsCreateLab4Profile(NULL); cmsHPROFILE hlRGB = cmsCreateRGBProfile(&D65, &primaries, linrgb); cmsHPROFILE hlGray = cmsCreateGrayProfile(cmsD50_xyY(), linear); cmsSetHeaderFlags(hlGray, cmsEmbeddedProfileTrue); cmsSaveProfileToFile(hlGray,"lgray.icc"); cmsSetHeaderFlags(hlRGB, cmsEmbeddedProfileTrue); cmsSaveProfileToFile(hlRGB,"lrgb.icc"); xform_srgb_to_lrgb = cmsCreateTransform(hsRGB, TYPE_RGB_DBL, hlRGB, TYPE_RGB_DBL, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE /* preserve precision */ ); xform_srgb_to_lab = cmsCreateTransform(hsRGB, TYPE_RGB_DBL, hLab, TYPE_Lab_DBL, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE); xform_srgb_to_lgray = cmsCreateTransform(hsRGB, TYPE_RGB_DBL, hlGray, TYPE_GRAY_DBL, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE); cmsCloseProfile(hsRGB); cmsCloseProfile(hlRGB); cmsCloseProfile(hLab); cmsCloseProfile(hlGray); cmsFreeToneCurve(linear); cmsFreeToneCurve(srgb); cmsSetLogErrorHandler(errlog); /* sRGB, RGB, Lab, Gray */ printf("R',G',B',R,G,B,L,a,b,Gray\n"); }
// Reverse a gamma table cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, const cmsToneCurve* InCurve) { cmsToneCurve *out; cmsFloat64Number a = 0, b = 0, y, x1, y1, x2, y2; int i, j; int Ascending; _cmsAssert(InCurve != NULL); // Try to reverse it analytically whatever possible if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 && InCurve -> Segments[0].Type <= 5) { return cmsBuildParametricToneCurve(InCurve ->InterpParams->ContextID, -(InCurve -> Segments[0].Type), InCurve -> Segments[0].Params); } // Nope, reverse the table. out = cmsBuildTabulatedToneCurve16(InCurve ->InterpParams->ContextID, nResultSamples, NULL); if (out == NULL) return NULL; // We want to know if this is an ascending or descending table Ascending = !cmsIsToneCurveDescending(InCurve); // Iterate across Y axis for (i=0; i < nResultSamples; i++) { y = (cmsFloat64Number) i * 65535.0 / (nResultSamples - 1); // Find interval in which y is within. j = GetInterval(y, InCurve->Table16, InCurve->InterpParams); if (j >= 0) { // Get limits of interval x1 = InCurve ->Table16[j]; x2 = InCurve ->Table16[j+1]; y1 = (cmsFloat64Number) (j * 65535.0) / (InCurve ->nEntries - 1); y2 = (cmsFloat64Number) ((j+1) * 65535.0 ) / (InCurve ->nEntries - 1); // If collapsed, then use any if (x1 == x2) { out ->Table16[i] = _cmsQuickSaturateWord(Ascending ? y2 : y1); continue; } else { // Interpolate a = (y2 - y1) / (x2 - x1); b = y2 - a * x2; } } out ->Table16[i] = _cmsQuickSaturateWord(a* y + b); } return out; }
// Build a gamma table based on gamma constant cmsToneCurve* CMSEXPORT cmsBuildGamma(cmsContext ContextID, cmsFloat64Number Gamma) { return cmsBuildParametricToneCurve(ContextID, 1, &Gamma); }
static GimpColorProfile * gimp_color_profile_new_from_color_profile (GimpColorProfile *profile, gboolean linear) { GimpColorProfile *new_profile; cmsHPROFILE target_profile; GimpMatrix3 matrix = { 0, }; cmsCIEXYZ *whitepoint; cmsToneCurve *curve; const gchar *model; gchar *new_model; g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (profile), NULL); if (gimp_color_profile_is_rgb (profile)) { if (! gimp_color_profile_get_rgb_matrix_colorants (profile, &matrix)) return NULL; } else if (! gimp_color_profile_is_gray (profile)) { return NULL; } whitepoint = cmsReadTag (profile->priv->lcms_profile, cmsSigMediaWhitePointTag); target_profile = cmsCreateProfilePlaceholder (0); cmsSetProfileVersion (target_profile, 4.3); cmsSetDeviceClass (target_profile, cmsSigDisplayClass); cmsSetPCS (target_profile, cmsSigXYZData); cmsWriteTag (target_profile, cmsSigMediaWhitePointTag, whitepoint); if (linear) { /* linear light */ curve = cmsBuildGamma (NULL, 1.00); gimp_color_profile_set_tag (target_profile, cmsSigProfileDescriptionTag, "linear TRC variant generated by GIMP"); } else { cmsFloat64Number srgb_parameters[5] = { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 }; /* sRGB curve */ curve = cmsBuildParametricToneCurve (NULL, 4, srgb_parameters); gimp_color_profile_set_tag (target_profile, cmsSigProfileDescriptionTag, "sRGB TRC variant generated by GIMP"); } if (gimp_color_profile_is_rgb (profile)) { cmsCIEXYZ red; cmsCIEXYZ green; cmsCIEXYZ blue; cmsSetColorSpace (target_profile, cmsSigRgbData); red.X = matrix.coeff[0][0]; red.Y = matrix.coeff[0][1]; red.Z = matrix.coeff[0][2]; green.X = matrix.coeff[1][0]; green.Y = matrix.coeff[1][1]; green.Z = matrix.coeff[1][2]; blue.X = matrix.coeff[2][0]; blue.Y = matrix.coeff[2][1]; blue.Z = matrix.coeff[2][2]; cmsWriteTag (target_profile, cmsSigRedColorantTag, &red); cmsWriteTag (target_profile, cmsSigGreenColorantTag, &green); cmsWriteTag (target_profile, cmsSigBlueColorantTag, &blue); cmsWriteTag (target_profile, cmsSigRedTRCTag, curve); cmsWriteTag (target_profile, cmsSigGreenTRCTag, curve); cmsWriteTag (target_profile, cmsSigBlueTRCTag, curve); } else { cmsSetColorSpace (target_profile, cmsSigGrayData); cmsWriteTag (target_profile, cmsSigGrayTRCTag, curve); } cmsFreeToneCurve (curve); model = gimp_color_profile_get_model (profile); if (model && g_str_has_prefix (model, "Generated from '")) { /* don't add multiple "Generated from 'foo'" */ new_model = g_strdup (model); } else { new_model = g_strdup_printf ("Generated from '%s'", gimp_color_profile_get_description (profile)); } gimp_color_profile_set_tag (target_profile, cmsSigDeviceMfgDescTag, "GIMP"); gimp_color_profile_set_tag (target_profile, cmsSigDeviceModelDescTag, new_model); gimp_color_profile_set_tag (target_profile, cmsSigCopyrightTag, "Public Domain"); g_free (new_model); new_profile = gimp_color_profile_new_from_lcms_profile (target_profile, NULL); cmsCloseProfile (target_profile); return new_profile; }