📄 cmsxform.c
字号:
//// Little cms// Copyright (C) 1998-2004 Marti Maria//// Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the Software // is furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.#include "lcms.h"// #define DEBUG 1// Transformations stuff// -----------------------------------------------------------------------// InterfacecmsHTRANSFORM LCMSEXPORT cmsCreateTransform(cmsHPROFILE Input, DWORD InputFormat, cmsHPROFILE Output, DWORD OutputFormat, int Intent, DWORD dwFlags);cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE Input, DWORD InputFormat, cmsHPROFILE Output, DWORD OutputFormat, cmsHPROFILE Proofing, int Intent, int ProofingIntent, DWORD dwFlags);void LCMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform);void LCMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform, LPVOID InputBuffer, LPVOID OutputBuffer, unsigned int Size);void LCMSEXPORT cmsGetAlarmCodes(int *r, int *g, int *b);void LCMSEXPORT cmsSetAlarmCodes(int r, int g, int b);BOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, int Intent, int UsedDirection);// -------------------------------------------------------------------------// Alarm RGB codesstatic WORD AlarmR = 0x8fff, AlarmG = 0x8fff, AlarmB = 0x8fff;// Tag tables, soted by intentsstatic icTagSignature Device2PCS[] = {icSigAToB0Tag, // Perceptual icSigAToB1Tag, // Relative colorimetric icSigAToB2Tag, // Saturation icSigAToB1Tag }; // Absolute colorimetric // (Relative/WhitePoint)static icTagSignature PCS2Device[] = {icSigBToA0Tag, // Perceptual icSigBToA1Tag, // Relative colorimetric icSigBToA2Tag, // Saturation icSigBToA1Tag }; // Absolute colorimetric // (Relative/WhitePoint)static icTagSignature Preview[] = {icSigPreview0Tag, icSigPreview1Tag, icSigPreview2Tag, icSigPreview1Tag };static double GlobalAdaptationState = 0;// --------------------------------Stages--------------------------------------// Following routines does implement several kind of steps inside // transform. On building the transform, code chooses adequate.// From Shaper-Matrix to PCSstaticvoid ShaperMatrixToPCS(struct _cmstransform_struct *p, WORD In[3], WORD Out[3]){ cmsEvalMatShaper(p -> InMatShaper, In, Out);}// From LUT to PCSstaticvoid LUTtoPCS(struct _cmstransform_struct *p, WORD In[], WORD Out[3]){ cmsEvalLUT(p -> Device2PCS, In, Out);}// From indexed named color to PCS staticvoid NC2toPCS(struct _cmstransform_struct *p, WORD In[], WORD Out[3]){ int index = In[0]; if (index >= p ->NamedColorList-> nColors) cmsSignalError(LCMS_ERRC_WARNING, "Color %d out of range", index); else CopyMemory(Out, p ->NamedColorList->List[index].PCS, 3 * sizeof(WORD));}// From PCS to Shaper-Matrixstaticvoid PCStoShaperMatrix(struct _cmstransform_struct *p, WORD In[3], WORD Out[3]){ cmsEvalMatShaper(p -> OutMatShaper, In, Out);}// From PCS to LUTstaticvoid PCStoLUT(struct _cmstransform_struct *p, WORD In[3], WORD Out[]){ cmsEvalLUT(p -> PCS2Device, In, Out);}// ----------------------- TRANSFORMATIONS --------------------------// Inlining some assignations#define COPY_3CHANS(to, from) { to[0]=from[0]; to[1]=from[1]; to[2]=from[2]; }// Null transformation, only hold channelsstaticvoid NullXFORM(_LPcmsTRANSFORM p, LPVOID in, LPVOID out, unsigned int Size){ register LPBYTE accum; register LPBYTE output; WORD wIn[MAXCHANNELS]; register unsigned int i, n; accum = (LPBYTE) in; output = (LPBYTE) out; n = Size; // Buffer len for (i=0; i < n; i++) { accum = p -> FromInput(p, wIn, accum); output = p -> ToOutput(p, wIn, output); }}// This is the "normal" proofing transformstaticvoid NormalXFORM(_LPcmsTRANSFORM p, LPVOID in, LPVOID out, unsigned int Size){ register LPBYTE accum; register LPBYTE output; WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS]; WORD wStageABC[3], wPCS[3], wStageLMN[MAXCHANNELS]; WORD wGamut[1]; register unsigned int i, n; accum = (LPBYTE) in; output = (LPBYTE) out; n = Size; // Buffer len for (i=0; i < n; i++) { accum = p -> FromInput(p, wIn, accum); p -> FromDevice(p, wIn, wStageABC); if (p -> Stage1) { p -> Stage1(wStageABC, wPCS, &p->m1, &p->of1); if (wPCS[0] == 0xFFFF && wPCS[1] == 0xFFFF && wPCS[2] == 0xFFFF) { // White cutoff output = p -> ToOutput((_LPcmsTRANSFORM) p, _cmsWhiteBySpace(cmsGetColorSpace(p -> OutputProfile)), output); continue; } } else COPY_3CHANS(wPCS, wStageABC); if (p->Gamut) { // Gamut check, enabled across CLUT cmsEvalLUT(p -> Gamut, wPCS, wGamut); if (wGamut[0] >= 1) { wOut[0] = AlarmR; // Gamut alarm wOut[1] = AlarmG; wOut[2] = AlarmB; wOut[3] = 0; output = p -> ToOutput((_LPcmsTRANSFORM)p, wOut, output); continue; } } if (p -> Preview) { WORD wPreview[3]; // PCS cmsEvalLUT(p -> Preview, wPCS, wPreview); COPY_3CHANS(wPCS, wPreview); } if (p -> Stage2) { p -> Stage2(wPCS, wStageLMN, &p->m2, &p->of2); if (wPCS[0] == 0xFFFF && wPCS[1] == 0xFFFF && wPCS[2] == 0xFFFF) { // White cutoff output = p -> ToOutput((_LPcmsTRANSFORM)p, _cmsWhiteBySpace(cmsGetColorSpace(p -> OutputProfile)), output); continue; } } else COPY_3CHANS(wStageLMN, wPCS); // Here wOut may come as MAXCHANNELS channels p -> ToDevice(p, wStageLMN, wOut); output = p -> ToOutput((_LPcmsTRANSFORM)p, wOut, output); }}// Using precalculated LUTstaticvoid PrecalculatedXFORM(_LPcmsTRANSFORM p, LPVOID in, LPVOID out, unsigned int Size){ register LPBYTE accum; register LPBYTE output; WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS]; register unsigned int i, n; accum = (LPBYTE) in; output = (LPBYTE) out; n = Size; // Buffer len for (i=0; i < n; i++) { accum = p -> FromInput(p, wIn, accum); cmsEvalLUT(p -> DeviceLink, wIn, wOut); output = p -> ToOutput(p, wOut, output); }}// Auxiliar: Handle precalculated gamut checkstaticvoid TransformOnePixelWithGamutCheck(_LPcmsTRANSFORM p, WORD wIn[], WORD wOut[]){ WORD wOutOfGamut; cmsEvalLUT(p ->GamutCheck, wIn, &wOutOfGamut); if (wOutOfGamut >= 1) { ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS); wOut[0] = AlarmR; wOut[1] = AlarmG; wOut[2] = AlarmB; } else cmsEvalLUT(p -> DeviceLink, wIn, wOut);}staticvoid PrecalculatedXFORMGamutCheck(_LPcmsTRANSFORM p, LPVOID in, LPVOID out, unsigned int Size){ register LPBYTE accum; register LPBYTE output; WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS]; register unsigned int i, n; accum = (LPBYTE) in; output = (LPBYTE) out; n = Size; // Buffer len for (i=0; i < n; i++) { accum = p -> FromInput(p, wIn, accum); TransformOnePixelWithGamutCheck(p, wIn, wOut); output = p -> ToOutput(p, wOut, output); }}// Using precalculated LUT + Cachestaticvoid CachedXFORM(_LPcmsTRANSFORM p, LPVOID in, LPVOID out, unsigned int Size){ register LPBYTE accum; register LPBYTE output; WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS]; register unsigned int i, n; accum = (LPBYTE) in; output = (LPBYTE) out; n = Size; // Buffer len // Empty buffers for quick memcmp ZeroMemory(wIn, sizeof(WORD) * MAXCHANNELS); ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS); for (i=0; i < n; i++) { accum = p -> FromInput(p, wIn, accum); if (memcmp(wIn, p ->CacheIn, sizeof(WORD) * MAXCHANNELS) == 0) { CopyMemory(wOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS); } else { CopyMemory(p ->CacheIn, wIn, sizeof(WORD) * MAXCHANNELS); cmsEvalLUT(p -> DeviceLink, wIn, wOut); CopyMemory(p ->CacheOut, wOut, sizeof(WORD) * MAXCHANNELS); } output = p -> ToOutput(p, wOut, output); }}// Using precalculated LUT + Cachestaticvoid CachedXFORMGamutCheck(_LPcmsTRANSFORM p, LPVOID in, LPVOID out, unsigned int Size){ register LPBYTE accum; register LPBYTE output; WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS]; register unsigned int i, n; accum = (LPBYTE) in; output = (LPBYTE) out; n = Size; // Buffer len // Empty buffers for quick memcmp ZeroMemory(wIn, sizeof(WORD) * MAXCHANNELS); ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS); for (i=0; i < n; i++) { accum = p -> FromInput(p, wIn, accum); if (memcmp(wIn, p ->CacheIn, sizeof(WORD) * MAXCHANNELS) == 0) { CopyMemory(wOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS); } else { CopyMemory(p ->CacheIn, wIn, sizeof(WORD) * MAXCHANNELS); TransformOnePixelWithGamutCheck(p, wIn, wOut); CopyMemory(p ->CacheOut, wOut, sizeof(WORD) * MAXCHANNELS); } output = p -> ToOutput(p, wOut, output); }}// Using smelted Matrix/Shaperstaticvoid MatrixShaperXFORM(_LPcmsTRANSFORM p, LPVOID in, LPVOID out, unsigned int Size){ register LPBYTE accum; register LPBYTE output; WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS]; register unsigned int i, n; accum = (LPBYTE) in; output = (LPBYTE) out; n = Size; // Buffer len for (i=0; i < n; i++) { accum = p -> FromInput(p, wIn, accum); cmsEvalMatShaper(p -> SmeltMatShaper, wIn, wOut); output = p -> ToOutput(p, wOut, output); }}// Using Named color input tablestaticvoid NC2deviceXform(_LPcmsTRANSFORM p,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -