📄 cmsgmt.c
字号:
INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOTPRECALC); // Restores error handler previous state cmsErrorAction(nErrState); // All ok? if (Chain.hForward && Chain.hReverse) { // Go on, try to compute gamut LUT from PCS. // This consist on a single channel containing // dE when doing a transform back and forth on // the colorimetric intent. Gamut = cmsAllocLUT(); Gamut = cmsAlloc3DGrid(Gamut, nGridpoints, nChannels, 1); // If no input, then this is a gamut tag operated by Lab, // so include pertinent prelinearization if (hInput == NULL) { CreateLabPrelinearization(Trans); cmsAllocLinearTable(Gamut, Trans, 1); cmsFreeGammaTriple(Trans); } cmsSample3DGrid(Gamut, GamutSampler, (LPVOID) &Chain, Gamut ->wFlags); } else Gamut = NULL; // Didn't work... // Free all needed stuff. if (Chain.hInput) cmsDeleteTransform(Chain.hInput); if (Chain.hForward) cmsDeleteTransform(Chain.hForward); if (Chain.hReverse) cmsDeleteTransform(Chain.hReverse); cmsCloseProfile(hLab); // And return computed hull return Gamut;}// WrapperLPLUT _cmsComputeGamutLUT(cmsHPROFILE hProfile, int Intent){ return ComputeGamutWithInput(NULL, hProfile, Intent);}// This routine does compute the gamut check CLUT. This CLUT goes from whatever // input space to the 0 or != 0 gamut check.LPLUT _cmsPrecalculateGamutCheck(cmsHTRANSFORM h){ _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) h; return ComputeGamutWithInput(p->InputProfile, p ->PreviewProfile, p->Intent);}// SoftProofing. Convert from Lab to device, then back to Lab, // any gamut remapping is appliedstaticint SoftProofSampler(register WORD In[], register WORD Out[], register LPVOID Cargo){ LPGAMUTCHAIN t = (LPGAMUTCHAIN) Cargo; WORD Colorant[MAXCHANNELS]; // From pcs to colorant cmsDoTransform(t -> hForward, In, Colorant, 1); // Now, do the inverse, from colorant to pcs. cmsDoTransform(t -> hReverse, Colorant, Out, 1); return TRUE;}// Does return Softproofing LUT on desired intentLPLUT _cmsComputeSoftProofLUT(cmsHPROFILE hProfile, int nIntent){ cmsHPROFILE hLab; LPLUT SoftProof; DWORD dwFormat; GAMUTCHAIN Chain; int nErrState; LPGAMMATABLE Trans[3]; // LUTs are never abs. colorimetric, is the transform who // is responsible of generating white point displacement if (nIntent == INTENT_ABSOLUTE_COLORIMETRIC) nIntent = INTENT_RELATIVE_COLORIMETRIC; ZeroMemory(&Chain, sizeof(GAMUTCHAIN)); hLab = cmsCreateLabProfile(NULL); // ONLY 4 channels dwFormat = (CHANNELS_SH(4)|BYTES_SH(2)); // Safeguard against early abortion nErrState = cmsErrorAction(LCMS_ERROR_IGNORE); // Does create the first step Chain.hForward = cmsCreateTransform(hLab, TYPE_Lab_16, hProfile, dwFormat, nIntent, cmsFLAGS_NOTPRECALC); // Does create the last step Chain.hReverse = cmsCreateTransform(hProfile, dwFormat, hLab, TYPE_Lab_16, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOTPRECALC); // Restores error handler previous state cmsErrorAction(nErrState); // All ok? if (Chain.hForward && Chain.hReverse) { // This is Lab -> Lab, so 33 point should hold anything SoftProof = cmsAllocLUT(); SoftProof = cmsAlloc3DGrid(SoftProof, 33, 3, 3); CreateLabPrelinearization(Trans); cmsAllocLinearTable(SoftProof, Trans, 1); cmsFreeGammaTriple(Trans); cmsSample3DGrid(SoftProof, SoftProofSampler, (LPVOID) &Chain, SoftProof->wFlags); } else SoftProof = NULL; // Didn't work... // Free all needed stuff. if (Chain.hForward) cmsDeleteTransform(Chain.hForward); if (Chain.hReverse) cmsDeleteTransform(Chain.hReverse); cmsCloseProfile(hLab); return SoftProof;}#ifdef DEBUGstaticvoid ASAVE(LPGAMMATABLE p, const char* dump){ FILE* f; int i; f = fopen(dump, "wt"); if (!f) return; if (p) { for (i=0; i < p -> nEntries; i++) fprintf(f, "%g\n", (double) p -> GammaTable[i]); } fclose(f);}#endifstaticint MostlyLinear(WORD Table[], int nEntries){ register int i; int diff; for (i=5; i < nEntries; i++) { diff = abs((int) Table[i] - (int) _cmsQuantizeVal(i, nEntries)); if (diff > 0x0300) return 0; } return 1;}staticvoid SlopeLimiting(WORD Table[], int nEntries){ int At = (int) floor((double) nEntries * 0.02 + 0.5); // Cutoff at 2% double Val, Slope; int i; Val = Table[At]; Slope = Val / At; for (i=0; i < At; i++) Table[i] = (WORD) floor(i * Slope + 0.5);}// Check for monotonicity.staticBOOL IsMonotonic(LPGAMMATABLE t){ int n = t -> nEntries; int i, last; last = t ->GammaTable[n-1]; for (i = n-2; i >= 0; --i) { if (t ->GammaTable[i] > last) return FALSE; else last = t ->GammaTable[i]; } return TRUE;}// Check for endpointsstaticBOOL HasProperEndpoints(LPGAMMATABLE t){ if (t ->GammaTable[0] != 0) return FALSE; if (t ->GammaTable[t ->nEntries-1] != 0xFFFF) return FALSE; return TRUE;}#define PRELINEARIZATION_POINTS 4096// Fixes the gamma balancing of transform. Thanks to Mike Chaney// for pointing this subtle bug.void _cmsComputePrelinearizationTablesFromXFORM(cmsHTRANSFORM h[], int nTransforms, LPLUT Grid){ LPGAMMATABLE Trans[MAXCHANNELS]; unsigned int t, i, v; int j; WORD In[MAXCHANNELS], Out[MAXCHANNELS]; BOOL lIsSuitable; _LPcmsTRANSFORM InputXForm = (_LPcmsTRANSFORM) h[0]; _LPcmsTRANSFORM OutputXForm = (_LPcmsTRANSFORM) h[nTransforms-1]; // First space is *Lab, use our specialized curves for v2 Lab if (InputXForm ->EntryColorSpace == icSigLabData && OutputXForm->ExitColorSpace != icSigLabData) { CreateLabPrelinearization(Trans); cmsAllocLinearTable(Grid, Trans, 1); cmsFreeGammaTriple(Trans); return; } // Do nothing on all but RGB to RGB transforms if ((InputXForm ->EntryColorSpace != icSigRgbData) || (OutputXForm->ExitColorSpace != icSigRgbData)) return; for (t = 0; t < Grid -> InputChan; t++) Trans[t] = cmsAllocGamma(PRELINEARIZATION_POINTS); for (i=0; i < PRELINEARIZATION_POINTS; i++) { v = _cmsQuantizeVal(i, PRELINEARIZATION_POINTS); for (t=0; t < Grid -> InputChan; t++) In[t] = (WORD) v; cmsDoTransform(h[0], In, Out, 1); for (j=1; j < nTransforms; j++) cmsDoTransform(h[j], Out, Out, 1); for (t=0; t < Grid -> InputChan; t++) Trans[t] ->GammaTable[i] = Out[t]; } // Check transfer curves lIsSuitable = TRUE; for (t=0; (lIsSuitable && (t < Grid->InputChan)); t++) { // Exclude if already linear if (MostlyLinear(Trans[t]->GammaTable, PRELINEARIZATION_POINTS)) lIsSuitable = FALSE; // Exclude if non-monotonic if (!IsMonotonic(Trans[t])) lIsSuitable = FALSE; // Exclude if weird endpoints if (!HasProperEndpoints(Trans[t])) lIsSuitable = FALSE; // Exclude if transfer function is not smooth enough // to be modelled as a gamma function, or the gamma is reversed if (cmsEstimateGamma(Trans[t]) < 1.0) lIsSuitable = FALSE; } if (lIsSuitable) { for (t = 0; t < Grid ->InputChan; t++) SlopeLimiting(Trans[t]->GammaTable, Trans[t]->nEntries); } #ifdef DEBUG if (lIsSuitable) { ASAVE(Trans[0], "\\gammar.txt"); ASAVE(Trans[1], "\\gammag.txt"); ASAVE(Trans[2], "\\gammab.txt"); }#endif if (lIsSuitable) cmsAllocLinearTable(Grid, Trans, 1); for (t = 0; t < Grid ->InputChan; t++) cmsFreeGamma(Trans[t]); }// Compute K -> L* relationshipstaticLPGAMMATABLE ComputeKToLstar(cmsHPROFILE hProfile, int nPoints, int Intent){ LPGAMMATABLE out; int i; WORD cmyk[4], wLab[3]; cmsHPROFILE hLab = cmsCreateLabProfile(NULL); cmsHTRANSFORM xform = cmsCreateTransform(hProfile, TYPE_CMYK_16, hLab, TYPE_Lab_16, Intent, cmsFLAGS_NOTPRECALC); out = cmsAllocGamma(nPoints); for (i=0; i < nPoints; i++) { cmyk[0] = 0; cmyk[1] = 0; cmyk[2] = 0; cmyk[3] = _cmsQuantizeVal(i, nPoints); cmsDoTransform(xform, cmyk, wLab, 1); out->GammaTable[i] = (WORD) (0xFFFF - wLab[0]); } cmsDeleteTransform(xform); cmsCloseProfile(hLab); return out;}// Compute Black tone curve on a CMYK -> CMYK transform. This is done by// using the proof direction on both profiles to find K->L* relationship// then joining both curvesLPGAMMATABLE _cmsBuildKToneCurve(cmsHTRANSFORM hCMYK2CMYK, int nPoints){ LPGAMMATABLE in, out; LPGAMMATABLE KTone; _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) hCMYK2CMYK; // Make sure CMYK -> CMYK if (p -> EntryColorSpace != icSigCmykData || p -> ExitColorSpace != icSigCmykData) return NULL; // Create individual curves in = ComputeKToLstar(p ->InputProfile, nPoints, p->Intent); out = ComputeKToLstar(p ->OutputProfile, nPoints, p->Intent); // Build the relationship KTone = cmsJoinGamma(in, out); #ifdef DEBUG ASAVE(in, "\\in.txt"); ASAVE(out, "\\out.txt"); ASAVE(KTone, "\\KTone.txt");#endif cmsFreeGamma(in); cmsFreeGamma(out); // Make sure it is monotonic if (!IsMonotonic(KTone)) { cmsFreeGamma(KTone); return NULL; } return KTone;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -