// Auxiliar to retrieve a pointer to the segmentr containing the Lab value static cmsGDBPoint* GetPoint(cmsGDB* gbd, const cmsCIELab* Lab, cmsSpherical* sp) { cmsVEC3 v; int alpha, theta; // Housekeeping _cmsAssert(gbd != NULL); _cmsAssert(Lab != NULL); _cmsAssert(sp != NULL); // Center L* by substracting half of its domain, that's 50 _cmsVEC3init(&v, Lab ->L - 50.0, Lab ->a, Lab ->b); // Convert to spherical coordinates ToSpherical(sp, &v); if (sp ->r < 0 || sp ->alpha < 0 || sp->theta < 0) { cmsSignalError(gbd ->ContextID, cmsERROR_RANGE, "spherical value out of range"); return NULL; } // On which sector it falls? QuantizeToSector(sp, &alpha, &theta); if (alpha < 0 || theta < 0 || alpha >= SECTORS || theta >= SECTORS) { cmsSignalError(gbd ->ContextID, cmsERROR_RANGE, " quadrant out of range"); return NULL; } // Get pointer to the sector return &gbd ->Gamut[theta][alpha]; }
// For backwards compatibility cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform, cmsUInt32Number InputFormat, cmsUInt32Number OutputFormat) { _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; cmsFormatter16 FromInput, ToOutput; // We only can afford to change formatters if previous transform is at least 16 bits if (!(xform ->dwOriginalFlags & cmsFLAGS_CAN_CHANGE_FORMATTER)) { cmsSignalError(xform ->ContextID, cmsERROR_NOT_SUITABLE, "cmsChangeBuffersFormat works only on transforms created originally with at least 16 bits of precision"); return FALSE; } FromInput = _cmsGetFormatter(xform->ContextID, InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; ToOutput = _cmsGetFormatter(xform->ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; if (FromInput == NULL || ToOutput == NULL) { cmsSignalError(xform -> ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); return FALSE; } xform ->InputFormat = InputFormat; xform ->OutputFormat = OutputFormat; xform ->FromInput = FromInput; xform ->ToOutput = ToOutput; return TRUE; }
// Chain several profiles into a single LUT. It just checks the parameters and then calls the handler // for the first intent in chain. The handler may be user-defined. Is up to the handler to deal with the // rest of intents in chain. A maximum of 255 profiles at time are supported, which is pretty reasonable. cmsPipeline* _cmsLinkProfiles(cmsContext ContextID, cmsUInt32Number nProfiles, cmsUInt32Number TheIntents[], cmsHPROFILE hProfiles[], cmsBool BPC[], cmsFloat64Number AdaptationStates[], cmsUInt32Number dwFlags) { cmsUInt32Number i; cmsIntentsList* Intent; // Make sure a reasonable number of profiles is provided if (nProfiles <= 0 || nProfiles > 255) { cmsSignalError(ContextID, cmsERROR_RANGE, "Couldn't link '%d' profiles", nProfiles); return NULL; } for (i=0; i < nProfiles; i++) { // Check if black point is really needed or allowed. Note that // following Adobe's document: // BPC does not apply to devicelink profiles, nor to abs colorimetric, // and applies always on V4 perceptual and saturation. if (TheIntents[i] == INTENT_ABSOLUTE_COLORIMETRIC) BPC[i] = FALSE; if (TheIntents[i] == INTENT_PERCEPTUAL || TheIntents[i] == INTENT_SATURATION) { // Force BPC for V4 profiles in perceptual and saturation if (cmsGetProfileVersion(hProfiles[i]) >= 4.0) BPC[i] = TRUE; } } // Search for a handler. The first intent in the chain defines the handler. That would // prevent using multiple custom intents in a multiintent chain, but the behaviour of // this case would present some issues if the custom intent tries to do things like // preserve primaries. This solution is not perfect, but works well on most cases. Intent = SearchIntent(TheIntents[0]); if (Intent == NULL) { cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported intent '%d'", TheIntents[0]); return NULL; } // Call the handler return Intent ->Link(ContextID, nProfiles, TheIntents, hProfiles, BPC, AdaptationStates, dwFlags); }
// Returns TRUE if the intent is implemented as CLUT cmsBool CMSEXPORT cmsIsCLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number UsedDirection) { const cmsTagSignature* TagTable; // For devicelinks, the supported intent is that one stated in the header if (cmsGetDeviceClass(hProfile) == cmsSigLinkClass) { return (cmsGetHeaderRenderingIntent(hProfile) == Intent); } switch (UsedDirection) { case LCMS_USED_AS_INPUT: TagTable = Device2PCS16; break; case LCMS_USED_AS_OUTPUT:TagTable = PCS2Device16; break; // For proofing, we need rel. colorimetric in output. Let's do some recursion case LCMS_USED_AS_PROOF: return cmsIsIntentSupported(hProfile, Intent, LCMS_USED_AS_INPUT) && cmsIsIntentSupported(hProfile, INTENT_RELATIVE_COLORIMETRIC, LCMS_USED_AS_OUTPUT); default: cmsSignalError(cmsGetProfileContextID(hProfile), cmsERROR_RANGE, "Unexpected direction (%d)", UsedDirection); return FALSE; } return cmsIsTag(hProfile, TagTable[Intent]); }
LPLCMSICCPROFILE _cmsCreateProfileFromMemPlaceholder(LPVOID MemPtr, DWORD dwSize) { LPLCMSICCPROFILE NewIcc; LPVOID ICCfile = MemoryOpen((LPBYTE) MemPtr, (size_t) dwSize, 'r'); if (ICCfile == NULL) { cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't allocate %ld bytes for profile", dwSize); return NULL; } NewIcc = (LPLCMSICCPROFILE) _cmsCreateProfilePlaceholder(); if (NewIcc == NULL) return NULL; NewIcc -> PhysicalFile[0] = 0; NewIcc ->stream = ICCfile; NewIcc ->Read = MemoryRead; NewIcc ->Seek = MemorySeek; NewIcc ->Tell = MemoryTell; NewIcc ->Close = MemoryClose; NewIcc ->Grow = MemoryGrow; NewIcc ->Write = MemoryWrite; NewIcc ->IsWrite = FALSE; return NewIcc; }
LPLCMSICCPROFILE _cmsCreateProfileFromFilePlaceholder(const char* FileName) { LPLCMSICCPROFILE NewIcc; LPVOID ICCfile = FileOpen(FileName); if (ICCfile == NULL) { cmsSignalError(LCMS_ERRC_ABORTED, "File '%s' not found", FileName); return NULL; } NewIcc = (LPLCMSICCPROFILE) _cmsCreateProfilePlaceholder(); if (NewIcc == NULL) return NULL; strncpy(NewIcc -> PhysicalFile, FileName, MAX_PATH-1); NewIcc -> PhysicalFile[MAX_PATH-1] = 0; NewIcc ->stream = ICCfile; NewIcc ->Read = FileRead; NewIcc ->Seek = FileSeek; NewIcc ->Tell = FileTell; NewIcc ->Close = FileClose; NewIcc ->Grow = FileGrow; NewIcc ->Write = NULL; NewIcc ->IsWrite = FALSE; return NewIcc; }
// Multiprofile transforms: Gamut check is not available here, as it is unclear from which profile the gamut comes. cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransformTHR(cmsContext ContextID, cmsHPROFILE hProfiles[], cmsUInt32Number nProfiles, cmsUInt32Number InputFormat, cmsUInt32Number OutputFormat, cmsUInt32Number Intent, cmsUInt32Number dwFlags) { cmsUInt32Number i; cmsBool BPC[256]; cmsUInt32Number Intents[256]; cmsFloat64Number AdaptationStates[256]; if (nProfiles <= 0 || nProfiles > 255) { cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles); return NULL; } for (i=0; i < nProfiles; i++) { BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE; Intents[i] = Intent; AdaptationStates[i] = cmsSetAdaptationStateTHR(ContextID, -1); } return cmsCreateExtendedTransform(ContextID, nProfiles, hProfiles, BPC, Intents, AdaptationStates, NULL, 0, InputFormat, OutputFormat, dwFlags); }
// Parametric curves // // Parameters goes as: Curve, a, b, c, d, e, f // Type is the ICC type +1 // if type is negative, then the curve is analyticaly inverted cmsToneCurve* CMSEXPORT cmsBuildParametricToneCurve(cmsContext ContextID, cmsInt32Number Type, const cmsFloat64Number Params[]) { cmsCurveSegment Seg0; int Pos = 0; cmsUInt32Number size; _cmsParametricCurvesCollection* c = GetParametricCurveByType(Type, &Pos); _cmsAssert(Params != NULL); if (c == NULL) { cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type); return NULL; } memset(&Seg0, 0, sizeof(Seg0)); Seg0.x0 = MINUS_INF; Seg0.x1 = PLUS_INF; Seg0.Type = Type; size = c->ParameterCount[Pos] * sizeof(cmsFloat64Number); memmove(Seg0.Params, Params, size); return cmsBuildSegmentedToneCurve(ContextID, 1, &Seg0); }
static int WriteInputMatrixShaper(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsStage* Matrix, cmsStage* Shaper) { cmsColorSpaceSignature ColorSpace; int rc; cmsCIEXYZ BlackPointAdaptedToD50; ColorSpace = cmsGetColorSpace(hProfile); cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, INTENT_RELATIVE_COLORIMETRIC, 0); if (ColorSpace == cmsSigGrayData) { cmsToneCurve** ShaperCurve = _cmsStageGetPtrToCurveSet(Shaper); rc = EmitCIEBasedA(m, ShaperCurve[0], &BlackPointAdaptedToD50); } else if (ColorSpace == cmsSigRgbData) { rc = EmitCIEBasedABC(m, GetPtrToMatrix(Matrix), _cmsStageGetPtrToCurveSet(Shaper), &BlackPointAdaptedToD50); } else { cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Profile is not suitable for CSA. Unsupported colorspace."); return 0; } return rc; }
BOOL cmsxIT8SetDataSet(LCMSHANDLE hIT8, const char* cPatch, const char* cSample, char *Val) { LPIT8 it8 = (LPIT8) hIT8; int iField, iSet; iField = LocateSample(it8, cSample); if (iField < 0) { cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't find data field %s\n", cSample); return false; } if (it8-> nPatches == 0) { AllocateDataFormat(it8); AllocateDataSet(it8); CookPointers(it8); } if (stricmp(cSample, "SAMPLE_ID") == 0) { iSet = LocateEmptyPatch(it8, cPatch); if (iSet < 0) { cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't add more patches '%s'\n", cPatch); return false; } iField = it8 -> SampleID; } else { iSet = LocatePatch(it8, cPatch); if (iSet < 0) { cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't find patch '%s'\n", cPatch); return false; } } return SetData(it8, iSet, iField, Val); }
void cmsFreeNamedColorList(LPcmsNAMEDCOLORLIST v) { if (v == NULL) { cmsSignalError(LCMS_ERRC_RECOVERABLE, "Couldn't free a NULL named color list"); return; } _cmsFree(v); }
static LCMSBOOL FileSeek(struct _lcms_iccprofile_struct* Icc, size_t offset) { if (fseek((FILE*) Icc ->stream, (long) offset, SEEK_SET) != 0) { cmsSignalError(LCMS_ERRC_ABORTED, "Seek error; probably corrupted file"); return TRUE; } return FALSE; }
static size_t FileRead(void *buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc) { size_t nReaded = fread(buffer, size, count, (FILE*) Icc->stream); if (nReaded != count) { cmsSignalError(LCMS_ERRC_ABORTED, "Read error. Got %d bytes, block should be of %d bytes", nReaded * size, count * size); return 0; } return nReaded; }
static BOOL DataFormatSection(LPIT8 it8) { int iField = 0; BOOL Ignoring = false; InSymbol(it8); /* Eats "BEGIN_DATA_FORMAT" */ CheckEOLN(it8); while (it8->sy != SEND_DATA_FORMAT && it8->sy != SEOLN && it8->sy != SEOF && it8->sy != SSYNERROR) { if (it8->sy != SIDENT) { cmsSignalError(LCMS_ERRC_ABORTED, "Sample type expected"); it8->sy = SSYNERROR; return false; } if (!Ignoring && iField > it8->nSamples) { cmsSignalError(LCMS_ERRC_WARNING, "More than NUMBER_OF_FIELDS fields. Extra is ignored\n"); Ignoring = true; } else { if (!SetDataFormat(it8, iField, it8->id)) return false; iField++; } InSymbol(it8); Skip(it8, SEOLN); } Skip(it8, SEOLN); Skip(it8, SEND_DATA_FORMAT); Skip(it8, SEOLN); return true; }
/* Add a property into a linked list */ static BOOL AddToList(LPIT8 it8, LPKEYVALUE* Head, const char *Key, const char* Value) { LPKEYVALUE p; LPKEYVALUE last; /* Check if property is already in list (this is an error) */ if (IsAvailableOnList(*Head, Key, &last)) { cmsSignalError(LCMS_ERRC_ABORTED, "duplicate key <%s>", Key); return false; } /* Allocate the container */ p = (LPKEYVALUE) AllocChunk(it8, sizeof(KEYVALUE)); if (p == NULL) { cmsSignalError(LCMS_ERRC_ABORTED, "AddToList: out of memory"); return false; } /* Store name and value */ p->Keyword = AllocString(it8, Key); if (Value) p->Value = AllocString(it8, Value); else p->Value = NULL; p->Next = NULL; /* Keep the container in our list */ if (*Head == NULL) *Head = p; else last->Next = p; return true; }
static LCMSBOOL MemorySeek(struct _lcms_iccprofile_struct* Icc, size_t offset) { FILEMEM* ResData = (FILEMEM*) Icc ->stream; if (offset > ResData ->Size) { cmsSignalError(LCMS_ERRC_ABORTED, "Pointer error; probably corrupted file"); return TRUE; } ResData ->Pointer = (DWORD) offset; return FALSE; }
BOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint) { double x, y; double T, T2, T3; // double M1, M2; // No optimization provided. T = TempK; T2 = T*T; // Square T3 = T2*T; // Cube // For correlated color temperature (T) between 4000K and 7000K: if (T >= 4000. && T <= 7000.) { x = -4.6070*(1E9/T3) + 2.9678*(1E6/T2) + 0.09911*(1E3/T) + 0.244063; } else // or for correlated color temperature (T) between 7000K and 25000K: if (T > 7000.0 && T <= 25000.0) { x = -2.0064*(1E9/T3) + 1.9018*(1E6/T2) + 0.24748*(1E3/T) + 0.237040; } else { cmsSignalError(LCMS_ERRC_ABORTED, "cmsWhitePointFromTemp: invalid temp"); return FALSE; } // Obtain y(x) y = -3.000*(x*x) + 2.870*x - 0.275; // wave factors (not used, but here for futures extensions) // M1 = (-1.3515 - 1.7703*x + 5.9114 *y)/(0.0241 + 0.2562*x - 0.7341*y); // M2 = (0.0300 - 31.4424*x + 30.0717*y)/(0.0241 + 0.2562*x - 0.7341*y); // Fill WhitePoint struct WhitePoint -> x = x; WhitePoint -> y = y; WhitePoint -> Y = 1.0; return TRUE; }
static void AllocateDataSet(LPIT8 it8) { if (it8 -> Data) return; /* Already allocated */ it8-> nSamples = atoi(cmsxIT8GetProperty(it8, "NUMBER_OF_FIELDS")); it8-> nPatches = atoi(cmsxIT8GetProperty(it8, "NUMBER_OF_SETS")); it8-> Data = (char**)AllocChunk (it8, (it8->nSamples + 1) * (it8->nPatches + 1) *sizeof (char*)); if (it8->Data == NULL) { cmsSignalError(-1, "AllocateDataSet: Unable to allocate data array"); } }
// Smooths a curve sampled at regular intervals. cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda) { cmsFloat32Number w[MAX_NODES_IN_CURVE], y[MAX_NODES_IN_CURVE], z[MAX_NODES_IN_CURVE]; int i, nItems, Zeros, Poles; if (Tab == NULL) return FALSE; if (cmsIsToneCurveLinear(Tab)) return FALSE; // Nothing to do nItems = Tab -> nEntries; if (nItems >= MAX_NODES_IN_CURVE) { cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: too many points."); return FALSE; } memset(w, 0, nItems * sizeof(cmsFloat32Number)); memset(y, 0, nItems * sizeof(cmsFloat32Number)); memset(z, 0, nItems * sizeof(cmsFloat32Number)); for (i=0; i < nItems; i++) { y[i+1] = (cmsFloat32Number) Tab -> Table16[i]; w[i+1] = 1.0; } if (!smooth2(Tab ->InterpParams->ContextID, w, y, z, (cmsFloat32Number) lambda, nItems)) return FALSE; // Do some reality - checking... Zeros = Poles = 0; for (i=nItems; i > 1; --i) { if (z[i] == 0.) Zeros++; if (z[i] >= 65535.) Poles++; if (z[i] < z[i-1]) return FALSE; // Non-Monotonic } if (Zeros > (nItems / 3)) return FALSE; // Degenerated, mostly zeros if (Poles > (nItems / 3)) return FALSE; // Degenerated, mostly poles // Seems ok for (i=0; i < nItems; i++) { // Clamp to cmsUInt16Number Tab -> Table16[i] = _cmsQuickSaturateWord(z[i+1]); } return TRUE; }
static size_t MemoryRead(LPVOID buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc) { FILEMEM* ResData = (FILEMEM*) Icc ->stream; LPBYTE Ptr; size_t len = size * count; size_t extent = ResData -> Pointer + len; if (len == 0) { return 0; } if (len / size != count) { cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Integer overflow with count / size."); return 0; } if (extent < len || extent < ResData -> Pointer) { cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Integer overflow with len."); return 0; } if (ResData -> Pointer + len > ResData -> Size) { len = (ResData -> Size - ResData -> Pointer); cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Got %d bytes, block should be of %d bytes", len * size, count * size); return 0; } Ptr = ResData -> Block; Ptr += ResData -> Pointer; CopyMemory(buffer, Ptr, len); ResData -> Pointer += (int) len; return count; }
static void EvalNamedColor(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) { cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) mpe ->Data; cmsUInt16Number index = (cmsUInt16Number) _cmsQuickSaturateWord(In[0] * 65535.0); cmsUInt32Number j; if (index >= NamedColorList-> nColors) { cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range; ignored", index); } else { for (j=0; j < NamedColorList ->ColorantCount; j++) Out[j] = (cmsFloat32Number) (NamedColorList->List[index].DeviceColorant[j] / 65535.0); } }
static BOOL SynError(LPIT8 it8, const char *Txt, ...) { char Buffer[256], ErrMsg[1024]; va_list args; va_start(args, Txt); vsprintf(Buffer, Txt, args); va_end(args); sprintf(ErrMsg, "%s: Line %d, %s", it8->FileName, it8->lineno, Buffer); it8->sy = SSYNERROR; cmsSignalError(LCMS_ERRC_ABORTED, ErrMsg); return false; }
static void AllocateDataFormat(LPIT8 it8) { if (it8 -> DataFormat) return; /* Already allocated */ // work around a crash on invalid profile, see bug #229370 const char *numberOfFields = cmsxIT8GetProperty(it8, "NUMBER_OF_FIELDS"); if (numberOfFields) it8 -> nSamples = atoi(numberOfFields); else it8 -> nSamples = 0; if (it8 -> nSamples <= 0) { cmsSignalError(LCMS_ERRC_WARNING, "AllocateDataFormat: Unknown NUMBER_OF_FIELDS, assuming 10"); it8 -> nSamples = 10; } it8 -> DataFormat = (char**) AllocChunk (it8, (it8->nSamples + 1) * sizeof(char *)); if (it8->DataFormat == NULL) { cmsSignalError(LCMS_ERRC_ABORTED, "AllocateDataFormat: Unable to allocate dataFormat array"); } }
static void EvalNamedColorPCS(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) { cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) mpe ->Data; cmsUInt16Number index = (cmsUInt16Number) _cmsQuickSaturateWord(In[0] * 65535.0); if (index >= NamedColorList-> nColors) { cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range; ignored", index); } else { // Named color always uses Lab Out[0] = (cmsFloat32Number) (NamedColorList->List[index].PCS[0] / 65535.0); Out[1] = (cmsFloat32Number) (NamedColorList->List[index].PCS[1] / 65535.0); Out[2] = (cmsFloat32Number) (NamedColorList->List[index].PCS[2] / 65535.0); } }
icInt32Number _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, LCMSBOOL lSignalError) { icInt32Number i; if (sig == 0) return -1; // 0 identifies a special tag holding raw memory. for (i=0; i < Profile -> TagCount; i++) { if (sig == Profile -> TagNames[i]) return i; } if (lSignalError) cmsSignalError(LCMS_ERRC_ABORTED, "Tag '%lx' not found", sig); return -1; }
void _cmsSetSaveToDisk(LPLCMSICCPROFILE Icc, const char* FileName) { if (FileName == NULL) { Icc ->stream = NULL; } else { Icc ->stream = fopen(FileName, "wb"); if (Icc ->stream == NULL) cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't write to file '%s'", FileName); } Icc ->Write = FileWrite; // Save to disk Icc ->Close = FileClose; }
void _cmsSetSaveToMemory(LPLCMSICCPROFILE Icc, LPVOID MemPtr, size_t dwSize) { if (MemPtr == NULL) { Icc ->stream = NULL; } else { Icc ->stream = (FILEMEM*) MemoryOpen((LPBYTE) MemPtr, dwSize, 'w'); if (Icc ->stream == NULL) cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't write to memory"); } Icc ->Write = MemoryWrite; Icc ->Close = MemoryClose; }
// Obtains WhitePoint from Temperature cmsBool CMSEXPORT cmsWhitePointFromTemp(cmsCIExyY* WhitePoint, cmsFloat64Number TempK) { cmsFloat64Number x, y; cmsFloat64Number T, T2, T3; // cmsFloat64Number M1, M2; _cmsAssert(WhitePoint != NULL); T = TempK; T2 = T*T; // Square T3 = T2*T; // Cube // For correlated color temperature (T) between 4000K and 7000K: if (T >= 4000. && T <= 7000.) { x = -4.6070*(1E9/T3) + 2.9678*(1E6/T2) + 0.09911*(1E3/T) + 0.244063; } else // or for correlated color temperature (T) between 7000K and 25000K: if (T > 7000.0 && T <= 25000.0) { x = -2.0064*(1E9/T3) + 1.9018*(1E6/T2) + 0.24748*(1E3/T) + 0.237040; } else { cmsSignalError(0, cmsERROR_RANGE, "cmsWhitePointFromTemp: invalid temp"); return FALSE; } // Obtain y(x) y = -3.000*(x*x) + 2.870*x - 0.275; // wave factors (not used, but here for futures extensions) // M1 = (-1.3515 - 1.7703*x + 5.9114 *y)/(0.0241 + 0.2562*x - 0.7341*y); // M2 = (0.0300 - 31.4424*x + 30.0717*y)/(0.0241 + 0.2562*x - 0.7341*y); WhitePoint -> x = x; WhitePoint -> y = y; WhitePoint -> Y = 1.0; return TRUE; }
LCMSBOOL cmmGetProfileElement( LPLCMSICCPROFILE hProfile, icTagSignature sig, LPBYTE data, size_t *dataSize ) { int idx = findTag(hProfile, sig); if(idx < 0) { cmsSignalError(LCMS_ERRC_ABORTED, "Tagged profile element not found"); return FALSE; } *dataSize = MIN(*dataSize, hProfile->TagSizes[idx]); if(hProfile->TagPtrs[idx]) { CopyMemory(data, hProfile->TagPtrs[idx], *dataSize); } else { seekMemBuffer(hProfile->stream, hProfile->TagOffsets[idx]); readMemBuffer(data, 1, *dataSize, hProfile->stream); } return TRUE; }
static int WriteInputMatrixShaper(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsStage* Matrix, cmsStage* Shaper) { cmsColorSpaceSignature ColorSpace; int rc; cmsCIEXYZ BlackPointAdaptedToD50; ColorSpace = cmsGetColorSpace(hProfile); cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, INTENT_RELATIVE_COLORIMETRIC, 0); if (ColorSpace == cmsSigGrayData) { cmsToneCurve** ShaperCurve = _cmsStageGetPtrToCurveSet(Shaper); rc = EmitCIEBasedA(m, ShaperCurve[0], &BlackPointAdaptedToD50); } else if (ColorSpace == cmsSigRgbData) { cmsMAT3 Mat; int i, j; memmove(&Mat, GetPtrToMatrix(Matrix), sizeof(Mat)); for (i=0; i < 3; i++) for (j=0; j < 3; j++) Mat.v[i].n[j] *= MAX_ENCODEABLE_XYZ; rc = EmitCIEBasedABC(m, (cmsFloat64Number *) &Mat, _cmsStageGetPtrToCurveSet(Shaper), &BlackPointAdaptedToD50); } else { cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Profile is not suitable for CSA. Unsupported colorspace."); return 0; } return rc; }