diff options
Diffstat (limited to 'third_party/lcms2-2.6/src/cmsxform.c')
-rw-r--r-- | third_party/lcms2-2.6/src/cmsxform.c | 1137 |
1 files changed, 0 insertions, 1137 deletions
diff --git a/third_party/lcms2-2.6/src/cmsxform.c b/third_party/lcms2-2.6/src/cmsxform.c deleted file mode 100644 index dffe6b2fb7..0000000000 --- a/third_party/lcms2-2.6/src/cmsxform.c +++ /dev/null @@ -1,1137 +0,0 @@ -//--------------------------------------------------------------------------------- -// -// Little Color Management System -// Copyright (c) 1998-2014 Marti Maria Saguer -// -// 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 "lcms2_internal.h" - -// Transformations stuff -// ----------------------------------------------------------------------- - -#define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0 - -// The Context0 observer adaptation state. -_cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; - -// Init and duplicate observer adaptation state -void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx, - const struct _cmsContext_struct* src) -{ - static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; - void* from; - - if (src != NULL) { - from = src ->chunks[AdaptationStateContext]; - } - else { - from = &AdaptationStateChunk; - } - - ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType)); -} - - -// Sets adaptation state for absolute colorimetric intent in the given context. Adaptation state applies on all -// but cmsCreateExtendedTransformTHR(). Little CMS can handle incomplete adaptation states. -cmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d) -{ - cmsFloat64Number prev; - _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext); - - // Get previous value for return - prev = ptr ->AdaptationState; - - // Set the value if d is positive or zero - if (d >= 0.0) { - - ptr ->AdaptationState = d; - } - - // Always return previous value - return prev; -} - - -// The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine -cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d) -{ - return cmsSetAdaptationStateTHR(NULL, d); -} - -// ----------------------------------------------------------------------- - -// Alarm codes for 16-bit transformations, because the fixed range of containers there are -// no values left to mark out of gamut. - -#define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - -_cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; - -// Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be -// encoded in 16 bits. -void CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) -{ - _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); - - _cmsAssert(ContextAlarmCodes != NULL); // Can't happen - - memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes)); -} - -// Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context. -// Values are meant to be encoded in 16 bits. -void CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) -{ - _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); - - _cmsAssert(ContextAlarmCodes != NULL); // Can't happen - - memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes)); -} - -void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]) -{ - _cmsAssert(NewAlarm != NULL); - - cmsSetAlarmCodesTHR(NULL, NewAlarm); -} - -void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number OldAlarm[cmsMAXCHANNELS]) -{ - _cmsAssert(OldAlarm != NULL); - cmsGetAlarmCodesTHR(NULL, OldAlarm); -} - - -// Init and duplicate alarm codes -void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx, - const struct _cmsContext_struct* src) -{ - static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; - void* from; - - if (src != NULL) { - from = src ->chunks[AlarmCodesContext]; - } - else { - from = &AlarmCodesChunk; - } - - ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType)); -} - -// ----------------------------------------------------------------------- - -// Get rid of transform resources -void CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform) -{ - _cmsTRANSFORM* p = (_cmsTRANSFORM*) hTransform; - - _cmsAssert(p != NULL); - - if (p -> GamutCheck) - cmsPipelineFree(p -> GamutCheck); - - if (p -> Lut) - cmsPipelineFree(p -> Lut); - - if (p ->InputColorant) - cmsFreeNamedColorList(p ->InputColorant); - - if (p -> OutputColorant) - cmsFreeNamedColorList(p ->OutputColorant); - - if (p ->Sequence) - cmsFreeProfileSequenceDescription(p ->Sequence); - - if (p ->UserData) - p ->FreeUserData(p ->ContextID, p ->UserData); - - _cmsFree(p ->ContextID, (void *) p); -} - -// Apply transform. -void CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform, - const void* InputBuffer, - void* OutputBuffer, - cmsUInt32Number Size) - -{ - _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; - - p -> xform(p, InputBuffer, OutputBuffer, Size, Size); -} - - -// Apply transform. -void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, - const void* InputBuffer, - void* OutputBuffer, - cmsUInt32Number Size, cmsUInt32Number Stride) - -{ - _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; - - p -> xform(p, InputBuffer, OutputBuffer, Size, Stride); -} - - -// Transform routines ---------------------------------------------------------------------------------------------------------- - -// Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check. -// Note that because extended range, we can use a -1.0 value for out of gamut in this case. -static -void FloatXFORM(_cmsTRANSFORM* p, - const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) -{ - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS]; - cmsFloat32Number OutOfGamut; - cmsUInt32Number i, j; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - - for (i=0; i < Size; i++) { - - accum = p -> FromInputFloat(p, fIn, accum, Stride); - - // Any gamut chack to do? - if (p ->GamutCheck != NULL) { - - // Evaluate gamut marker. - cmsPipelineEvalFloat( fIn, &OutOfGamut, p ->GamutCheck); - - // Is current color out of gamut? - if (OutOfGamut > 0.0) { - - // Certainly, out of gamut - for (j=0; j < cmsMAXCHANNELS; j++) - fOut[j] = -1.0; - - } - else { - // No, proceed normally - cmsPipelineEvalFloat(fIn, fOut, p -> Lut); - } - } - else { - - // No gamut check at all - cmsPipelineEvalFloat(fIn, fOut, p -> Lut); - } - - // Back to asked representation - output = p -> ToOutputFloat(p, fOut, output, Stride); - } -} - - -static -void NullFloatXFORM(_cmsTRANSFORM* p, - const void* in, - void* out, - cmsUInt32Number Size, - cmsUInt32Number Stride) -{ - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsFloat32Number fIn[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; - - for (i=0; i < n; i++) { - - accum = p -> FromInputFloat(p, fIn, accum, Stride); - output = p -> ToOutputFloat(p, fIn, output, Stride); - } -} - -// 16 bit precision ----------------------------------------------------------------------------------------------------------- - -// Null transformation, only applies formatters. No cach?static -void NullXFORM(_cmsTRANSFORM* p, - const void* in, - void* out, cmsUInt32Number Size, - cmsUInt32Number Stride) -{ - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsUInt16Number wIn[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; // Buffer len - - for (i=0; i < n; i++) { - - accum = p -> FromInput(p, wIn, accum, Stride); - output = p -> ToOutput(p, wIn, output, Stride); - } -} - - -// No gamut check, no cache, 16 bits -static -void PrecalculatedXFORM(_cmsTRANSFORM* p, - const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) -{ - register cmsUInt8Number* accum; - register cmsUInt8Number* output; - cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; - - for (i=0; i < n; i++) { - - accum = p -> FromInput(p, wIn, accum, Stride); - p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); - output = p -> ToOutput(p, wOut, output, Stride); - } -} - - -// Auxiliar: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical. -static -void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p, - const cmsUInt16Number wIn[], - cmsUInt16Number wOut[]) -{ - cmsUInt16Number wOutOfGamut; - - p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data); - if (wOutOfGamut >= 1) { - - cmsUInt16Number i; - _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext); - - for (i=0; i < p ->Lut->OutputChannels; i++) { - - wOut[i] = ContextAlarmCodes ->AlarmCodes[i]; - } - } - else - p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); -} - -// Gamut check, No cach? 16 bits. -static -void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, - const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) -{ - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; // Buffer len - - for (i=0; i < n; i++) { - - accum = p -> FromInput(p, wIn, accum, Stride); - TransformOnePixelWithGamutCheck(p, wIn, wOut); - output = p -> ToOutput(p, wOut, output, Stride); - } -} - - -// No gamut check, Cach? 16 bits, -static -void CachedXFORM(_cmsTRANSFORM* p, - const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) -{ - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - _cmsCACHE Cache; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; // Buffer len - - // Empty buffers for quick memcmp - memset(wIn, 0, sizeof(wIn)); - memset(wOut, 0, sizeof(wOut)); - - // Get copy of zero cache - memcpy(&Cache, &p ->Cache, sizeof(Cache)); - - for (i=0; i < n; i++) { - - accum = p -> FromInput(p, wIn, accum, Stride); - - if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { - - memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); - } - else { - - p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); - - memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); - memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); - } - - output = p -> ToOutput(p, wOut, output, Stride); - } - -} - - -// All those nice features together -static -void CachedXFORMGamutCheck(_cmsTRANSFORM* p, - const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) -{ - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - _cmsCACHE Cache; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; // Buffer len - - // Empty buffers for quick memcmp - memset(wIn, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS); - memset(wOut, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS); - - // Get copy of zero cache - memcpy(&Cache, &p ->Cache, sizeof(Cache)); - - for (i=0; i < n; i++) { - - accum = p -> FromInput(p, wIn, accum, Stride); - - if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { - memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); - } - else { - TransformOnePixelWithGamutCheck(p, wIn, wOut); - memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); - memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); - } - - output = p -> ToOutput(p, wOut, output, Stride); - } - -} - -// ------------------------------------------------------------------------------------------------------------- - -// List of used-defined transform factories -typedef struct _cmsTransformCollection_st { - - _cmsTransformFactory Factory; - struct _cmsTransformCollection_st *Next; - -} _cmsTransformCollection; - -// The linked list head -_cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL }; - - -// Duplicates the zone of memory used by the plug-in in the new context -static -void DupPluginTransformList(struct _cmsContext_struct* ctx, - const struct _cmsContext_struct* src) -{ - _cmsTransformPluginChunkType newHead = { NULL }; - _cmsTransformCollection* entry; - _cmsTransformCollection* Anterior = NULL; - _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin]; - - // Walk the list copying all nodes - for (entry = head->TransformCollection; - entry != NULL; - entry = entry ->Next) { - - _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection)); - - if (newEntry == NULL) - return; - - // We want to keep the linked list order, so this is a little bit tricky - newEntry -> Next = NULL; - if (Anterior) - Anterior -> Next = newEntry; - - Anterior = newEntry; - - if (newHead.TransformCollection == NULL) - newHead.TransformCollection = newEntry; - } - - ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType)); -} - -void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx, - const struct _cmsContext_struct* src) -{ - if (src != NULL) { - - // Copy all linked list - DupPluginTransformList(ctx, src); - } - else { - static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL }; - ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType)); - } -} - - - -// Register new ways to transform -cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data) -{ - cmsPluginTransform* Plugin = (cmsPluginTransform*) Data; - _cmsTransformCollection* fl; - _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin); - - if (Data == NULL) { - - // Free the chain. Memory is safely freed at exit - ctx->TransformCollection = NULL; - return TRUE; - } - - // Factory callback is required - if (Plugin ->Factory == NULL) return FALSE; - - - fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection)); - if (fl == NULL) return FALSE; - - // Copy the parameters - fl ->Factory = Plugin ->Factory; - - // Keep linked list - fl ->Next = ctx->TransformCollection; - ctx->TransformCollection = fl; - - // All is ok - return TRUE; -} - - -void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn) -{ - _cmsAssert(CMMcargo != NULL); - CMMcargo ->UserData = ptr; - CMMcargo ->FreeUserData = FreePrivateDataFn; -} - -// returns the pointer defined by the plug-in to store private data -void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo) -{ - _cmsAssert(CMMcargo != NULL); - return CMMcargo ->UserData; -} - -// returns the current formatters -void CMSEXPORT _cmsGetTransformFormatters16(struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput) -{ - _cmsAssert(CMMcargo != NULL); - if (FromInput) *FromInput = CMMcargo ->FromInput; - if (ToOutput) *ToOutput = CMMcargo ->ToOutput; -} - -void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput) -{ - _cmsAssert(CMMcargo != NULL); - if (FromInput) *FromInput = CMMcargo ->FromInputFloat; - if (ToOutput) *ToOutput = CMMcargo ->ToOutputFloat; -} - - -// Allocate transform struct and set it to defaults. Ask the optimization plug-in about if those formats are proper -// for separated transforms. If this is the case, -static -_cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, - cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) -{ - _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin); - _cmsTransformCollection* Plugin; - - // Allocate needed memory - _cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); - if (!p) { - cmsPipelineFree(lut); - return NULL; - } - - // Store the proposed pipeline - p ->Lut = lut; - - // Let's see if any plug-in want to do the transform by itself - for (Plugin = ctx ->TransformCollection; - Plugin != NULL; - Plugin = Plugin ->Next) { - - if (Plugin ->Factory(&p->xform, &p->UserData, &p ->FreeUserData, &p ->Lut, InputFormat, OutputFormat, dwFlags)) { - - // Last plugin in the declaration order takes control. We just keep - // the original parameters as a logging. - // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default - // an optimized transform is not reusable. The plug-in can, however, change - // the flags and make it suitable. - - p ->ContextID = ContextID; - p ->InputFormat = *InputFormat; - p ->OutputFormat = *OutputFormat; - p ->dwOriginalFlags = *dwFlags; - - // Fill the formatters just in case the optimized routine is interested. - // No error is thrown if the formatter doesn't exist. It is up to the optimization - // factory to decide what to do in those cases. - p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - - return p; - } - } - - // Not suitable for the transform plug-in, let's check the pipeline plug-in - if (p ->Lut != NULL) - _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags); - - // Check whatever this is a true floating point transform - if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) { - - // Get formatter function always return a valid union, but the contents of this union may be NULL. - p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; - - if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { - - cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); - cmsDeleteTransform(p); - return NULL; - } - - if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { - - p ->xform = NullFloatXFORM; - } - else { - // Float transforms don't use cach? always are non-NULL - p ->xform = FloatXFORM; - } - - } - else { - - if (*InputFormat == 0 && *OutputFormat == 0) { - p ->FromInput = p ->ToOutput = NULL; - *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; - } - else { - - int BytesPerPixelInput; - - p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; - - if (p ->FromInput == NULL || p ->ToOutput == NULL) { - - cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); - cmsDeleteTransform(p); - return NULL; - } - - BytesPerPixelInput = T_BYTES(p ->InputFormat); - if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2) - *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; - - } - - if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { - - p ->xform = NullXFORM; - } - else { - if (*dwFlags & cmsFLAGS_NOCACHE) { - - if (*dwFlags & cmsFLAGS_GAMUTCHECK) - p ->xform = PrecalculatedXFORMGamutCheck; // Gamut check, no cach? - else - p ->xform = PrecalculatedXFORM; // No cach? no gamut check - } - else { - - if (*dwFlags & cmsFLAGS_GAMUTCHECK) - p ->xform = CachedXFORMGamutCheck; // Gamut check, cach? - else - p ->xform = CachedXFORM; // No gamut check, cach? - } - } - } - - p ->InputFormat = *InputFormat; - p ->OutputFormat = *OutputFormat; - p ->dwOriginalFlags = *dwFlags; - p ->ContextID = ContextID; - p ->UserData = NULL; - return p; -} - -static -cmsBool GetXFormColorSpaces(int nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output) -{ - cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut; - cmsColorSpaceSignature PostColorSpace; - int i; - - if (nProfiles <= 0) return FALSE; - if (hProfiles[0] == NULL) return FALSE; - - *Input = PostColorSpace = cmsGetColorSpace(hProfiles[0]); - - for (i=0; i < nProfiles; i++) { - - cmsProfileClassSignature cls; - cmsHPROFILE hProfile = hProfiles[i]; - - int lIsInput = (PostColorSpace != cmsSigXYZData) && - (PostColorSpace != cmsSigLabData); - - if (hProfile == NULL) return FALSE; - - cls = cmsGetDeviceClass(hProfile); - - if (cls == cmsSigNamedColorClass) { - - ColorSpaceIn = cmsSig1colorData; - ColorSpaceOut = (nProfiles > 1) ? cmsGetPCS(hProfile) : cmsGetColorSpace(hProfile); - } - else - if (lIsInput || (cls == cmsSigLinkClass)) { - - ColorSpaceIn = cmsGetColorSpace(hProfile); - ColorSpaceOut = cmsGetPCS(hProfile); - } - else - { - ColorSpaceIn = cmsGetPCS(hProfile); - ColorSpaceOut = cmsGetColorSpace(hProfile); - } - - if (i==0) - *Input = ColorSpaceIn; - - PostColorSpace = ColorSpaceOut; - } - - *Output = PostColorSpace; - - return TRUE; -} - -// Check colorspace -static -cmsBool IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwFormat) -{ - int Space1 = T_COLORSPACE(dwFormat); - int Space2 = _cmsLCMScolorSpace(Check); - - if (Space1 == PT_ANY) return TRUE; - if (Space1 == Space2) return TRUE; - - if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE; - if (Space1 == PT_Lab && Space2 == PT_LabV2) return TRUE; - - return FALSE; -} - -// ---------------------------------------------------------------------------------------------------------------- - -static -void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src) -{ - if (src == NULL) { - wtPt ->X = cmsD50X; - wtPt ->Y = cmsD50Y; - wtPt ->Z = cmsD50Z; - } - else { - wtPt ->X = src->X; - wtPt ->Y = src->Y; - wtPt ->Z = src->Z; - } - -} - -// New to lcms 2.0 -- have all parameters available. -cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, - cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], - cmsBool BPC[], - cmsUInt32Number Intents[], - cmsFloat64Number AdaptationStates[], - cmsHPROFILE hGamutProfile, - cmsUInt32Number nGamutPCSposition, - cmsUInt32Number InputFormat, - cmsUInt32Number OutputFormat, - cmsUInt32Number dwFlags) -{ - _cmsTRANSFORM* xform; - cmsColorSpaceSignature EntryColorSpace; - cmsColorSpaceSignature ExitColorSpace; - cmsPipeline* Lut; - cmsUInt32Number LastIntent = Intents[nProfiles-1]; - - // If it is a fake transform - if (dwFlags & cmsFLAGS_NULLTRANSFORM) - { - return AllocEmptyTransform(ContextID, NULL, INTENT_PERCEPTUAL, &InputFormat, &OutputFormat, &dwFlags); - } - - // If gamut check is requested, make sure we have a gamut profile - if (dwFlags & cmsFLAGS_GAMUTCHECK) { - if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK; - } - - // On floating point transforms, inhibit cache - if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat)) - dwFlags |= cmsFLAGS_NOCACHE; - - // Mark entry/exit spaces - if (!GetXFormColorSpaces(nProfiles, hProfiles, &EntryColorSpace, &ExitColorSpace)) { - cmsSignalError(ContextID, cmsERROR_NULL, "NULL input profiles on transform"); - return NULL; - } - - // Check if proper colorspaces - if (!IsProperColorSpace(EntryColorSpace, InputFormat)) { - cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong input color space on transform"); - return NULL; - } - - if (!IsProperColorSpace(ExitColorSpace, OutputFormat)) { - cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong output color space on transform"); - return NULL; - } - - // Create a pipeline with all transformations - Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags); - if (Lut == NULL) { - cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Couldn't link the profiles"); - return NULL; - } - - // Check channel count - if ((cmsChannelsOf(EntryColorSpace) != cmsPipelineInputChannels(Lut)) || - (cmsChannelsOf(ExitColorSpace) != cmsPipelineOutputChannels(Lut))) { - cmsPipelineFree(Lut); - cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted"); - return NULL; - } - - - // All seems ok - xform = AllocEmptyTransform(ContextID, Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags); - if (xform == NULL) { - return NULL; - } - - // Keep values - xform ->EntryColorSpace = EntryColorSpace; - xform ->ExitColorSpace = ExitColorSpace; - xform ->RenderingIntent = Intents[nProfiles-1]; - - // Take white points - SetWhitePoint(&xform->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[0], cmsSigMediaWhitePointTag)); - SetWhitePoint(&xform->ExitWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[nProfiles-1], cmsSigMediaWhitePointTag)); - - - // Create a gamut check LUT if requested - if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK)) - xform ->GamutCheck = _cmsCreateGamutCheckPipeline(ContextID, hProfiles, - BPC, Intents, - AdaptationStates, - nGamutPCSposition, - hGamutProfile); - - - // Try to read input and output colorant table - if (cmsIsTag(hProfiles[0], cmsSigColorantTableTag)) { - - // Input table can only come in this way. - xform ->InputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[0], cmsSigColorantTableTag)); - } - - // Output is a little bit more complex. - if (cmsGetDeviceClass(hProfiles[nProfiles-1]) == cmsSigLinkClass) { - - // This tag may exist only on devicelink profiles. - if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)) { - - // It may be NULL if error - xform ->OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)); - } - - } else { - - if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)) { - - xform -> OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)); - } - } - - // Store the sequence of profiles - if (dwFlags & cmsFLAGS_KEEP_SEQUENCE) { - xform ->Sequence = _cmsCompileProfileSequence(ContextID, nProfiles, hProfiles); - } - else - xform ->Sequence = NULL; - - // If this is a cached transform, init first value, which is zero (16 bits only) - if (!(dwFlags & cmsFLAGS_NOCACHE)) { - - memset(&xform ->Cache.CacheIn, 0, sizeof(xform ->Cache.CacheIn)); - - if (xform ->GamutCheck != NULL) { - TransformOnePixelWithGamutCheck(xform, xform ->Cache.CacheIn, xform->Cache.CacheOut); - } - else { - - xform ->Lut ->Eval16Fn(xform ->Cache.CacheIn, xform->Cache.CacheOut, xform -> Lut->Data); - } - - } - - return (cmsHTRANSFORM) xform; -} - -// 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); -} - - - -cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[], - cmsUInt32Number nProfiles, - cmsUInt32Number InputFormat, - cmsUInt32Number OutputFormat, - cmsUInt32Number Intent, - cmsUInt32Number dwFlags) -{ - - if (nProfiles <= 0 || nProfiles > 255) { - cmsSignalError(NULL, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles); - return NULL; - } - - return cmsCreateMultiprofileTransformTHR(cmsGetProfileContextID(hProfiles[0]), - hProfiles, - nProfiles, - InputFormat, - OutputFormat, - Intent, - dwFlags); -} - -cmsHTRANSFORM CMSEXPORT cmsCreateTransformTHR(cmsContext ContextID, - cmsHPROFILE Input, - cmsUInt32Number InputFormat, - cmsHPROFILE Output, - cmsUInt32Number OutputFormat, - cmsUInt32Number Intent, - cmsUInt32Number dwFlags) -{ - - cmsHPROFILE hArray[2]; - - hArray[0] = Input; - hArray[1] = Output; - - return cmsCreateMultiprofileTransformTHR(ContextID, hArray, Output == NULL ? 1 : 2, InputFormat, OutputFormat, Intent, dwFlags); -} - -CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsHPROFILE Input, - cmsUInt32Number InputFormat, - cmsHPROFILE Output, - cmsUInt32Number OutputFormat, - cmsUInt32Number Intent, - cmsUInt32Number dwFlags) -{ - return cmsCreateTransformTHR(cmsGetProfileContextID(Input), Input, InputFormat, Output, OutputFormat, Intent, dwFlags); -} - - -cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransformTHR(cmsContext ContextID, - cmsHPROFILE InputProfile, - cmsUInt32Number InputFormat, - cmsHPROFILE OutputProfile, - cmsUInt32Number OutputFormat, - cmsHPROFILE ProofingProfile, - cmsUInt32Number nIntent, - cmsUInt32Number ProofingIntent, - cmsUInt32Number dwFlags) -{ - cmsHPROFILE hArray[4]; - cmsUInt32Number Intents[4]; - cmsBool BPC[4]; - cmsFloat64Number Adaptation[4]; - cmsBool DoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION) ? TRUE : FALSE; - - - hArray[0] = InputProfile; hArray[1] = ProofingProfile; hArray[2] = ProofingProfile; hArray[3] = OutputProfile; - Intents[0] = nIntent; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = ProofingIntent; - BPC[0] = DoBPC; BPC[1] = DoBPC; BPC[2] = 0; BPC[3] = 0; - - Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationStateTHR(ContextID, -1); - - if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK))) - return cmsCreateTransformTHR(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags); - - return cmsCreateExtendedTransform(ContextID, 4, hArray, BPC, Intents, Adaptation, - ProofingProfile, 1, InputFormat, OutputFormat, dwFlags); - -} - - -cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile, - cmsUInt32Number InputFormat, - cmsHPROFILE OutputProfile, - cmsUInt32Number OutputFormat, - cmsHPROFILE ProofingProfile, - cmsUInt32Number nIntent, - cmsUInt32Number ProofingIntent, - cmsUInt32Number dwFlags) -{ - return cmsCreateProofingTransformTHR(cmsGetProfileContextID(InputProfile), - InputProfile, - InputFormat, - OutputProfile, - OutputFormat, - ProofingProfile, - nIntent, - ProofingIntent, - dwFlags); -} - - -// Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed -cmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform) -{ - _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; - - if (xform == NULL) return NULL; - return xform -> ContextID; -} - -// Grab the input/output formats -cmsUInt32Number CMSEXPORT cmsGetTransformInputFormat(cmsHTRANSFORM hTransform) -{ - _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; - - if (xform == NULL) return 0; - return xform->InputFormat; -} - -cmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsHTRANSFORM hTransform) -{ - _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; - - if (xform == NULL) return 0; - return xform->OutputFormat; -} - -// 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; -} |