📄 cmslut.c
字号:
//// Little cms// Copyright (C) 1998-2005 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"// Pipeline of LUT. Enclosed by {} are new revision 4.0 of ICC spec.//// [Mat] -> [L1] -> { [Mat3] -> [Ofs3] -> [L3] ->} [CLUT] { -> [L4] -> [Mat4] -> [Ofs4] } -> [L2]//// Some of these stages would be missing. This implements the totality of // combinations of old and new LUT types as follows://// Lut8 & Lut16// ============// [Mat] -> [L1] -> [CLUT] -> [L2]//// Mat2, Ofs2, L3, L3, Mat3, Ofs3 are missing//// LutAToB// ========//// [L1] -> [CLUT] -> [L4] -> [Mat4] -> [Ofs4] -> [L2]//// Mat, Mat3, Ofs3, L3 are missing// L1 = A curves// L4 = M curves// L2 = B curves//// LutBToA // =======// // [L1] -> [Mat3] -> [Ofs3] -> [L3] -> [CLUT] -> [L2]//// Mat, L4, Mat4, Ofs4 are missing// L1 = B Curves// L3 = M Curves// L2 = A curves // //// V2&3 emulation// ===============//// For output, Mat is multiplied by// //// | 0xff00 / 0xffff 0 0 | // | 0 0xff00 / 0xffff 0 | // | 0 0 0xff00 / 0xffff | ////// For input, an additional matrix is needed at the very last end of the chain // //// | 0xffff / 0xff00 0 0 | // | 0 0xffff / 0xff00 0 | // | 0 0 0xffff / 0xff00 | ////// Which reduces to (val * 257) >> 8// A couple of macros to convert between revisions#define FROM_V2_TO_V4(x) (((((x)<<8)+(x))+0x80)>>8) // BY 65535 DIV 65280 ROUND#define FROM_V4_TO_V2(x) ((((x)<<8)+0x80)/257) // BY 65280 DIV 65535 ROUND// Lut Creation & DestructionLPLUT LCMSEXPORT cmsAllocLUT(void){ LPLUT NewLUT; NewLUT = (LPLUT) malloc(sizeof(LUT)); if (NewLUT) ZeroMemory(NewLUT, sizeof(LUT)); return NewLUT;}void LCMSEXPORT cmsFreeLUT(LPLUT Lut){ unsigned int i; if (!Lut) return; if (Lut -> T) free(Lut -> T); for (i=0; i < Lut -> OutputChan; i++) { if (Lut -> L2[i]) free(Lut -> L2[i]); } for (i=0; i < Lut -> InputChan; i++) { if (Lut -> L1[i]) free(Lut -> L1[i]); } if (Lut ->wFlags & LUT_HASTL3) { for (i=0; i < Lut -> InputChan; i++) { if (Lut -> L3[i]) free(Lut -> L3[i]); } } if (Lut ->wFlags & LUT_HASTL4) { for (i=0; i < Lut -> OutputChan; i++) { if (Lut -> L4[i]) free(Lut -> L4[i]); } } if (Lut ->CLut16params.p8) free(Lut ->CLut16params.p8); free(Lut);}staticLPVOID DupBlockTab(LPVOID Org, size_t size){ LPVOID mem = malloc(size); CopyMemory(mem, Org, size); return mem;}LPLUT LCMSEXPORT cmsDupLUT(LPLUT Orig){ LPLUT NewLUT = cmsAllocLUT(); unsigned int i; CopyMemory(NewLUT, Orig, sizeof(LUT)); for (i=0; i < Orig ->InputChan; i++) NewLUT -> L1[i] = (LPWORD) DupBlockTab((LPVOID) Orig ->L1[i], sizeof(WORD) * Orig ->In16params.nSamples); for (i=0; i < Orig ->OutputChan; i++) NewLUT -> L2[i] = (LPWORD) DupBlockTab((LPVOID) Orig ->L2[i], sizeof(WORD) * Orig ->Out16params.nSamples); NewLUT -> T = (LPWORD) DupBlockTab((LPVOID) Orig ->T, Orig -> Tsize); return NewLUT;}staticunsigned int UIpow(unsigned int a, unsigned int b){ unsigned int rv = 1; for (; b > 0; b--) rv *= a; return rv;}LPLUT LCMSEXPORT cmsAlloc3DGrid(LPLUT NewLUT, int clutPoints, int inputChan, int outputChan){ DWORD nTabSize; NewLUT -> wFlags |= LUT_HAS3DGRID; NewLUT -> cLutPoints = clutPoints; NewLUT -> InputChan = inputChan; NewLUT -> OutputChan = outputChan; nTabSize = (NewLUT -> OutputChan * UIpow(NewLUT->cLutPoints, NewLUT->InputChan) * sizeof(WORD)); NewLUT -> T = (LPWORD) malloc(nTabSize); ZeroMemory(NewLUT -> T, nTabSize); NewLUT ->Tsize = nTabSize; cmsCalcCLUT16Params(NewLUT -> cLutPoints, NewLUT -> InputChan, NewLUT -> OutputChan, &NewLUT -> CLut16params); return NewLUT;}LPLUT LCMSEXPORT cmsAllocLinearTable(LPLUT NewLUT, LPGAMMATABLE Tables[], int nTable){ unsigned int i; LPWORD PtrW; switch (nTable) { case 1: NewLUT -> wFlags |= LUT_HASTL1; cmsCalcL16Params(Tables[0] -> nEntries, &NewLUT -> In16params); NewLUT -> InputEntries = Tables[0] -> nEntries; for (i=0; i < NewLUT -> InputChan; i++) { PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> InputEntries); NewLUT -> L1[i] = PtrW; CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> InputEntries); CopyMemory(&NewLUT -> LCurvesBirth[0][i], &Tables[i] -> Birth, sizeof(LCMSGAMMAPARAMS)); } break; case 2: NewLUT -> wFlags |= LUT_HASTL2; cmsCalcL16Params(Tables[0] -> nEntries, &NewLUT -> Out16params); NewLUT -> OutputEntries = Tables[0] -> nEntries; for (i=0; i < NewLUT -> OutputChan; i++) { PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> OutputEntries); NewLUT -> L2[i] = PtrW; CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> OutputEntries); CopyMemory(&NewLUT -> LCurvesBirth[1][i], &Tables[i] -> Birth, sizeof(LCMSGAMMAPARAMS)); } break; // 3 & 4 according ICC 4.0 spec case 3: NewLUT -> wFlags |= LUT_HASTL3; cmsCalcL16Params(Tables[0] -> nEntries, &NewLUT -> L3params); NewLUT -> L3Entries = Tables[0] -> nEntries; for (i=0; i < NewLUT -> InputChan; i++) { PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> L3Entries); NewLUT -> L3[i] = PtrW; CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> L3Entries); CopyMemory(&NewLUT -> LCurvesBirth[2][i], &Tables[i] -> Birth, sizeof(LCMSGAMMAPARAMS)); } break; case 4: NewLUT -> wFlags |= LUT_HASTL4; cmsCalcL16Params(Tables[0] -> nEntries, &NewLUT -> L4params); NewLUT -> L4Entries = Tables[0] -> nEntries; for (i=0; i < NewLUT -> OutputChan; i++) { PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> L4Entries); NewLUT -> L4[i] = PtrW; CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> L4Entries); CopyMemory(&NewLUT -> LCurvesBirth[3][i], &Tables[i] -> Birth, sizeof(LCMSGAMMAPARAMS)); } break; default:; } return NewLUT;}// Set the LUT matrixLPLUT LCMSEXPORT cmsSetMatrixLUT(LPLUT Lut, LPMAT3 M){ MAT3toFix(&Lut ->Matrix, M); if (!MAT3isIdentity(&Lut->Matrix, 0.0001)) Lut ->wFlags |= LUT_HASMATRIX; return Lut;}// Set matrix & offset, v4 compatibleLPLUT LCMSEXPORT cmsSetMatrixLUT4(LPLUT Lut, LPMAT3 M, LPVEC3 off, DWORD dwFlags){ WMAT3 WMat; WVEC3 Woff; VEC3 Zero = {{0, 0, 0}}; MAT3toFix(&WMat, M); if (off == NULL) off = &Zero; VEC3toFix(&Woff, off); // Nop if identity if (MAT3isIdentity(&WMat, 0.0001) && (Woff.n[VX] == 0 && Woff.n[VY] == 0 && Woff.n[VZ] == 0)) return Lut; switch (dwFlags) { case LUT_HASMATRIX: Lut ->Matrix = WMat; Lut ->wFlags |= LUT_HASMATRIX; break; case LUT_HASMATRIX3: Lut ->Mat3 = WMat; Lut ->Ofs3 = Woff; Lut ->wFlags |= LUT_HASMATRIX3; break; case LUT_HASMATRIX4: Lut ->Mat4 = WMat; Lut ->Ofs4 = Woff; Lut ->wFlags |= LUT_HASMATRIX4; break; default:; } return Lut;}// The full evaluatorvoid LCMSEXPORT cmsEvalLUT(LPLUT Lut, WORD In[], WORD Out[]){ register unsigned int i; WORD StageABC[MAXCHANNELS], StageLMN[MAXCHANNELS]; // Try to speedup things on plain devicelinks if (Lut ->wFlags == LUT_HAS3DGRID) { Lut ->CLut16params.Interp3D(In, Out, Lut -> T, &Lut -> CLut16params); return; } // Nope, evaluate whole LUT for (i=0; i < Lut -> InputChan; i++) StageABC[i] = In[i]; if (Lut ->wFlags & LUT_V4_OUTPUT_EMULATE_V2) { // Clamp Lab to avoid overflow if (StageABC[0] > 0xFF00) StageABC[0] = 0xFF00; StageABC[0] = (WORD) FROM_V2_TO_V4(StageABC[0]); StageABC[1] = (WORD) FROM_V2_TO_V4(StageABC[1]); StageABC[2] = (WORD) FROM_V2_TO_V4(StageABC[2]); } if (Lut ->wFlags & LUT_V2_OUTPUT_EMULATE_V4) { StageABC[0] = (WORD) FROM_V4_TO_V2(StageABC[0]); StageABC[1] = (WORD) FROM_V4_TO_V2(StageABC[1]); StageABC[2] = (WORD) FROM_V4_TO_V2(StageABC[2]); } // Matrix handling. if (Lut -> wFlags & LUT_HASMATRIX) { WVEC3 InVect, OutVect; // In LUT8 here comes the special gray axis fixup if (Lut ->FixGrayAxes) { StageABC[1] = _cmsClampWord(StageABC[1] - 128); StageABC[2] = _cmsClampWord(StageABC[2] - 128); } // Matrix InVect.n[VX] = ToFixedDomain(StageABC[0]); InVect.n[VY] = ToFixedDomain(StageABC[1]); InVect.n[VZ] = ToFixedDomain(StageABC[2]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -