📄 cmsvirt.c
字号:
int InkLimitingSampler(register WORD In[], register WORD Out[], register LPVOID Cargo){ double InkLimit = *(double *) Cargo; double SumCMY, SumCMYK, Ratio; InkLimit = (InkLimit * 655.35); SumCMY = In[0] + In[1] + In[2]; SumCMYK = SumCMY + In[3]; if (SumCMYK > InkLimit) { Ratio = 1 - ((SumCMYK - InkLimit) / SumCMY); if (Ratio < 0) Ratio = 0; } else Ratio = 1; Out[0] = (WORD) floor(In[0] * Ratio + 0.5); // C Out[1] = (WORD) floor(In[1] * Ratio + 0.5); // M Out[2] = (WORD) floor(In[2] * Ratio + 0.5); // Y Out[3] = In[3]; // K (untouched) return TRUE;}// This is a devicelink operating in CMYK for ink-limitingcmsHPROFILE LCMSEXPORT cmsCreateInkLimitingDeviceLink(icColorSpaceSignature ColorSpace, double Limit){ cmsHPROFILE hICC; LPLUT Lut; if (ColorSpace != icSigCmykData) { cmsSignalError(LCMS_ERRC_ABORTED, "InkLimiting: Only CMYK currently supported"); return NULL; } if (Limit < 0.0 || Limit > 400) { cmsSignalError(LCMS_ERRC_WARNING, "InkLimiting: Limit should be between 0..400"); if (Limit < 0) Limit = 0; if (Limit > 400) Limit = 400; } hICC = _cmsCreateProfilePlaceholder(); if (!hICC) // can't allocate return NULL; cmsSetDeviceClass(hICC, icSigLinkClass); cmsSetColorSpace(hICC, ColorSpace); cmsSetPCS(hICC, ColorSpace); cmsSetRenderingIntent(hICC, INTENT_PERCEPTUAL); // Creates a LUT with 3D grid only Lut = cmsAllocLUT(); cmsAlloc3DGrid(Lut, 17, _cmsChannelsOf(ColorSpace), _cmsChannelsOf(ColorSpace)); if (!cmsSample3DGrid(Lut, InkLimitingSampler, (LPVOID) &Limit, 0)) { // Shouldn't reach here cmsFreeLUT(Lut); cmsCloseProfile(hICC); return NULL; } // Create tags cmsAddTag(hICC, icSigDeviceMfgDescTag, (LPVOID) "(lcms internal)"); cmsAddTag(hICC, icSigProfileDescriptionTag, (LPVOID) "lcms ink limiting device link"); cmsAddTag(hICC, icSigDeviceModelDescTag, (LPVOID) "ink limiting built-in"); cmsAddTag(hICC, icSigMediaWhitePointTag, (LPVOID) cmsD50_XYZ()); cmsAddTag(hICC, icSigAToB0Tag, (LPVOID) Lut); // LUT is already on virtual profile cmsFreeLUT(Lut); // Ok, done return hICC;}staticLPLUT Create3x3EmptyLUT(void){ LPLUT AToB0 = cmsAllocLUT(); AToB0 -> InputChan = AToB0 -> OutputChan = 3; return AToB0;}// Creates a fake Lab identity.cmsHPROFILE LCMSEXPORT cmsCreateLabProfile(LPcmsCIExyY WhitePoint){ cmsHPROFILE hProfile; LPLUT Lut; hProfile = cmsCreateRGBProfile(WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL); cmsSetDeviceClass(hProfile, icSigAbstractClass); cmsSetColorSpace(hProfile, icSigLabData); cmsSetPCS(hProfile, icSigLabData); cmsAddTag(hProfile, icSigDeviceMfgDescTag, (LPVOID) "(lcms internal)"); cmsAddTag(hProfile, icSigProfileDescriptionTag, (LPVOID) "lcms Lab identity"); cmsAddTag(hProfile, icSigDeviceModelDescTag, (LPVOID) "Lab built-in"); // An empty LUTs is all we need Lut = Create3x3EmptyLUT(); if (Lut == NULL) return NULL; cmsAddTag(hProfile, icSigAToB0Tag, (LPVOID) Lut); cmsAddTag(hProfile, icSigBToA0Tag, (LPVOID) Lut); cmsFreeLUT(Lut); return hProfile;}// Creates a fake Lab identity.cmsHPROFILE LCMSEXPORT cmsCreateLab4Profile(LPcmsCIExyY WhitePoint){ cmsHPROFILE hProfile; LPLUT Lut; hProfile = cmsCreateRGBProfile(WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL); cmsSetProfileICCversion(hProfile, 0x4000000); cmsSetDeviceClass(hProfile, icSigAbstractClass); cmsSetColorSpace(hProfile, icSigLabData); cmsSetPCS(hProfile, icSigLabData); cmsAddTag(hProfile, icSigDeviceMfgDescTag, (LPVOID) "(lcms internal)"); cmsAddTag(hProfile, icSigProfileDescriptionTag, (LPVOID) "lcms Lab identity v4"); cmsAddTag(hProfile, icSigDeviceModelDescTag, (LPVOID) "Lab v4 built-in"); // An empty LUTs is all we need Lut = Create3x3EmptyLUT(); if (Lut == NULL) return NULL; Lut -> wFlags |= LUT_V4_INPUT_EMULATE_V2; cmsAddTag(hProfile, icSigAToB0Tag, (LPVOID) Lut); Lut -> wFlags |= LUT_V4_OUTPUT_EMULATE_V2; cmsAddTag(hProfile, icSigBToA0Tag, (LPVOID) Lut); cmsFreeLUT(Lut); return hProfile;}// Creates a fake XYZ identitycmsHPROFILE LCMSEXPORT cmsCreateXYZProfile(void){ cmsHPROFILE hProfile; LPLUT Lut; hProfile = cmsCreateRGBProfile(cmsD50_xyY(), NULL, NULL); cmsSetDeviceClass(hProfile, icSigAbstractClass); cmsSetColorSpace(hProfile, icSigXYZData); cmsSetPCS(hProfile, icSigXYZData); cmsAddTag(hProfile, icSigDeviceMfgDescTag, (LPVOID) "(lcms internal)"); cmsAddTag(hProfile, icSigProfileDescriptionTag, (LPVOID) "lcms XYZ identity"); cmsAddTag(hProfile, icSigDeviceModelDescTag, (LPVOID) "XYZ built-in"); // An empty LUTs is all we need Lut = Create3x3EmptyLUT(); if (Lut == NULL) return NULL; cmsAddTag(hProfile, icSigAToB0Tag, (LPVOID) Lut); cmsAddTag(hProfile, icSigBToA0Tag, (LPVOID) Lut); cmsAddTag(hProfile, icSigPreview0Tag, (LPVOID) Lut); cmsFreeLUT(Lut); return hProfile;}/*If R抯RGB,G抯RGB, B抯RGB < 0.04045 R = R抯RGB / 12.92 G = G抯RGB / 12.92 B = B抯RGB / 12.92 else if R抯RGB,G抯RGB, B抯RGB >= 0.04045 R = ((R抯RGB + 0.055) / 1.055)^2.4 G = ((G抯RGB + 0.055) / 1.055)^2.4 B = ((B抯RGB + 0.055) / 1.055)^2.4 */staticLPGAMMATABLE Build_sRGBGamma(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 cmsBuildParametricGamma(1024, 4, Parameters);}cmsHPROFILE LCMSEXPORT cmsCreate_sRGBProfile(void){ cmsCIExyY D65; cmsCIExyYTRIPLE Rec709Primaries = { {0.6400, 0.3300, 1.0}, {0.3000, 0.6000, 1.0}, {0.1500, 0.0600, 1.0} }; LPGAMMATABLE Gamma22[3]; cmsHPROFILE hsRGB; cmsWhitePointFromTemp(6504, &D65); Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(); hsRGB = cmsCreateRGBProfile(&D65, &Rec709Primaries, Gamma22); cmsFreeGamma(Gamma22[0]); cmsAddTag(hsRGB, icSigDeviceMfgDescTag, (LPVOID) "(lcms internal)"); cmsAddTag(hsRGB, icSigDeviceModelDescTag, (LPVOID) "sRGB built-in"); cmsAddTag(hsRGB, icSigProfileDescriptionTag, (LPVOID) "sRGB built-in"); return hsRGB;}typedef struct { double Brightness; double Contrast; double Hue; double Saturation; cmsCIEXYZ WPsrc, WPdest;} BCHSWADJUSTS, *LPBCHSWADJUSTS;staticint bchswSampler(register WORD In[], register WORD Out[], register LPVOID Cargo){ cmsCIELab LabIn, LabOut; cmsCIELCh LChIn, LChOut; cmsCIEXYZ XYZ; LPBCHSWADJUSTS bchsw = (LPBCHSWADJUSTS) Cargo; cmsLabEncoded2Float(&LabIn, In); cmsLab2LCh(&LChIn, &LabIn); // Do some adjusts on LCh LChOut.L = LChIn.L * bchsw ->Contrast + bchsw ->Brightness; LChOut.C = LChIn.C + bchsw -> Saturation; LChOut.h = LChIn.h + bchsw -> Hue; cmsLCh2Lab(&LabOut, &LChOut); // Move white point in Lab cmsLab2XYZ(&bchsw ->WPsrc, &XYZ, &LabOut); cmsXYZ2Lab(&bchsw ->WPdest, &LabOut, &XYZ); // Back to encoded cmsFloat2LabEncoded(Out, &LabOut); return TRUE;}// Creates an abstract profile operating in Lab space for Brightness,// contrast, Saturation and white point displacementcmsHPROFILE LCMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints, double Bright, double Contrast, double Hue, double Saturation, int TempSrc, int TempDest){ cmsHPROFILE hICC; LPLUT Lut; BCHSWADJUSTS bchsw; cmsCIExyY WhitePnt; bchsw.Brightness = Bright; bchsw.Contrast = Contrast; bchsw.Hue = Hue; bchsw.Saturation = Saturation; cmsWhitePointFromTemp(TempSrc, &WhitePnt); cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt); cmsWhitePointFromTemp(TempDest, &WhitePnt); cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt); hICC = _cmsCreateProfilePlaceholder(); if (!hICC) // can't allocate return NULL; cmsSetDeviceClass(hICC, icSigAbstractClass); cmsSetColorSpace(hICC, icSigLabData); cmsSetPCS(hICC, icSigLabData); cmsSetRenderingIntent(hICC, INTENT_PERCEPTUAL); // Creates a LUT with 3D grid only Lut = cmsAllocLUT(); cmsAlloc3DGrid(Lut, nLUTPoints, 3, 3); if (!cmsSample3DGrid(Lut, bchswSampler, (LPVOID) &bchsw, 0)) { // Shouldn't reach here cmsFreeLUT(Lut); cmsCloseProfile(hICC); return NULL; } // Create tags cmsAddTag(hICC, icSigDeviceMfgDescTag, (LPVOID) "(lcms internal)"); cmsAddTag(hICC, icSigProfileDescriptionTag, (LPVOID) "lcms BCHSW abstract profile"); cmsAddTag(hICC, icSigDeviceModelDescTag, (LPVOID) "BCHSW built-in"); cmsAddTag(hICC, icSigMediaWhitePointTag, (LPVOID) cmsD50_XYZ()); cmsAddTag(hICC, icSigAToB0Tag, (LPVOID) Lut); // LUT is already on virtual profile cmsFreeLUT(Lut); // Ok, done return hICC;}// Creates a fake NULL profile. This profile return 1 channel as always 0. // Is useful only for gamut checking trickscmsHPROFILE LCMSEXPORT cmsCreateNULLProfile(void){ cmsHPROFILE hProfile; LPLUT Lut; LPGAMMATABLE EmptyTab; hProfile = _cmsCreateProfilePlaceholder(); if (!hProfile) // can't allocate return NULL; cmsSetDeviceClass(hProfile, icSigOutputClass); cmsSetColorSpace(hProfile, icSigGrayData); cmsSetPCS(hProfile, icSigLabData); // An empty LUTs is all we need Lut = cmsAllocLUT(); if (Lut == NULL) return NULL; Lut -> InputChan = 3; Lut -> OutputChan = 1; EmptyTab = cmsAllocGamma(2); EmptyTab ->GammaTable[0] = 0; EmptyTab ->GammaTable[1] = 0; cmsAllocLinearTable(Lut, &EmptyTab, 2); cmsAddTag(hProfile, icSigBToA0Tag, (LPVOID) Lut); cmsFreeLUT(Lut); cmsFreeGamma(EmptyTab); return hProfile;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -