📄 cmsio1.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.// ICC profile serialization#include "lcms.h"// ----------------------------------------------------------------- Tag Serialization// Alignment of ICC file format uses 4 bytes DWORD#define ALIGNLONG(x) (((x)+3) & ~(3)) // Aligns to DWORD boundarystatic int GlobalLanguageCode; // Language & country descriptors, for ICC 4.0 supportstatic int GlobalCountryCode; #ifdef __BEOS__# define USE_CUSTOM_SWAB 1#endif#ifdef USE_CUSTOM_SWAB// Replacement to swab function, thanks to YNOP// for providing the BeOS port//// from: @(#)swab.c 5.10 (Berkeley) 3/6/91staticvoid xswab(const void *from, void *to, size_t len){ register unsigned long temp; register int n; register char *fp, *tp; n = (len >> 1) + 1; fp = (char *)from; tp = (char *)to;#define STEP temp = *fp++,*tp++ = *fp++,*tp++ = temp /* round to multiple of 8 */ while ((--n) & 07) STEP; n >>= 3; while (--n >= 0) { STEP; STEP; STEP; STEP; STEP; STEP; STEP; STEP; }#undef STEP}#else#define xswab swab#endif//// Little-Endian to Big-Endian//#ifdef USE_BIG_ENDIAN#define AdjustEndianess16(a)#define AdjustEndianess32(a)#define AdjustEndianessArray16(a, b)#elsestaticvoid AdjustEndianess16(LPBYTE pByte){ BYTE tmp; tmp = pByte[0]; pByte[0] = pByte[1]; pByte[1] = tmp;}staticvoid AdjustEndianess32(LPBYTE pByte){ BYTE temp1; BYTE temp2; temp1 = *pByte++; temp2 = *pByte++; *(pByte-1) = *pByte; *pByte++ = temp2; *(pByte-3) = *pByte; *pByte = temp1;}// swap bytes in a array of wordsstaticvoid AdjustEndianessArray16(LPWORD p, size_t num_words){ xswab((char*) p, (char*)p, (int) num_words * sizeof(WORD));}#endif// Transports to properly encoded values - note that icc profiles does use// big endian notation.staticicInt32Number TransportValue32(icInt32Number Value){ icInt32Number Temp = Value; AdjustEndianess32((LPBYTE) &Temp); return Temp;}staticWORD TransportValue16(WORD Value){ WORD Temp = Value; AdjustEndianess16((LPBYTE) &Temp); return Temp;}// from Fixed point 8.8 to doublestaticdouble Convert8Fixed8(WORD fixed8){ BYTE msb, lsb; lsb = (BYTE) (fixed8 & 0xff); msb = (BYTE) (((WORD) fixed8 >> 8) & 0xff); return (double) ((double) msb + ((double) lsb / 256.0));}// from Fixed point 15.16 to doublestaticdouble Convert15Fixed16(icS15Fixed16Number fix32){ double floater, sign, mid, hack; int Whole, FracPart; AdjustEndianess32((LPBYTE) &fix32); sign = (fix32 < 0 ? -1 : 1); fix32 = abs(fix32); Whole = LOWORD(fix32 >> 16); FracPart = LOWORD(fix32 & 0x0000ffffL); hack = 65536.0; mid = (double) FracPart / hack; floater = (double) Whole + mid; return sign * floater;}// Auxiliar-- read base and return typestaticicTagTypeSignature ReadBase(LPLCMSICCPROFILE Icc){ icTagBase Base; Icc -> Read(&Base, sizeof(icTagBase), 1, Icc); AdjustEndianess32((LPBYTE) &Base.sig); return Base.sig;}staticvoid DecodeDateTimeNumber(const icDateTimeNumber *Source, struct tm *Dest){ Dest->tm_sec = TransportValue16(Source->seconds); Dest->tm_min = TransportValue16(Source->minutes); Dest->tm_hour = TransportValue16(Source->hours); Dest->tm_mday = TransportValue16(Source->day); Dest->tm_mon = TransportValue16(Source->month) - 1; Dest->tm_year = TransportValue16(Source->year) - 1900; Dest->tm_wday = -1; Dest->tm_yday = -1; Dest->tm_isdst = 0;}staticvoid EncodeDateTimeNumber(icDateTimeNumber *Dest, const struct tm *Source){ Dest->seconds = TransportValue16((WORD) Source->tm_sec); Dest->minutes = TransportValue16((WORD) Source->tm_min); Dest->hours = TransportValue16((WORD) Source->tm_hour); Dest->day = TransportValue16((WORD) Source->tm_mday); Dest->month = TransportValue16((WORD) (Source->tm_mon + 1)); Dest->year = TransportValue16((WORD) (Source->tm_year + 1900));}// Jun-21-2000: Some profiles (those that comes with W2K) comes// with the media white (media black?) x 100. Add a sanity checkstaticvoid NormalizeXYZ(LPcmsCIEXYZ Dest){ while (Dest -> X > 2. && Dest -> Y > 2. && Dest -> Z > 2.) { Dest -> X /= 10.; Dest -> Y /= 10.; Dest -> Z /= 10.; }}// Evaluates a XYZ tristimulous across chromatic adaptation matrixstaticvoid EvalCHRM(LPcmsCIEXYZ Dest, LPMAT3 Chrm, LPcmsCIEXYZ Src){ VEC3 d, s; s.n[VX] = Src -> X; s.n[VY] = Src -> Y; s.n[VZ] = Src -> Z; MAT3eval(&d, Chrm, &s); Dest ->X = d.n[VX]; Dest ->Y = d.n[VY]; Dest ->Z = d.n[VZ];}// Read profile header and validate itstaticLPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, BOOL lIsFromMemory){ icTag Tag; icHeader Header; icInt32Number TagCount, i; Icc -> Read(&Header, sizeof(icHeader), 1, Icc); // Convert endian AdjustEndianess32((LPBYTE) &Header.size); AdjustEndianess32((LPBYTE) &Header.cmmId); AdjustEndianess32((LPBYTE) &Header.version); AdjustEndianess32((LPBYTE) &Header.deviceClass); AdjustEndianess32((LPBYTE) &Header.colorSpace); AdjustEndianess32((LPBYTE) &Header.pcs); AdjustEndianess32((LPBYTE) &Header.magic); AdjustEndianess32((LPBYTE) &Header.flags); AdjustEndianess32((LPBYTE) &Header.attributes[0]); AdjustEndianess32((LPBYTE) &Header.renderingIntent); // Validate it if (Header.magic != icMagicNumber) goto ErrorCleanup; if (Icc ->Read(&TagCount, sizeof(icInt32Number), 1, Icc) != 1) goto ErrorCleanup; AdjustEndianess32((LPBYTE) &TagCount); Icc -> DeviceClass = Header.deviceClass; Icc -> ColorSpace = Header.colorSpace; Icc -> PCS = Header.pcs; Icc -> RenderingIntent = (icRenderingIntent) Header.renderingIntent; Icc -> flags = Header.flags; Icc -> attributes = Header.attributes[0]; Icc -> Illuminant.X = Convert15Fixed16(Header.illuminant.X); Icc -> Illuminant.Y = Convert15Fixed16(Header.illuminant.Y); Icc -> Illuminant.Z = Convert15Fixed16(Header.illuminant.Z); Icc -> Version = Header.version; // Get creation date/time DecodeDateTimeNumber(&Header.date, &Icc ->Created); // Fix illuminant, some profiles are broken in this field! Icc ->Illuminant = *cmsD50_XYZ(); // The profile ID are 16 raw bytes CopyMemory(Icc ->ProfileID, Header.reserved, 16); // Get rid of possible wrong profiles NormalizeXYZ(&Icc -> Illuminant); // Read tag directory if (TagCount > MAX_TABLE_TAG) { cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", TagCount); goto ErrorCleanup; } Icc -> TagCount = TagCount; for (i=0; i < TagCount; i++) { Icc ->Read(&Tag, sizeof(icTag), 1, Icc); AdjustEndianess32((LPBYTE) &Tag.offset); AdjustEndianess32((LPBYTE) &Tag.size); AdjustEndianess32((LPBYTE) &Tag.sig); // Signature Icc -> TagNames[i] = Tag.sig; Icc -> TagOffsets[i] = Tag.offset; Icc -> TagSizes[i] = Tag.size; } return Icc;ErrorCleanup: Icc ->Close(Icc); free(Icc); if (lIsFromMemory) cmsSignalError(LCMS_ERRC_ABORTED, "Corrupted memory profile"); else cmsSignalError(LCMS_ERRC_ABORTED, "Corrupted profile: '%s'", Icc->PhysicalFile); return NULL;}staticunsigned int uipow(unsigned int a, unsigned int b) { unsigned int rv = 1; for (; b > 0; b--) rv *= a; return rv;}// Convert between notations.#define TO16_TAB(x) (WORD) (((x) << 8) | (x))// LUT8 can come only in Lab space. There is a fatal flaw in// converting from Lut8 to Lut16. Due to particular encoding // of Lab, different actions should be taken from input and // output Lab8 LUTS. For input, is as easy as applying a << 8,// since numbers comes in fixed point. However, for output LUT// things goes a bit more complex.... LUT 16 is supposed to// have a domain of 0..ff00, so we should remap the LUT in order// to get things working. Affected signatures are B2Axx tags, // preview and gamut.// I do solve it by multiplying input matrix by:// // | 0xffff/0xff00 0 0 |// | 0 0xffff/0xff00 0 |// | 0 0 0xffff/0xff00 |//// The input values got then remapped to adequate domainstaticvoid FixLUT8(LPLUT Lut, icTagSignature sig, size_t nTabSize){ MAT3 Fixup, Original, Result; LPWORD PtrW; size_t i; switch (sig) { case icSigBToA0Tag: case icSigBToA1Tag: case icSigBToA2Tag: case icSigGamutTag: case icSigPreview0Tag: case icSigPreview1Tag: case icSigPreview2Tag: VEC3init(&Fixup.v[0], (double) 0xFFFF/0xFF00, 0, 0); VEC3init(&Fixup.v[1], 0, (double) 0xFFFF/0xFF00, 0); VEC3init(&Fixup.v[2], 0, 0, (double) 0xFFFF/0xFF00); MAT3fromFix(&Original, &Lut->Matrix); MAT3per(&Result, &Original, &Fixup); MAT3toFix(&Lut->Matrix, &Result); Lut -> wFlags |= LUT_HASMATRIX; break; // For input, clear low part since this has to be // Lab in fixed point default: PtrW = Lut -> T; for (i = 0; i < nTabSize; i++) { *PtrW++ &= 0xFF00; } } }// On Lab -> Lab abstract or Lab identities, fix both sides of LUTstaticvoid FixLUT8bothSides(LPLUT Lut, size_t nTabSize){ MAT3 Fixup, Original, Result; LPWORD PtrW; size_t i; VEC3init(&Fixup.v[0], (double) 0xFFFF/0xFF00, 0, 0); VEC3init(&Fixup.v[1], 0, (double) 0xFFFF/0xFF00, 0); VEC3init(&Fixup.v[2], 0, 0, (double) 0xFFFF/0xFF00); MAT3fromFix(&Original, &Lut->Matrix); MAT3per(&Result, &Original, &Fixup); MAT3toFix(&Lut->Matrix, &Result); Lut -> wFlags |= LUT_HASMATRIX; PtrW = Lut -> T; for (i = 0; i < nTabSize; i++) { *PtrW++ &= 0xFF00; } }// The infamous LUT 8staticvoid ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig){ icLut8 LUT8; LPBYTE Temp; size_t nTabSize; unsigned int i, j; unsigned int AllLinear; LPWORD PtrW; Icc ->Read(&LUT8, sizeof(icLut8) - SIZEOF_UINT8_ALIGNED, 1, Icc); NewLUT -> wFlags = LUT_HASTL1|LUT_HASTL2|LUT_HAS3DGRID; NewLUT -> cLutPoints = LUT8.clutPoints; NewLUT -> InputChan = LUT8.inputChan;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -