static LPVOID MemoryOpen(LPBYTE Block, size_t Size, char Mode) { FILEMEM* fm = (FILEMEM*) _cmsMalloc(sizeof(FILEMEM)); if (fm == NULL) return NULL; ZeroMemory(fm, sizeof(FILEMEM)); if (Mode == 'r') { fm ->Block = (LPBYTE) _cmsMalloc(Size); if (fm ->Block == NULL) { _cmsFree(fm); return NULL; } CopyMemory(fm->Block, Block, Size); fm ->FreeBlockOnClose = TRUE; } else { fm ->Block = Block; fm ->FreeBlockOnClose = FALSE; } fm ->Size = Size; fm ->Pointer = 0; return (LPVOID) fm; }
LPMATSHAPER cmsAllocMatShaper(LPMAT3 Matrix, LPGAMMATABLE Tables[], DWORD Behaviour) { LPMATSHAPER NewMatShaper; int i, AllLinear; NewMatShaper = (LPMATSHAPER) _cmsMalloc(sizeof(MATSHAPER)); if (NewMatShaper) ZeroMemory(NewMatShaper, sizeof(MATSHAPER)); NewMatShaper->dwFlags = Behaviour & (MATSHAPER_ALLSMELTED); // Fill matrix part MAT3toFix(&NewMatShaper -> Matrix, Matrix); // Reality check if (!MAT3isIdentity(&NewMatShaper -> Matrix, 0.00001)) NewMatShaper -> dwFlags |= MATSHAPER_HASMATRIX; // Now, on the table characteristics cmsCalcL16Params(Tables[0] -> nEntries, &NewMatShaper -> p16); // Copy tables AllLinear = 0; for (i=0; i < 3; i++) { LPWORD PtrW; PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewMatShaper -> p16.nSamples); if (PtrW == NULL) { cmsFreeMatShaper(NewMatShaper); return NULL; } CopyMemory(PtrW, Tables[i] -> GammaTable, sizeof(WORD) * Tables[i] -> nEntries); NewMatShaper -> L[i] = PtrW; // Set table pointer // Linear after all? AllLinear += cmsIsLinear(PtrW, NewMatShaper -> p16.nSamples); } // If is all linear, then supress table interpolation (this // will speed greately some trivial operations if (AllLinear != 3) NewMatShaper -> dwFlags |= MATSHAPER_HASSHAPER; return NewMatShaper; }
// Sub allocation takes care of many pointers of small size. The memory allocated in // this way have be freed at once. Next function allocates a single chunk for linked list // I prefer this method over realloc due to the big inpact on xput realloc may have if // memory is being swapped to disk. This approach is safer (although that may not be true on all platforms) static _cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32Number Initial) { _cmsSubAllocator_chunk* chunk; // 20K by default if (Initial == 0) Initial = 20*1024; // Create the container chunk = (_cmsSubAllocator_chunk*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator_chunk)); if (chunk == NULL) return NULL; // Initialize values chunk ->Block = (cmsUInt8Number*) _cmsMalloc(ContextID, Initial); if (chunk ->Block == NULL) { // Something went wrong _cmsFree(ContextID, chunk); return NULL; } chunk ->BlockSize = Initial; chunk ->Used = 0; chunk ->next = NULL; return chunk; }
static void* defMtxCreate(cmsContext id) { _cmsMutex* ptr_mutex = (_cmsMutex*) _cmsMalloc(id, sizeof(_cmsMutex)); _cmsInitMutexPrimitive(ptr_mutex); return (void*) ptr_mutex; }
static int ComputeTables(LPGAMMATABLE Table[3], LPWORD Out[3], LPL16PARAMS p16) { int i, AllLinear; cmsCalcL16Params(Table[0] -> nEntries, p16); AllLinear = 0; for (i=0; i < 3; i++) { LPWORD PtrW; PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * p16 -> nSamples); if (PtrW == NULL) return -1; // Signal error CopyMemory(PtrW, Table[i] -> GammaTable, sizeof(WORD) * Table[i] -> nEntries); Out[i] = PtrW; // Set table pointer // Linear after all? AllLinear += cmsIsLinear(PtrW, p16 -> nSamples); } // If is all linear, then supress table interpolation (this // will speed greately some trivial operations. // Return 1 if present, 0 if all linear if (AllLinear != 3) return 1; return 0; }
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) _cmsMalloc(nTabSize); if (NewLUT -> T == NULL) return NULL; ZeroMemory(NewLUT -> T, nTabSize); NewLUT ->Tsize = nTabSize; cmsCalcCLUT16Params(NewLUT -> cLutPoints, NewLUT -> InputChan, NewLUT -> OutputChan, &NewLUT -> CLut16params); return NewLUT; }
static LPVOID DupBlockTab(LPVOID Org, size_t size) { LPVOID mem = _cmsMalloc(size); if (mem != NULL) CopyMemory(mem, Org, size); return mem; }
// Generic allocate & zero static void* _cmsMallocZeroDefaultFn(cmsContext ContextID, cmsUInt32Number size) { void *pt = _cmsMalloc(ContextID, size); if (pt == NULL) return NULL; memset(pt, 0, size); return pt; }
LPLUT LCMSEXPORT cmsAllocLUT(void) { LPLUT NewLUT; NewLUT = (LPLUT) _cmsMalloc(sizeof(LUT)); if (NewLUT) ZeroMemory(NewLUT, sizeof(LUT)); return NewLUT; }
// Generic block duplication static void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number size) { void* mem; if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never dup over 512Mb mem = _cmsMalloc(ContextID, size); if (mem != NULL && Org != NULL) memmove(mem, Org, size); return mem; }
// Precomputes tables for 8-bit on input devicelink. // LPLUT _cmsBlessLUT8(LPLUT Lut) { int i, j; WORD StageABC[3]; Fixed32 v1, v2, v3; LPL8PARAMS p8; LPL16PARAMS p = &Lut ->CLut16params; p8 = (LPL8PARAMS) _cmsMalloc(sizeof(L8PARAMS)); if (p8 == NULL) return NULL; // values comes * 257, so we can safely take first byte (x << 8 + x) // if there are prelinearization, is already smelted in tables for (i=0; i < 256; i++) { StageABC[0] = StageABC[1] = StageABC[2] = RGB_8_TO_16(i); if (Lut ->wFlags & LUT_HASTL1) { for (j=0; j < 3; j++) StageABC[j] = cmsLinearInterpLUT16(StageABC[j], Lut -> L1[j], &Lut -> In16params); Lut ->wFlags &= ~LUT_HASTL1; } v1 = ToFixedDomain(StageABC[0] * p -> Domain); v2 = ToFixedDomain(StageABC[1] * p -> Domain); v3 = ToFixedDomain(StageABC[2] * p -> Domain); p8 ->X0[i] = p->opta3 * FIXED_TO_INT(v1); p8 ->Y0[i] = p->opta2 * FIXED_TO_INT(v2); p8 ->Z0[i] = p->opta1 * FIXED_TO_INT(v3); p8 ->rx[i] = (WORD) FIXED_REST_TO_INT(v1); p8 ->ry[i] = (WORD) FIXED_REST_TO_INT(v2); p8 ->rz[i] = (WORD) FIXED_REST_TO_INT(v3); } Lut -> CLut16params.p8 = p8; Lut -> CLut16params.Interp3D = cmsTetrahedralInterp8; return Lut; }
LPMATSHAPER cmsAllocMatShaper2(LPMAT3 Matrix, LPGAMMATABLE In[], LPGAMMATABLE Out[], DWORD Behaviour) { LPMATSHAPER NewMatShaper; int rc; NewMatShaper = (LPMATSHAPER) _cmsMalloc(sizeof(MATSHAPER)); if (NewMatShaper) ZeroMemory(NewMatShaper, sizeof(MATSHAPER)); NewMatShaper->dwFlags = Behaviour & (MATSHAPER_ALLSMELTED); // Fill matrix part MAT3toFix(&NewMatShaper -> Matrix, Matrix); // Reality check if (!MAT3isIdentity(&NewMatShaper -> Matrix, 0.00001)) NewMatShaper -> dwFlags |= MATSHAPER_HASMATRIX; // Now, on the table characteristics if (Out) { rc = ComputeTables(Out, NewMatShaper ->L, &NewMatShaper ->p16); if (rc < 0) { cmsFreeMatShaper(NewMatShaper); return NULL; } if (rc == 1) NewMatShaper -> dwFlags |= MATSHAPER_HASSHAPER; } if (In) { rc = ComputeTables(In, NewMatShaper ->L2, &NewMatShaper ->p2_16); if (rc < 0) { cmsFreeMatShaper(NewMatShaper); return NULL; } if (rc == 1) NewMatShaper -> dwFlags |= MATSHAPER_HASINPSHAPER; } return NewMatShaper; }
cmsHPROFILE _cmsCreateProfilePlaceholder(void) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) _cmsMalloc(sizeof(LCMSICCPROFILE)); if (Icc == NULL) return NULL; // Empty values ZeroMemory(Icc, sizeof(LCMSICCPROFILE)); // Make sure illuminant is correct Icc ->Illuminant = *cmsD50_XYZ(); // Set it to empty Icc -> TagCount = 0; // Return the handle return (cmsHPROFILE) Icc; }
// Duplicating a MLU is as easy as copying all members cmsMLU* CMSEXPORT cmsMLUdup(const cmsMLU* mlu) { cmsMLU* NewMlu = NULL; // Duplicating a NULL obtains a NULL if (mlu == NULL) return NULL; NewMlu = cmsMLUalloc(mlu ->ContextID, mlu ->UsedEntries); if (NewMlu == NULL) return NULL; // Should never happen if (NewMlu ->AllocatedEntries < mlu ->UsedEntries) goto Error; // Sanitize... if (NewMlu ->Entries == NULL || mlu ->Entries == NULL) goto Error; memmove(NewMlu ->Entries, mlu ->Entries, mlu ->UsedEntries * sizeof(_cmsMLUentry)); NewMlu ->UsedEntries = mlu ->UsedEntries; // The MLU may be empty if (mlu ->PoolUsed == 0) { NewMlu ->MemPool = NULL; } else { // It is not empty NewMlu ->MemPool = _cmsMalloc(mlu ->ContextID, mlu ->PoolUsed); if (NewMlu ->MemPool == NULL) goto Error; } NewMlu ->PoolSize = mlu ->PoolUsed; if (NewMlu ->MemPool == NULL || mlu ->MemPool == NULL) goto Error; memmove(NewMlu ->MemPool, mlu->MemPool, mlu ->PoolUsed); NewMlu ->PoolUsed = mlu ->PoolUsed; return NewMlu; Error: if (NewMlu != NULL) cmsMLUfree(NewMlu); return NULL; }
static void GenerateCSA(void) { cmsHPROFILE hProfile = cmsOpenProfileFromFile(cInProf, "r"); size_t n; char* Buffer; n = cmsGetPostScriptCSA(hProfile, Intent, NULL, 0); if (n == 0) return; Buffer = (char*) _cmsMalloc(n + 1); cmsGetPostScriptCSA(hProfile, Intent, Buffer, n); Buffer[n] = 0; fprintf(OutFile, "%s", Buffer); _cmsFree(Buffer); cmsCloseProfile(hProfile); }
LPcmsNAMEDCOLORLIST cmsAllocNamedColorList(int n) { size_t size = sizeof(cmsNAMEDCOLORLIST) + (n - 1) * sizeof(cmsNAMEDCOLOR); LPcmsNAMEDCOLORLIST v = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size); if (v == NULL) { cmsSignalError(LCMS_ERRC_ABORTED, "Out of memory creating named color list"); return NULL; } ZeroMemory(v, size); v ->nColors = n; v ->Allocated = n; v ->Prefix[0] = 0; v ->Suffix[0] = 0; return v; }
cmsSEQ* CMSEXPORT cmsDupProfileSequenceDescription(const cmsSEQ* pseq) { cmsSEQ *NewSeq; cmsUInt32Number i; if (pseq == NULL) return NULL; NewSeq = (cmsSEQ*) _cmsMalloc(pseq -> ContextID, sizeof(cmsSEQ)); if (NewSeq == NULL) return NULL; NewSeq -> seq = (cmsPSEQDESC*) _cmsCalloc(pseq ->ContextID, pseq ->n, sizeof(cmsPSEQDESC)); if (NewSeq ->seq == NULL) goto Error; NewSeq -> ContextID = pseq ->ContextID; NewSeq -> n = pseq ->n; for (i=0; i < pseq->n; i++) { memmove(&NewSeq ->seq[i].attributes, &pseq ->seq[i].attributes, sizeof(cmsUInt64Number)); NewSeq ->seq[i].deviceMfg = pseq ->seq[i].deviceMfg; NewSeq ->seq[i].deviceModel = pseq ->seq[i].deviceModel; memmove(&NewSeq ->seq[i].ProfileID, &pseq ->seq[i].ProfileID, sizeof(cmsProfileID)); NewSeq ->seq[i].technology = pseq ->seq[i].technology; NewSeq ->seq[i].Manufacturer = cmsMLUdup(pseq ->seq[i].Manufacturer); NewSeq ->seq[i].Model = cmsMLUdup(pseq ->seq[i].Model); NewSeq ->seq[i].Description = cmsMLUdup(pseq ->seq[i].Description); } return NewSeq; Error: cmsFreeProfileSequenceDescription(NewSeq); return NULL; }
static LPcmsNAMEDCOLORLIST GrowNamedColorList(LPcmsNAMEDCOLORLIST v, int ByElements) { if (ByElements > v ->Allocated) { LPcmsNAMEDCOLORLIST TheNewList; int NewElements; size_t size; if (v ->Allocated == 0) NewElements = 64; // Initial guess else NewElements = v ->Allocated; while (ByElements > NewElements) NewElements *= 2; size = sizeof(cmsNAMEDCOLORLIST) + (sizeof(cmsNAMEDCOLOR) * NewElements); TheNewList = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size); if (TheNewList == NULL) { cmsSignalError(LCMS_ERRC_ABORTED, "Out of memory reallocating named color list"); return NULL; } else { ZeroMemory(TheNewList, size); CopyMemory(TheNewList, v, sizeof(cmsNAMEDCOLORLIST) + (v ->nColors - 1) * sizeof(cmsNAMEDCOLOR)); TheNewList -> Allocated = NewElements; _cmsFree(v); return TheNewList; } } return v; }
LPVOID _cmsInitTag(LPLCMSICCPROFILE Icc, icTagSignature sig, size_t size, const void* Init) { LPVOID Ptr; icInt32Number i; i = _cmsSearchTag(Icc, sig, FALSE); if (i >=0) { if (Icc -> TagPtrs[i]) _cmsFree(Icc -> TagPtrs[i]); } else { i = Icc -> TagCount; Icc -> TagCount++; if (Icc ->TagCount >= MAX_TABLE_TAG) { cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", MAX_TABLE_TAG); Icc ->TagCount = MAX_TABLE_TAG-1; return NULL; } } Ptr = _cmsMalloc(size); if (Ptr == NULL) return NULL; CopyMemory(Ptr, Init, size); Icc ->TagNames[i] = sig; Icc ->TagSizes[i] = size; Icc ->TagPtrs[i] = Ptr; return Ptr; }
static void GenerateCRD(void) { cmsHPROFILE hProfile = cmsOpenProfileFromFile(cOutProf, "r"); size_t n; char* Buffer; DWORD dwFlags = 0; if (BlackPointCompensation) dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION; if (Undecorated) dwFlags |= cmsFLAGS_NODEFAULTRESOURCEDEF; switch (PrecalcMode) { case 0: dwFlags |= cmsFLAGS_LOWRESPRECALC; break; case 2: dwFlags |= cmsFLAGS_HIGHRESPRECALC; break; case 1: if (NumOfGridPoints > 0) dwFlags |= cmsFLAGS_GRIDPOINTS(NumOfGridPoints); break; default: FatalError("ERROR: Unknown precalculation mode '%d'", PrecalcMode); } n = cmsGetPostScriptCRDEx(hProfile, Intent, dwFlags, NULL, 0); if (n == 0) return; Buffer = (char*) _cmsMalloc(n + 1); cmsGetPostScriptCRDEx(hProfile, Intent, dwFlags, Buffer, n); Buffer[n] = 0; fprintf(OutFile, "%s", Buffer); _cmsFree(Buffer); cmsCloseProfile(hProfile); }
int main(int argc, char *argv[]) { int i, nargs; cmsHPROFILE Profiles[257]; cmsHPROFILE hProfile; DWORD dwFlags = 0; cmsHTRANSFORM hTransform; fprintf(stderr, "little cms device link generator - v1.7\n"); HandleSwitches(argc, argv); cmsSetErrorHandler(MyErrorHandler); nargs = (argc - xoptind); if (nargs < 1) Help(0); if (nargs > 255) FatalError("ERROR: Holy profile! what are you trying to do with so many profiles?"); for (i=0; i < nargs; i++) { Profiles[i] = OpenProfile(argv[i + xoptind]); } switch (PrecalcMode) { case 0: dwFlags |= cmsFLAGS_LOWRESPRECALC; break; case 2: dwFlags |= cmsFLAGS_HIGHRESPRECALC; break; case 1: if (NumOfGridPoints > 0) dwFlags |= cmsFLAGS_GRIDPOINTS(NumOfGridPoints); break; default: FatalError("ERROR: Unknown precalculation mode '%d'", PrecalcMode); } if (BlackPointCompensation) dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION; if (BlackPreservation > 0) { dwFlags |= cmsFLAGS_PRESERVEBLACK; cmsSetCMYKPreservationStrategy(BlackPreservation-1); } if (TagResult) dwFlags |= cmsFLAGS_GUESSDEVICECLASS; if (NoPrelinearization) dwFlags |= cmsFLAGS_NOPRELINEARIZATION; if (InkLimit != 400.0) { cmsHPROFILE hInkLimit = cmsCreateInkLimitingDeviceLink( cmsGetColorSpace(Profiles[nargs-1]), InkLimit); Profiles[nargs++] = hInkLimit; } if (lUse8bits) dwFlags |= cmsFLAGS_NOPRELINEARIZATION; hTransform = cmsCreateMultiprofileTransform(Profiles, nargs, 0, 0, Intent, dwFlags); if (hTransform) { size_t size = sizeof(int) + nargs * sizeof(cmsPSEQDESC); LPcmsSEQ pseq = (LPcmsSEQ) _cmsMalloc(size); ZeroMemory(pseq, size); pseq ->n = nargs; for (i=0; i < nargs; i++) { strcpy(pseq ->seq[i].Manufacturer, cmsTakeManufacturer(Profiles[i])); strcpy(pseq ->seq[1].Model, cmsTakeModel(Profiles[i])); } hProfile = cmsTransform2DeviceLink(hTransform, dwFlags); cmsAddTag(hProfile, icSigProfileDescriptionTag, (LPVOID) Description); cmsAddTag(hProfile, icSigCopyrightTag, (LPVOID) "Generated by littlecms icclink. No copyright, use freely"); cmsAddTag(hProfile, icSigProfileSequenceDescTag, (LPVOID) pseq); if (lUse8bits) _cmsSetLUTdepth(hProfile, 8); if (_cmsSaveProfile(hProfile, cOutProf)) fprintf(stderr, "Ok"); else fprintf(stderr, "Error saving file!"); cmsCloseProfile(hProfile); _cmsFree(pseq); } cmsDeleteTransform(hTransform); for (i=0; i < nargs; i++) { cmsCloseProfile(Profiles[i]); } return 0; }
LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC) { LPcmsCIECAM02 lpMod; if((lpMod = (LPcmsCIECAM02) _cmsMalloc(sizeof(cmsCIECAM02))) == NULL) { return (LCMSHANDLE) NULL; } ZeroMemory(lpMod, sizeof(cmsCIECAM02)); lpMod ->adoptedWhite.XYZ[0] = pVC ->whitePoint.X; lpMod ->adoptedWhite.XYZ[1] = pVC ->whitePoint.Y; lpMod ->adoptedWhite.XYZ[2] = pVC ->whitePoint.Z; lpMod -> LA = pVC ->La; lpMod -> Yb = pVC ->Yb; lpMod -> D = pVC ->D_value; lpMod -> surround = pVC ->surround; switch (lpMod -> surround) { case AVG_SURROUND_4: lpMod->F = 1.0; // Not included in CAM02 lpMod->c = 0.69; lpMod->Nc = 1.0; break; case CUTSHEET_SURROUND: lpMod->F = 0.8; lpMod->c = 0.41; lpMod->Nc = 0.8; break; case DARK_SURROUND: lpMod -> F = 0.8; lpMod -> c = 0.525; lpMod -> Nc = 0.8; break; case DIM_SURROUND: lpMod -> F = 0.9; lpMod -> c = 0.59; lpMod -> Nc = 0.95; break; default: // Average surround lpMod -> F = 1.0; lpMod -> c = 0.69; lpMod -> Nc = 1.0; } lpMod -> n = compute_n(lpMod); lpMod -> z = compute_z(lpMod); lpMod -> Nbb = computeNbb(lpMod); lpMod -> FL = computeFL(lpMod); if (lpMod -> D == D_CALCULATE || lpMod -> D == D_CALCULATE_DISCOUNT) { lpMod -> D = computeD(lpMod); } lpMod -> Ncb = lpMod -> Nbb; lpMod -> adoptedWhite = XYZtoCAT02(lpMod -> adoptedWhite); lpMod -> adoptedWhite = ChromaticAdaptation(lpMod -> adoptedWhite, lpMod); lpMod -> adoptedWhite = CAT02toHPE(lpMod -> adoptedWhite); lpMod -> adoptedWhite = NonlinearCompression(lpMod -> adoptedWhite, lpMod); return (LCMSHANDLE) lpMod; }
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) _cmsMalloc(sizeof(WORD) * NewLUT -> InputEntries); if (PtrW == NULL) return NULL; NewLUT -> L1[i] = PtrW; CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> InputEntries); CopyMemory(&NewLUT -> LCurvesSeed[0][i], &Tables[i] -> Seed, 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) _cmsMalloc(sizeof(WORD) * NewLUT -> OutputEntries); if (PtrW == NULL) return NULL; NewLUT -> L2[i] = PtrW; CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> OutputEntries); CopyMemory(&NewLUT -> LCurvesSeed[1][i], &Tables[i] -> Seed, 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) _cmsMalloc(sizeof(WORD) * NewLUT -> L3Entries); if (PtrW == NULL) return NULL; NewLUT -> L3[i] = PtrW; CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> L3Entries); CopyMemory(&NewLUT -> LCurvesSeed[2][i], &Tables[i] -> Seed, 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) _cmsMalloc(sizeof(WORD) * NewLUT -> L4Entries); if (PtrW == NULL) return NULL; NewLUT -> L4[i] = PtrW; CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> L4Entries); CopyMemory(&NewLUT -> LCurvesSeed[3][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS)); } break; default:; } return NewLUT; }