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"); }
bool ProfileUtils::createIccProfile(bool isLaptop, const Edid &edid, const QString &filename) { cmsCIExyYTRIPLE chroma; cmsCIExyY white_point; cmsHPROFILE lcms_profile = NULL; cmsToneCurve *transfer_curve[3] = { NULL, NULL, NULL }; bool ret = false; cmsHANDLE dict = NULL; /* ensure the per-user directory exists */ // Create dir path if not available // check if the file doesn't already exist QFileInfo fileInfo(filename); if (fileInfo.exists()) { qCWarning(COLORD) << "EDID ICC Profile already exists" << filename; if (*transfer_curve != NULL) cmsFreeToneCurve(*transfer_curve); return false; } // copy color data from our structures // Red chroma.Red.x = edid.red().x(); chroma.Red.y = edid.red().y(); // Green chroma.Green.x = edid.green().x(); chroma.Green.y = edid.green().y(); // Blue chroma.Blue.x = edid.blue().x(); chroma.Blue.y = edid.blue().y(); // White white_point.x = edid.white().x(); white_point.y = edid.white().y(); white_point.Y = 1.0; // estimate the transfer function for the gamma transfer_curve[0] = transfer_curve[1] = transfer_curve[2] = cmsBuildGamma(NULL, edid.gamma()); // create our generated profile lcms_profile = cmsCreateRGBProfile(&white_point, &chroma, transfer_curve); if (lcms_profile == NULL) { qCWarning(COLORD) << "Failed to create ICC profile on cmsCreateRGBProfile"; if (*transfer_curve != NULL) cmsFreeToneCurve(*transfer_curve); return false; } cmsSetColorSpace(lcms_profile, cmsSigRgbData); cmsSetPCS(lcms_profile, cmsSigXYZData); cmsSetHeaderRenderingIntent(lcms_profile, INTENT_RELATIVE_COLORIMETRIC); cmsSetDeviceClass(lcms_profile, cmsSigDisplayClass); // copyright ret = cmsWriteTagTextAscii(lcms_profile, cmsSigCopyrightTag, "No copyright"); if (!ret) { qCWarning(COLORD) << "Failed to write copyright"; if (*transfer_curve != NULL) cmsFreeToneCurve(*transfer_curve); return false; } // set model QString model; if (isLaptop) { model = DmiUtils::deviceModel(); } else { model = edid.name(); } if (model.isEmpty()) { model = QStringLiteral("Unknown monitor"); } ret = cmsWriteTagTextAscii(lcms_profile, cmsSigDeviceModelDescTag, model); if (!ret) { qCWarning(COLORD) << "Failed to write model"; if (*transfer_curve != NULL) { cmsFreeToneCurve(*transfer_curve); } return false; } // write title ret = cmsWriteTagTextAscii(lcms_profile, cmsSigProfileDescriptionTag, model); if (!ret) { qCWarning(COLORD) << "Failed to write description"; if (*transfer_curve != NULL) cmsFreeToneCurve(*transfer_curve); return false; } // get manufacturer QString vendor; if (isLaptop) { vendor = DmiUtils::deviceVendor(); } else { vendor = edid.vendor(); } if (vendor.isEmpty()) { vendor = QStringLiteral("Unknown vendor"); } ret = cmsWriteTagTextAscii(lcms_profile, cmsSigDeviceMfgDescTag, vendor); if (!ret) { qCWarning(COLORD) << "Failed to write manufacturer"; if (*transfer_curve != NULL) cmsFreeToneCurve(*transfer_curve); return false; } // just create a new dict dict = cmsDictAlloc(NULL); // set the framework creator metadata cmsDictAddEntryAscii(dict, CD_PROFILE_METADATA_CMF_PRODUCT, PACKAGE_NAME); cmsDictAddEntryAscii(dict, CD_PROFILE_METADATA_CMF_BINARY, PACKAGE_NAME); cmsDictAddEntryAscii(dict, CD_PROFILE_METADATA_CMF_VERSION, PACKAGE_VERSION); /* set the data source so we don't ever prompt the user to * recalibrate (as the EDID data won't have changed) */ cmsDictAddEntryAscii(dict, CD_PROFILE_METADATA_DATA_SOURCE, CD_PROFILE_METADATA_DATA_SOURCE_EDID); // set 'ICC meta Tag for Monitor Profiles' data cmsDictAddEntryAscii(dict, "EDID_md5", edid.hash()); if (!model.isEmpty()) cmsDictAddEntryAscii(dict, "EDID_model", model); if (!edid.serial().isEmpty()) { cmsDictAddEntryAscii(dict, "EDID_serial", edid.serial()); } if (!edid.pnpId().isEmpty()) { cmsDictAddEntryAscii(dict, "EDID_mnft", edid.pnpId()); } if (!vendor.isEmpty()) { cmsDictAddEntryAscii(dict, "EDID_manufacturer", vendor); } /* write new tag */ ret = cmsWriteTag(lcms_profile, cmsSigMetaTag, dict); if (!ret) { qCWarning(COLORD) << "Failed to write profile metadata"; if (*transfer_curve != NULL) cmsFreeToneCurve(*transfer_curve); return false; } /* write profile id */ ret = cmsMD5computeID(lcms_profile); if (!ret) { qCWarning(COLORD) << "Failed to write profile id"; if (dict != NULL) cmsDictFree (dict); if (*transfer_curve != NULL) cmsFreeToneCurve(*transfer_curve); return false; } /* save, TODO: get error */ ret = cmsSaveProfileToFile(lcms_profile, filename.toUtf8()); if (dict != NULL) { cmsDictFree (dict); } if (*transfer_curve != NULL) { cmsFreeToneCurve (*transfer_curve); } return ret; }
int main(int argc, char *argv[]) { int i, nargs, rc; cmsHPROFILE Profiles[257]; cmsHPROFILE hProfile; cmsUInt32Number dwFlags; cmsHTRANSFORM hTransform = NULL; // Here we are fprintf(stderr, "little cms ICC device link generator - v2.2 [LittleCMS %2.2f]\n", LCMS_VERSION / 1000.0); fflush(stderr); // Initialize InitUtils("linkicc"); rc = 0; // Get the options HandleSwitches(argc, argv); // How many profiles to link? nargs = (argc - xoptind); if (nargs < 1) return Help(0); if (nargs > 255) { FatalError("Holy profile! what are you trying to do with so many profiles!?"); goto Cleanup; } // Open all profiles memset(Profiles, 0, sizeof(Profiles)); for (i=0; i < nargs; i++) { Profiles[i] = OpenStockProfile(0, argv[i + xoptind]); if (Profiles[i] == NULL) goto Cleanup; if (Verbose >= 1) { PrintProfileInformation(Profiles[i]); } } // Ink limiting if (InkLimit != 400.0) { cmsColorSpaceSignature EndingColorSpace = cmsGetColorSpace(Profiles[nargs-1]); Profiles[nargs++] = cmsCreateInkLimitingDeviceLink(EndingColorSpace, InkLimit); } // Set the flags dwFlags = cmsFLAGS_KEEP_SEQUENCE; switch (PrecalcMode) { case 0: dwFlags |= cmsFLAGS_LOWRESPRECALC; break; case 2: dwFlags |= cmsFLAGS_HIGHRESPRECALC; break; case 1: if (NumOfGridPoints > 0) dwFlags |= cmsFLAGS_GRIDPOINTS(NumOfGridPoints); break; default: { FatalError("Unknown precalculation mode '%d'", PrecalcMode); goto Cleanup; } } if (BlackPointCompensation) dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION; if (TagResult) dwFlags |= cmsFLAGS_GUESSDEVICECLASS; if (KeepLinearization) dwFlags |= cmsFLAGS_CLUT_PRE_LINEARIZATION|cmsFLAGS_CLUT_POST_LINEARIZATION; if (lUse8bits) dwFlags |= cmsFLAGS_8BITS_DEVICELINK; cmsSetAdaptationState(ObserverAdaptationState); // Create the color transform. Specify 0 for the format is safe as the transform // is intended to be used only for the devicelink. hTransform = cmsCreateMultiprofileTransform(Profiles, nargs, 0, 0, Intent, dwFlags|cmsFLAGS_NOOPTIMIZE); if (hTransform == NULL) { FatalError("Transform creation failed"); goto Cleanup; } hProfile = cmsTransform2DeviceLink(hTransform, Version, dwFlags); if (hProfile == NULL) { FatalError("Devicelink creation failed"); goto Cleanup; } SetTextTags(hProfile); cmsSetHeaderRenderingIntent(hProfile, Intent); if (cmsSaveProfileToFile(hProfile, cOutProf)) { if (Verbose > 0) fprintf(stderr, "Ok"); } else FatalError("Error saving file!"); cmsCloseProfile(hProfile); Cleanup: if (hTransform != NULL) cmsDeleteTransform(hTransform); for (i=0; i < nargs; i++) { if (Profiles[i] != NULL) cmsCloseProfile(Profiles[i]); } return rc; }