📄 cmsxform.c
字号:
LPVOID in, LPVOID out, unsigned int Size){ register LPBYTE accum; register LPBYTE output; WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS]; register unsigned int i; accum = (LPBYTE) in; output = (LPBYTE) out; for (i=0; i < Size; i++) { accum = p -> FromInput(p, wIn, accum); CopyMemory(wOut, p ->NamedColorList->List[wIn[0]].DeviceColorant, sizeof(WORD) * MAXCHANNELS); output = p -> ToOutput(p, wOut, output); } }// --------------------------------------------------------------------------// Build a LUT based on shape-matrix method.// Some non-conformant gray profiles are using kTCR as L*,// this function converts the curve to XYZ PCS.staticvoid FromLstarToXYZ(LPGAMMATABLE g, LPGAMMATABLE gxyz[3]){ int i; int nPoints = 4096; cmsCIELab Lab; cmsCIEXYZ XYZ; L16PARAMS L16; // Setup interpolation across origin cmsCalcL16Params(g ->nEntries, &L16); // Allocate curves gxyz[0] = cmsAllocGamma(nPoints); gxyz[1] = cmsAllocGamma(nPoints); gxyz[2] = cmsAllocGamma(nPoints); // Transport from Lab to XYZ for (i=0; i < nPoints; i++) { WORD val = _cmsQuantizeVal(i, nPoints); WORD w = cmsLinearInterpLUT16(val, g->GammaTable, &L16); Lab.L = ((double) 100.0 * w ) / 65535.0; Lab.a = Lab.b = 0; cmsLab2XYZ(NULL, &XYZ, &Lab); // Should be same curve gxyz[0] ->GammaTable[i] = (WORD) floor((65535.0 * XYZ.X) / D50X + 0.5); gxyz[1] ->GammaTable[i] = (WORD) floor((65535.0 * XYZ.Y) / D50Y + 0.5); gxyz[2] ->GammaTable[i] = (WORD) floor((65535.0 * XYZ.Z) / D50Z + 0.5); }}// Monochrome versionstaticLPMATSHAPER cmsBuildGrayInputMatrixShaper(cmsHPROFILE hProfile){ cmsCIEXYZ Illuminant; LPGAMMATABLE GrayTRC, Shapes[3]; LPMATSHAPER MatShaper; MAT3 Scale; GrayTRC = cmsReadICCGamma(hProfile, icSigGrayTRCTag); // Y cmsTakeIluminant(&Illuminant, hProfile); if (cmsGetPCS(hProfile) == icSigLabData) { // Fixup for Lab monochrome FromLstarToXYZ(GrayTRC, Shapes); } else { Shapes[0] = cmsDupGamma(GrayTRC); Shapes[1] = cmsDupGamma(GrayTRC); Shapes[2] = cmsDupGamma(GrayTRC); } if (!Shapes[0] || !Shapes[1] || !Shapes[2]) return NULL; cmsFreeGamma(GrayTRC); // R=G=B as precondition VEC3init(&Scale.v[0], Illuminant.X/3, Illuminant.X/3, Illuminant.X/3); VEC3init(&Scale.v[1], Illuminant.Y/3, Illuminant.Y/3, Illuminant.Y/3); VEC3init(&Scale.v[2], Illuminant.Z/3, Illuminant.Z/3, Illuminant.Z/3); MatShaper = cmsAllocMatShaper(&Scale, Shapes, MATSHAPER_INPUT); cmsFreeGammaTriple(Shapes); return MatShaper;}// Monochrome as outputstaticLPMATSHAPER cmsBuildGrayOutputMatrixShaper(cmsHPROFILE hProfile){ cmsCIEXYZ Illuminant; LPGAMMATABLE GrayTRC, Shapes[3]; LPMATSHAPER MatShaper; MAT3 Scale; cmsTakeIluminant(&Illuminant, hProfile); // That is a special case for non-compliant profiles. if (cmsGetPCS(hProfile) == icSigLabData) { LPGAMMATABLE Shapes1[3]; GrayTRC = cmsReadICCGamma(hProfile, icSigGrayTRCTag); FromLstarToXYZ(GrayTRC, Shapes1); // Reversing must be done after curve translation Shapes[0] = cmsReverseGamma(Shapes1[0]->nEntries, Shapes1[0]); Shapes[1] = cmsReverseGamma(Shapes1[1]->nEntries, Shapes1[1]); Shapes[2] = cmsReverseGamma(Shapes1[2]->nEntries, Shapes1[2]); cmsFreeGammaTriple(Shapes1); } else { // Normal case GrayTRC = cmsReadICCGammaReversed(hProfile, icSigGrayTRCTag); // Y Shapes[0] = cmsDupGamma(GrayTRC); Shapes[1] = cmsDupGamma(GrayTRC); Shapes[2] = cmsDupGamma(GrayTRC); } if (!Shapes[0] || !Shapes[1] || !Shapes[2]) return NULL; cmsFreeGamma(GrayTRC); VEC3init(&Scale.v[0], 0, 1.0/Illuminant.Y, 0); VEC3init(&Scale.v[1], 0, 1.0/Illuminant.Y, 0); VEC3init(&Scale.v[2], 0, 1.0/Illuminant.Y, 0); MatShaper = cmsAllocMatShaper(&Scale, Shapes, MATSHAPER_OUTPUT); cmsFreeGammaTriple(Shapes); return MatShaper;}// Input matrix, only in XYZLPMATSHAPER cmsBuildInputMatrixShaper(cmsHPROFILE InputProfile){ MAT3 DoubleMat; LPGAMMATABLE Shapes[3]; LPMATSHAPER InMatSh; // Check if this is a grayscale profile. If so, build // appropiate conversion tables. The tables are the PCS // iluminant, scaled across GrayTRC if (cmsGetColorSpace(InputProfile) == icSigGrayData) { // if (dwFlags) *dwFlags |= cmsFLAGS_NOTPRECALC; return cmsBuildGrayInputMatrixShaper(InputProfile); } if (!cmsReadICCMatrixRGB2XYZ(&DoubleMat, InputProfile)) return NULL; Shapes[0] = cmsReadICCGamma(InputProfile, icSigRedTRCTag); Shapes[1] = cmsReadICCGamma(InputProfile, icSigGreenTRCTag); Shapes[2] = cmsReadICCGamma(InputProfile, icSigBlueTRCTag); if (!Shapes[0] || !Shapes[1] || !Shapes[2]) return NULL; InMatSh = cmsAllocMatShaper(&DoubleMat, Shapes, MATSHAPER_INPUT); cmsFreeGammaTriple(Shapes); return InMatSh;}// Output style matrix-shaperLPMATSHAPER cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile){ MAT3 DoubleMat, DoubleInv; LPGAMMATABLE InverseShapes[3]; LPMATSHAPER OutMatSh; if (cmsGetColorSpace(OutputProfile) == icSigGrayData) { return cmsBuildGrayOutputMatrixShaper(OutputProfile); } if (!cmsReadICCMatrixRGB2XYZ(&DoubleMat, OutputProfile)) return NULL; if (MAT3inverse(&DoubleMat, &DoubleInv) < 0) return NULL; InverseShapes[0] = cmsReadICCGammaReversed(OutputProfile, icSigRedTRCTag); InverseShapes[1] = cmsReadICCGammaReversed(OutputProfile, icSigGreenTRCTag); InverseShapes[2] = cmsReadICCGammaReversed(OutputProfile, icSigBlueTRCTag); OutMatSh = cmsAllocMatShaper(&DoubleInv, InverseShapes, MATSHAPER_OUTPUT); cmsFreeGammaTriple(InverseShapes); return OutMatSh;}// This function builds a transform matrix chaining parametersstaticBOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p){ MAT3 From, To, ToInv, Transfer; LPGAMMATABLE In[3], InverseOut[3]; if (!cmsReadICCMatrixRGB2XYZ(&From, p -> InputProfile)) return FALSE; if (!cmsReadICCMatrixRGB2XYZ(&To, p -> OutputProfile)) return FALSE; // invert dest if (MAT3inverse(&To, &ToInv) < 0) return FALSE; // Multiply MAT3per(&Transfer, &ToInv, &From); // Read gamma curves In[0] = cmsReadICCGamma(p -> InputProfile, icSigRedTRCTag); In[1] = cmsReadICCGamma(p -> InputProfile, icSigGreenTRCTag); In[2] = cmsReadICCGamma(p -> InputProfile, icSigBlueTRCTag); if (!In[0] || !In[1] || !In[2]) return FALSE; InverseOut[0] = cmsReadICCGammaReversed(p -> OutputProfile, icSigRedTRCTag); InverseOut[1] = cmsReadICCGammaReversed(p -> OutputProfile, icSigGreenTRCTag); InverseOut[2] = cmsReadICCGammaReversed(p -> OutputProfile, icSigBlueTRCTag); p -> SmeltMatShaper = cmsAllocMatShaper2(&Transfer, In, InverseOut, MATSHAPER_ALLSMELTED); cmsFreeGammaTriple(In); cmsFreeGammaTriple(InverseOut); return (p -> SmeltMatShaper != NULL);}// Conversion between PCS ------------------------------------------// Identifies intent archieved by LUTstaticint GetPhase(cmsHPROFILE hProfile){ switch (cmsGetPCS(hProfile)) { case icSigXYZData: return XYZRel; case icSigLabData: return LabRel; default: cmsSignalError(LCMS_ERRC_ABORTED, "Invalid PCS"); } return XYZRel;}staticvoid TakeConversionRoutines(_LPcmsTRANSFORM p, int DoBPC){ cmsCIEXYZ BlackPointIn, WhitePointIn, IlluminantIn; cmsCIEXYZ BlackPointOut, WhitePointOut, IlluminantOut; cmsCIEXYZ BlackPointProof, WhitePointProof, IlluminantProof; MAT3 ChromaticAdaptationMatrixIn, ChromaticAdaptationMatrixOut; MAT3 ChromaticAdaptationMatrixProof; cmsTakeIluminant(&IlluminantIn, p -> InputProfile); cmsTakeMediaWhitePoint(&WhitePointIn, p -> InputProfile); cmsTakeMediaBlackPoint(&BlackPointIn, p -> InputProfile); cmsReadChromaticAdaptationMatrix(&ChromaticAdaptationMatrixIn, p -> InputProfile); cmsTakeIluminant(&IlluminantOut, p -> OutputProfile); cmsTakeMediaWhitePoint(&WhitePointOut, p -> OutputProfile); cmsTakeMediaBlackPoint(&BlackPointOut, p -> OutputProfile); cmsReadChromaticAdaptationMatrix(&ChromaticAdaptationMatrixOut, p -> OutputProfile); if (p -> Preview == NULL && p ->Gamut == NULL) // Non-proofing { if (p ->Intent == INTENT_PERCEPTUAL || p ->Intent == INTENT_SATURATION) { // For v4 profiles, Perceptual PCS has a reference black point // which v2 profiles should scale to. if ((cmsGetProfileICCversion(p ->InputProfile) >= 0x4000000) || (cmsGetProfileICCversion(p ->OutputProfile) >= 0x4000000)) { DoBPC = TRUE; } } // Black point compensation does not apply to absolute intent if (p ->Intent == INTENT_ABSOLUTE_COLORIMETRIC) DoBPC = FALSE; // Black point compensation does not apply to devicelink profiles if (cmsGetDeviceClass(p ->InputProfile) == icSigLinkClass) DoBPC = FALSE; if (cmsGetDeviceClass(p ->OutputProfile) == icSigLinkClass) DoBPC = FALSE; if (DoBPC) { // Detect Black points cmsDetectBlackPoint(&BlackPointIn, p->InputProfile, p->Intent, 0); cmsDetectBlackPoint(&BlackPointOut, p->OutputProfile, p->Intent, 0); // If equal black points, then do nothing. This often applies to BP=0 if (BlackPointIn.X == BlackPointOut.X && BlackPointIn.Y == BlackPointOut.Y && BlackPointIn.Z == BlackPointOut.Z) DoBPC = FALSE; } cmsChooseCnvrt(p -> Intent == INTENT_ABSOLUTE_COLORIMETRIC, p -> Phase1, &BlackPointIn, &WhitePointIn, &IlluminantIn, &ChromaticAdaptationMatrixIn, p -> Phase3, &BlackPointOut, &WhitePointOut, &IlluminantOut, &ChromaticAdaptationMatrixOut, DoBPC, p ->AdaptationState, &p->Stage1, &p->m1, &p->of1); } else // Proofing { cmsTakeIluminant(&IlluminantProof, p -> PreviewProfile); cmsTakeMediaWhitePoint(&WhitePointProof, p -> PreviewProfile); cmsTakeMediaBlackPoint(&BlackPointProof, p -> PreviewProfile); cmsReadChromaticAdaptationMatrix(&ChromaticAdaptationMatrixProof, p -> PreviewProfile); if (DoBPC) { cmsDetectBlackPoint(&BlackPointProof, p->PreviewProfile, p->Intent, 0); cmsDetectBlackPoint(&BlackPointIn, p->InputProfile, p->Intent, 0); cmsDetectBlackPoint(&BlackPointOut, p->OutputProfile, p->Intent, 0); // Reality check if (BlackPointIn.X == BlackPointProof.X && BlackPointIn.Y == BlackPointProof.Y && BlackPointIn.Z == BlackPointProof.Z) DoBPC = FALSE; } cmsChooseCnvrt(p -> Intent == INTENT_ABSOLUTE_COLORIMETRIC, p -> Phase1, &BlackPointIn, &WhitePointIn, &IlluminantIn, &ChromaticAdaptationMatrixIn, p -> Phase2, &BlackPointProof, &WhitePointProof, &IlluminantProof, &ChromaticAdaptationMatrixProof, DoBPC, p ->AdaptationState, &p->Stage1, &p->m1, &p->of1); cmsChooseCnvrt(p -> ProofIntent == INTENT_ABSOLUTE_COLORIMETRIC, p -> Phase2, &BlackPointProof, &WhitePointProof, &IlluminantProof, &ChromaticAdaptationMatrixProof, p -> Phase3, &BlackPointOut, &WhitePointOut, &IlluminantOut, &ChromaticAdaptationMatrixOut, 0, 0.0, &p->Stage2, &p->m2, &p->of2); }}// Check colorspacestaticBOOL IsProperColorSpace(cmsHPROFILE hProfile, DWORD dwFormat, BOOL lUsePCS){ int Space = T_COLORSPACE(dwFormat); if (Space == PT_ANY) return TRUE; if (lUsePCS) return (Space == _cmsLCMScolorSpace(cmsGetPCS(hProfile)));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -