📄 cmssamp.c
字号:
// If going across black only, keep black only if (In[0] == 0 && In[1] == 0 && In[2] == 0) { Out[0] = Out[1] = Out[2] = 0; Out[3] = LabK[3]; return 1; } // Try the original transform, maybe K is already ok (valid on K=0) cmsDoTransform(bp ->cmyk2cmyk, In, Out, 1); if (Out[3] == LabK[3]) return 1; // No, mesure and keep Lab measurement for further usage cmsDoTransform(bp->hProofOutput, Out, &ColorimetricLab, 1); // Is not black only and the transform doesn't keep black. // Obtain the Lab of CMYK. After that we have Lab + K cmsDoTransform(bp ->cmyk2Lab, In, LabK, 1); // Obtain the corresponding CMY using reverse interpolation. // As a seed, we use the colorimetric CMY cmsEvalLUTreverse(bp ->LabK2cmyk, LabK, Out, Out); // Estimate the error cmsDoTransform(bp->hProofOutput, Out, &BlackPreservingLab, 1); Error = cmsDeltaE(&ColorimetricLab, &BlackPreservingLab); // Apply TAC if needed SumCMY = Out[0] + Out[1] + Out[2]; SumCMYK = SumCMY + Out[3]; if (SumCMYK > bp ->MaxTAC) { double Ratio = 1 - ((SumCMYK - bp->MaxTAC) / SumCMY); if (Ratio < 0) Ratio = 0; Out[0] = (WORD) floor(Out[0] * Ratio + 0.5); // C Out[1] = (WORD) floor(Out[1] * Ratio + 0.5); // M Out[2] = (WORD) floor(Out[2] * Ratio + 0.5); // Y } return 1;}// Sample whole gamut to estimate maximum TAC#ifdef _MSC_VER#pragma warning(disable : 4100)#endifstaticint EstimateTAC(register WORD In[], register WORD Out[], register LPVOID Cargo){ BPCARGO* bp = (LPBPCARGO) Cargo; WORD RoundTrip[4]; int Sum; cmsDoTransform(bp->hRoundTrip, In, RoundTrip, 1); Sum = RoundTrip[0] + RoundTrip[1] + RoundTrip[2] + RoundTrip[3]; if (Sum > bp ->MaxTAC) bp ->MaxTAC = Sum; return 1;}// Estimate the maximum errorstaticint BlackPreservingEstimateErrorSampler(register WORD In[], register WORD Out[], register LPVOID Cargo){ BPCARGO* bp = (LPBPCARGO) Cargo; WORD ColorimetricOut[4]; cmsCIELab ColorimetricLab, BlackPreservingLab; double Error; if (In[0] == 0 && In[1] == 0 && In[2] == 0) return 1; cmsDoTransform(bp->cmyk2cmyk, In, ColorimetricOut, 1); cmsDoTransform(bp->hProofOutput, ColorimetricOut, &ColorimetricLab, 1); cmsDoTransform(bp->hProofOutput, Out, &BlackPreservingLab, 1); Error = cmsDeltaE(&ColorimetricLab, &BlackPreservingLab); if (Error > bp ->MaxError) bp ->MaxError = Error; return 1;}// This is the black-preserving devicelink generatorLPLUT _cmsPrecalculateBlackPreservingDeviceLink(cmsHTRANSFORM hCMYK2CMYK, DWORD dwFlags){ _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) hCMYK2CMYK; BPCARGO Cargo; LPLUT Grid; cmsHPROFILE hLab = cmsCreateLabProfile(NULL); int nGridPoints; icTagSignature Device2PCS[] = {icSigAToB0Tag, // Perceptual icSigAToB1Tag, // Relative colorimetric icSigAToB2Tag, // Saturation icSigAToB1Tag }; // Absolute colorimetric // (Relative/WhitePoint) nGridPoints = _cmsReasonableGridpointsByColorspace(p -> EntryColorSpace, dwFlags); // Fill in cargo struct Cargo.cmyk2cmyk = hCMYK2CMYK; // Compute tone curves Cargo.KTone = _cmsBuildKToneCurve(hCMYK2CMYK, 256); if (Cargo.KTone == NULL) return NULL; cmsCalcL16Params(Cargo.KTone ->nEntries, &Cargo.KToneParams); Cargo.cmyk2Lab = cmsCreateTransform(p ->InputProfile, TYPE_CMYK_16, hLab, TYPE_Lab_16, p->Intent, cmsFLAGS_NOTPRECALC); // We are going to use the reverse of proof direction Cargo.LabK2cmyk = cmsReadICCLut(p->OutputProfile, Device2PCS[p->Intent]); // Setup a roundtrip on output profile for TAC estimation Cargo.hRoundTrip = cmsCreateTransform(p ->OutputProfile, TYPE_CMYK_16, p ->OutputProfile, TYPE_CMYK_16, p->Intent, cmsFLAGS_NOTPRECALC); // Setup a proof CMYK->Lab on output Cargo.hProofOutput = cmsCreateTransform(p ->OutputProfile, TYPE_CMYK_16, hLab, TYPE_Lab_DBL, p->Intent, cmsFLAGS_NOTPRECALC); Grid = cmsAllocLUT(); if (!Grid) return NULL; Grid = cmsAlloc3DGrid(Grid, nGridPoints, 4, 4); p -> FromInput = _cmsIdentifyInputFormat(p, TYPE_CMYK_16); p -> ToOutput = _cmsIdentifyOutputFormat(p, TYPE_CMYK_16); // Step #1, estimate TAC Cargo.MaxTAC = 0; if (!cmsSample3DGrid(Grid, EstimateTAC, (LPVOID) &Cargo, 0)) { cmsFreeLUT(Grid); Grid = NULL; goto Cleanup; } // Step #2, compute approximation if (!cmsSample3DGrid(Grid, BlackPreservingSampler, (LPVOID) &Cargo, 0)) { cmsFreeLUT(Grid); Grid = NULL; goto Cleanup; } // Step #3, estimate error Cargo.MaxError = 0; cmsSample3DGrid(Grid, BlackPreservingEstimateErrorSampler, (LPVOID) &Cargo, SAMPLER_INSPECT); Cleanup: cmsDeleteTransform(Cargo.cmyk2Lab); cmsDeleteTransform(Cargo.hRoundTrip); cmsDeleteTransform(Cargo.hProofOutput); cmsCloseProfile(hLab); cmsFreeGamma(Cargo.KTone); cmsFreeLUT(Cargo.LabK2cmyk); return Grid;}// Fix broken LUT. just to obtain other CMS compatibilitystaticvoid PatchLUT(LPLUT Grid, WORD At[], WORD Value[], int nChannelsOut, int nChannelsIn){ LPL16PARAMS p16 = &Grid -> CLut16params; double px, py, pz, pw; int x0, y0, z0, w0; int i, index; if (Grid ->wFlags & LUT_HASTL1) return; // There is a prelinearization px = ((double) At[0] * (p16->Domain)) / 65535.0; py = ((double) At[1] * (p16->Domain)) / 65535.0; pz = ((double) At[2] * (p16->Domain)) / 65535.0; pw = ((double) At[3] * (p16->Domain)) / 65535.0; x0 = (int) floor(px); y0 = (int) floor(py); z0 = (int) floor(pz); w0 = (int) floor(pw); if (nChannelsIn == 4) { if (((px - x0) != 0) || ((py - y0) != 0) || ((pz - z0) != 0) || ((pw - w0) != 0)) return; // Not on exact node index = p16 -> opta4 * x0 + p16 -> opta3 * y0 + p16 -> opta2 * z0 + p16 -> opta1 * w0; } else if (nChannelsIn == 3) { if (((px - x0) != 0) || ((py - y0) != 0) || ((pz - z0) != 0)) return; // Not on exact node index = p16 -> opta3 * x0 + p16 -> opta2 * y0 + p16 -> opta1 * z0; } else if (nChannelsIn == 1) { if (((px - x0) != 0)) return; // Not on exact node index = p16 -> opta1 * x0; } else { cmsSignalError(LCMS_ERRC_ABORTED, "(internal) %d Channels are not supported on PatchLUT", nChannelsIn); return; } for (i=0; i < nChannelsOut; i++) Grid -> T[index + i] = Value[i];}BOOL _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p){ WORD *WhitePointIn, *WhitePointOut, *BlackPointIn, *BlackPointOut; int nOuts, nIns; if (!p -> DeviceLink) return FALSE; if (p ->Intent == INTENT_ABSOLUTE_COLORIMETRIC) return FALSE; if ((p ->PreviewProfile != NULL) && (p ->ProofIntent == INTENT_ABSOLUTE_COLORIMETRIC)) return FALSE; if (!_cmsEndPointsBySpace(p -> EntryColorSpace, &WhitePointIn, &BlackPointIn, &nIns)) return FALSE; if (!_cmsEndPointsBySpace(p -> ExitColorSpace, &WhitePointOut, &BlackPointOut, &nOuts)) return FALSE; // Fix white only PatchLUT(p -> DeviceLink, WhitePointIn, WhitePointOut, nOuts, nIns); // PatchLUT(p -> DeviceLink, BlackPointIn, BlackPointOut, nOuts, nIns); return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -