1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//--------------------------------------------------------------------------------- 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Little Color Management System 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Copyright (c) 1998-2014 Marti Maria Saguer 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Permission is hereby granted, free of charge, to any person obtaining 7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// a copy of this software and associated documentation files (the "Software"), 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// to deal in the Software without restriction, including without limitation 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// the rights to use, copy, modify, merge, publish, distribute, sublicense, 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// and/or sell copies of the Software, and to permit persons to whom the Software 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// is furnished to do so, subject to the following conditions: 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The above copyright notice and this permission notice shall be included in 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// all copies or substantial portions of the Software. 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//--------------------------------------------------------------------------------- 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "lcms2_internal.h" 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Transformations stuff 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ----------------------------------------------------------------------- 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The Context0 observer adaptation state. 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov_cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Init and duplicate observer adaptation state 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx, 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const struct _cmsContext_struct* src) 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* from; 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (src != NULL) { 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov from = src ->chunks[AdaptationStateContext]; 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov from = &AdaptationStateChunk; 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType)); 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Sets adaptation state for absolute colorimetric intent in the given context. Adaptation state applies on all 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// but cmsCreateExtendedTransformTHR(). Little CMS can handle incomplete adaptation states. 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d) 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFloat64Number prev; 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext); 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get previous value for return 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov prev = ptr ->AdaptationState; 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Set the value if d is positive or zero 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (d >= 0.0) { 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ptr ->AdaptationState = d; 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Always return previous value 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return prev; 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d) 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmsSetAdaptationStateTHR(NULL, d); 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ----------------------------------------------------------------------- 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Alarm codes for 16-bit transformations, because the fixed range of containers there are 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// no values left to mark out of gamut. 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov_cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// encoded in 16 bits. 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(ContextAlarmCodes != NULL); // Can't happen 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes)); 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context. 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Values are meant to be encoded in 16 bits. 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(ContextAlarmCodes != NULL); // Can't happen 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes)); 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]) 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(NewAlarm != NULL); 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSetAlarmCodesTHR(NULL, NewAlarm); 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number OldAlarm[cmsMAXCHANNELS]) 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(OldAlarm != NULL); 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsGetAlarmCodesTHR(NULL, OldAlarm); 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Init and duplicate alarm codes 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx, 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const struct _cmsContext_struct* src) 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* from; 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (src != NULL) { 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov from = src ->chunks[AlarmCodesContext]; 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov from = &AlarmCodesChunk; 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType)); 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ----------------------------------------------------------------------- 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Get rid of transform resources 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform) 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTRANSFORM* p = (_cmsTRANSFORM*) hTransform; 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(p != NULL); 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (p -> GamutCheck) 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPipelineFree(p -> GamutCheck); 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (p -> Lut) 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPipelineFree(p -> Lut); 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (p ->InputColorant) 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFreeNamedColorList(p ->InputColorant); 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (p -> OutputColorant) 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFreeNamedColorList(p ->OutputColorant); 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (p ->Sequence) 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFreeProfileSequenceDescription(p ->Sequence); 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (p ->UserData) 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->FreeUserData(p ->ContextID, p ->UserData); 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(p ->ContextID, (void *) p); 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Apply transform. 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform, 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const void* InputBuffer, 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* OutputBuffer, 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Size) 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p -> xform(p, InputBuffer, OutputBuffer, Size, Size); 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Apply transform. 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const void* InputBuffer, 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* OutputBuffer, 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Size, cmsUInt32Number Stride) 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p -> xform(p, InputBuffer, OutputBuffer, Size, Stride); 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Transform routines ---------------------------------------------------------------------------------------------------------- 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check. 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Note that because extended range, we can use a -1.0 value for out of gamut in this case. 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid FloatXFORM(_cmsTRANSFORM* p, 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const void* in, 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* out, cmsUInt32Number Size, cmsUInt32Number Stride) 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* accum; 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* output; 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS]; 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFloat32Number OutOfGamut; 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i, j; 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = (cmsUInt8Number*) in; 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = (cmsUInt8Number*) out; 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < Size; i++) { 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = p -> FromInputFloat(p, fIn, accum, Stride); 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Any gamut chack to do? 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (p ->GamutCheck != NULL) { 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Evaluate gamut marker. 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPipelineEvalFloat( fIn, &OutOfGamut, p ->GamutCheck); 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Is current color out of gamut? 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (OutOfGamut > 0.0) { 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Certainly, out of gamut 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (j=0; j < cmsMAXCHANNELS; j++) 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fOut[j] = -1.0; 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // No, proceed normally 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPipelineEvalFloat(fIn, fOut, p -> Lut); 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // No gamut check at all 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPipelineEvalFloat(fIn, fOut, p -> Lut); 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Back to asked representation 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = p -> ToOutputFloat(p, fOut, output, Stride); 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid NullFloatXFORM(_cmsTRANSFORM* p, 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const void* in, 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* out, 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Size, 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Stride) 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* accum; 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* output; 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFloat32Number fIn[cmsMAXCHANNELS]; 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i, n; 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = (cmsUInt8Number*) in; 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = (cmsUInt8Number*) out; 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = Size; 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < n; i++) { 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = p -> FromInputFloat(p, fIn, accum, Stride); 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = p -> ToOutputFloat(p, fIn, output, Stride); 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 16 bit precision ----------------------------------------------------------------------------------------------------------- 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Null transformation, only applies formatters. No cach?static 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid NullXFORM(_cmsTRANSFORM* p, 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const void* in, 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* out, cmsUInt32Number Size, 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Stride) 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* accum; 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* output; 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number wIn[cmsMAXCHANNELS]; 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i, n; 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = (cmsUInt8Number*) in; 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = (cmsUInt8Number*) out; 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = Size; // Buffer len 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < n; i++) { 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = p -> FromInput(p, wIn, accum, Stride); 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = p -> ToOutput(p, wIn, output, Stride); 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// No gamut check, no cache, 16 bits 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid PrecalculatedXFORM(_cmsTRANSFORM* p, 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const void* in, 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* out, cmsUInt32Number Size, cmsUInt32Number Stride) 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov register cmsUInt8Number* accum; 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov register cmsUInt8Number* output; 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i, n; 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = (cmsUInt8Number*) in; 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = (cmsUInt8Number*) out; 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = Size; 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < n; i++) { 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = p -> FromInput(p, wIn, accum, Stride); 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = p -> ToOutput(p, wOut, output, Stride); 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Auxiliar: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical. 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p, 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const cmsUInt16Number wIn[], 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number wOut[]) 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number wOutOfGamut; 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data); 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (wOutOfGamut >= 1) { 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number i; 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext); 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < p ->Lut->OutputChannels; i++) { 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov wOut[i] = ContextAlarmCodes ->AlarmCodes[i]; 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Gamut check, No cach? 16 bits. 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const void* in, 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* out, cmsUInt32Number Size, cmsUInt32Number Stride) 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* accum; 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* output; 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i, n; 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = (cmsUInt8Number*) in; 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = (cmsUInt8Number*) out; 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = Size; // Buffer len 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < n; i++) { 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = p -> FromInput(p, wIn, accum, Stride); 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TransformOnePixelWithGamutCheck(p, wIn, wOut); 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = p -> ToOutput(p, wOut, output, Stride); 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// No gamut check, Cach? 16 bits, 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CachedXFORM(_cmsTRANSFORM* p, 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const void* in, 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* out, cmsUInt32Number Size, cmsUInt32Number Stride) 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* accum; 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* output; 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i, n; 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsCACHE Cache; 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = (cmsUInt8Number*) in; 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = (cmsUInt8Number*) out; 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = Size; // Buffer len 387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Empty buffers for quick memcmp 389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memset(wIn, 0, sizeof(wIn)); 390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memset(wOut, 0, sizeof(wOut)); 391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get copy of zero cache 393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(&Cache, &p ->Cache, sizeof(Cache)); 394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < n; i++) { 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = p -> FromInput(p, wIn, accum, Stride); 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = p -> ToOutput(p, wOut, output, Stride); 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// All those nice features together 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CachedXFORMGamutCheck(_cmsTRANSFORM* p, 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const void* in, 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* out, cmsUInt32Number Size, cmsUInt32Number Stride) 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* accum; 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* output; 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i, n; 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsCACHE Cache; 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = (cmsUInt8Number*) in; 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = (cmsUInt8Number*) out; 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = Size; // Buffer len 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Empty buffers for quick memcmp 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memset(wIn, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS); 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memset(wOut, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS); 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get copy of zero cache 438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(&Cache, &p ->Cache, sizeof(Cache)); 439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < n; i++) { 441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov accum = p -> FromInput(p, wIn, accum, Stride); 443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TransformOnePixelWithGamutCheck(p, wIn, wOut); 449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); 450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); 451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output = p -> ToOutput(p, wOut, output, Stride); 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ------------------------------------------------------------------------------------------------------------- 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// List of used-defined transform factories 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct _cmsTransformCollection_st { 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTransformFactory Factory; 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov struct _cmsTransformCollection_st *Next; 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} _cmsTransformCollection; 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The linked list head 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov_cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL }; 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Duplicates the zone of memory used by the plug-in in the new context 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid DupPluginTransformList(struct _cmsContext_struct* ctx, 475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const struct _cmsContext_struct* src) 476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTransformPluginChunkType newHead = { NULL }; 478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTransformCollection* entry; 479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTransformCollection* Anterior = NULL; 480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin]; 481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Walk the list copying all nodes 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (entry = head->TransformCollection; 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov entry != NULL; 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov entry = entry ->Next) { 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection)); 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (newEntry == NULL) 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // We want to keep the linked list order, so this is a little bit tricky 493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov newEntry -> Next = NULL; 494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Anterior) 495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Anterior -> Next = newEntry; 496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Anterior = newEntry; 498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (newHead.TransformCollection == NULL) 500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov newHead.TransformCollection = newEntry; 501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType)); 504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx, 507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const struct _cmsContext_struct* src) 508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (src != NULL) { 510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Copy all linked list 512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov DupPluginTransformList(ctx, src); 513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL }; 516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType)); 517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Register new ways to transform 523ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data) 524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPluginTransform* Plugin = (cmsPluginTransform*) Data; 526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTransformCollection* fl; 527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin); 528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Data == NULL) { 530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Free the chain. Memory is safely freed at exit 532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->TransformCollection = NULL; 533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Factory callback is required 537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Plugin ->Factory == NULL) return FALSE; 538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection)); 541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (fl == NULL) return FALSE; 542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Copy the parameters 544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fl ->Factory = Plugin ->Factory; 545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Keep linked list 547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fl ->Next = ctx->TransformCollection; 548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ctx->TransformCollection = fl; 549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // All is ok 551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn) 556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(CMMcargo != NULL); 558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CMMcargo ->UserData = ptr; 559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CMMcargo ->FreeUserData = FreePrivateDataFn; 560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// returns the pointer defined by the plug-in to store private data 563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo) 564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(CMMcargo != NULL); 566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return CMMcargo ->UserData; 567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// returns the current formatters 570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT _cmsGetTransformFormatters16(struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput) 571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(CMMcargo != NULL); 573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (FromInput) *FromInput = CMMcargo ->FromInput; 574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ToOutput) *ToOutput = CMMcargo ->ToOutput; 575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput) 578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(CMMcargo != NULL); 580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (FromInput) *FromInput = CMMcargo ->FromInputFloat; 581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ToOutput) *ToOutput = CMMcargo ->ToOutputFloat; 582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Allocate transform struct and set it to defaults. Ask the optimization plug-in about if those formats are proper 586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// for separated transforms. If this is the case, 587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov_cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, 589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) 590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin); 592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTransformCollection* Plugin; 593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Allocate needed memory 595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); 596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!p) return NULL; 597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Store the proposed pipeline 599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->Lut = lut; 600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Let's see if any plug-in want to do the transform by itself 602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (Plugin = ctx ->TransformCollection; 603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Plugin != NULL; 604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Plugin = Plugin ->Next) { 605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Plugin ->Factory(&p->xform, &p->UserData, &p ->FreeUserData, &p ->Lut, InputFormat, OutputFormat, dwFlags)) { 607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Last plugin in the declaration order takes control. We just keep 609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // the original parameters as a logging. 610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default 611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // an optimized transform is not reusable. The plug-in can, however, change 612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // the flags and make it suitable. 613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->ContextID = ContextID; 615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->InputFormat = *InputFormat; 616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->OutputFormat = *OutputFormat; 617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->dwOriginalFlags = *dwFlags; 618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Fill the formatters just in case the optimized routine is interested. 620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // No error is thrown if the formatter doesn't exist. It is up to the optimization 621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // factory to decide what to do in those cases. 622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; 623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; 624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; 625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; 626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return p; 628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Not suitable for the transform plug-in, let's check the pipeline plug-in 632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (p ->Lut != NULL) 633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags); 634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Check whatever this is a true floating point transform 636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) { 637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get formatter function always return a valid union, but the contents of this union may be NULL. 639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; 640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; 641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; 642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { 644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); 646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(ContextID, p); 647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { 651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->xform = NullFloatXFORM; 653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Float transforms don't use cach? always are non-NULL 656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->xform = FloatXFORM; 657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (*InputFormat == 0 && *OutputFormat == 0) { 663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->FromInput = p ->ToOutput = NULL; 664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; 665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int BytesPerPixelInput; 669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; 671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; 672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (p ->FromInput == NULL || p ->ToOutput == NULL) { 674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); 676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(ContextID, p); 677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov BytesPerPixelInput = T_BYTES(p ->InputFormat); 681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2) 682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; 683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { 687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->xform = NullXFORM; 689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (*dwFlags & cmsFLAGS_NOCACHE) { 692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (*dwFlags & cmsFLAGS_GAMUTCHECK) 694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->xform = PrecalculatedXFORMGamutCheck; // Gamut check, no cach? else 695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->xform = PrecalculatedXFORM; // No cach? no gamut check 696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (*dwFlags & cmsFLAGS_GAMUTCHECK) 700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->xform = CachedXFORMGamutCheck; // Gamut check, cach? else 701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->xform = CachedXFORM; // No gamut check, cach? 702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->InputFormat = *InputFormat; 707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->OutputFormat = *OutputFormat; 708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->dwOriginalFlags = *dwFlags; 709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->ContextID = ContextID; 710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p ->UserData = NULL; 711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return p; 712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 715ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool GetXFormColorSpaces(int nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output) 716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut; 718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsColorSpaceSignature PostColorSpace; 719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i; 720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (nProfiles <= 0) return FALSE; 722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (hProfiles[0] == NULL) return FALSE; 723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *Input = PostColorSpace = cmsGetColorSpace(hProfiles[0]); 725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < nProfiles; i++) { 727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsProfileClassSignature cls; 729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hProfile = hProfiles[i]; 730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int lIsInput = (PostColorSpace != cmsSigXYZData) && 732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (PostColorSpace != cmsSigLabData); 733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (hProfile == NULL) return FALSE; 735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cls = cmsGetDeviceClass(hProfile); 737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (cls == cmsSigNamedColorClass) { 739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ColorSpaceIn = cmsSig1colorData; 741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ColorSpaceOut = (nProfiles > 1) ? cmsGetPCS(hProfile) : cmsGetColorSpace(hProfile); 742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (lIsInput || (cls == cmsSigLinkClass)) { 745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ColorSpaceIn = cmsGetColorSpace(hProfile); 747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ColorSpaceOut = cmsGetPCS(hProfile); 748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ColorSpaceIn = cmsGetPCS(hProfile); 752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ColorSpaceOut = cmsGetColorSpace(hProfile); 753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (i==0) 756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *Input = ColorSpaceIn; 757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PostColorSpace = ColorSpaceOut; 759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *Output = PostColorSpace; 762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Check colorspace 767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 768ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwFormat) 769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int Space1 = T_COLORSPACE(dwFormat); 771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int Space2 = _cmsLCMScolorSpace(Check); 772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Space1 == PT_ANY) return TRUE; 774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Space1 == Space2) return TRUE; 775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE; 777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Space1 == PT_Lab && Space2 == PT_LabV2) return TRUE; 778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ---------------------------------------------------------------------------------------------------------------- 783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src) 786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (src == NULL) { 788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov wtPt ->X = cmsD50X; 789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov wtPt ->Y = cmsD50Y; 790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov wtPt ->Z = cmsD50Z; 791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov wtPt ->X = src->X; 794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov wtPt ->Y = src->Y; 795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov wtPt ->Z = src->Z; 796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// New to lcms 2.0 -- have all parameters available. 801ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, 802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], 803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsBool BPC[], 804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intents[], 805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFloat64Number AdaptationStates[], 806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hGamutProfile, 807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number nGamutPCSposition, 808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number InputFormat, 809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number OutputFormat, 810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwFlags) 811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTRANSFORM* xform; 813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsColorSpaceSignature EntryColorSpace; 814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsColorSpaceSignature ExitColorSpace; 815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPipeline* Lut; 816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number LastIntent = Intents[nProfiles-1]; 817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // If it is a fake transform 819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (dwFlags & cmsFLAGS_NULLTRANSFORM) 820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return AllocEmptyTransform(ContextID, NULL, INTENT_PERCEPTUAL, &InputFormat, &OutputFormat, &dwFlags); 822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // If gamut check is requested, make sure we have a gamut profile 825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (dwFlags & cmsFLAGS_GAMUTCHECK) { 826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK; 827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // On floating point transforms, inhibit cache 830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat)) 831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dwFlags |= cmsFLAGS_NOCACHE; 832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Mark entry/exit spaces 834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!GetXFormColorSpaces(nProfiles, hProfiles, &EntryColorSpace, &ExitColorSpace)) { 835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_NULL, "NULL input profiles on transform"); 836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Check if proper colorspaces 840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!IsProperColorSpace(EntryColorSpace, InputFormat)) { 841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong input color space on transform"); 842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!IsProperColorSpace(ExitColorSpace, OutputFormat)) { 846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong output color space on transform"); 847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Create a pipeline with all transformations 851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags); 852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Lut == NULL) { 853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Couldn't link the profiles"); 854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Check channel count 858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ((cmsChannelsOf(EntryColorSpace) != cmsPipelineInputChannels(Lut)) || 859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (cmsChannelsOf(ExitColorSpace) != cmsPipelineOutputChannels(Lut))) { 860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPipelineFree(Lut); 861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted"); 862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // All seems ok 867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform = AllocEmptyTransform(ContextID, Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags); 868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (xform == NULL) { 869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Keep values 873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->EntryColorSpace = EntryColorSpace; 874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->ExitColorSpace = ExitColorSpace; 875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->RenderingIntent = Intents[nProfiles-1]; 876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Take white points 878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov SetWhitePoint(&xform->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[0], cmsSigMediaWhitePointTag)); 879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov SetWhitePoint(&xform->ExitWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[nProfiles-1], cmsSigMediaWhitePointTag)); 880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Create a gamut check LUT if requested 883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK)) 884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->GamutCheck = _cmsCreateGamutCheckPipeline(ContextID, hProfiles, 885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov BPC, Intents, 886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov AdaptationStates, 887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nGamutPCSposition, 888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hGamutProfile); 889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Try to read input and output colorant table 892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (cmsIsTag(hProfiles[0], cmsSigColorantTableTag)) { 893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Input table can only come in this way. 895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->InputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[0], cmsSigColorantTableTag)); 896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Output is a little bit more complex. 899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (cmsGetDeviceClass(hProfiles[nProfiles-1]) == cmsSigLinkClass) { 900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // This tag may exist only on devicelink profiles. 902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)) { 903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // It may be NULL if error 905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)); 906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)) { 911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform -> OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)); 913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Store the sequence of profiles 917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (dwFlags & cmsFLAGS_KEEP_SEQUENCE) { 918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->Sequence = _cmsCompileProfileSequence(ContextID, nProfiles, hProfiles); 919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->Sequence = NULL; 922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // If this is a cached transform, init first value, which is zero (16 bits only) 924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!(dwFlags & cmsFLAGS_NOCACHE)) { 925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memset(&xform ->Cache.CacheIn, 0, sizeof(xform ->Cache.CacheIn)); 927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (xform ->GamutCheck != NULL) { 929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TransformOnePixelWithGamutCheck(xform, xform ->Cache.CacheIn, xform->Cache.CacheOut); 930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->Lut ->Eval16Fn(xform ->Cache.CacheIn, xform->Cache.CacheOut, xform -> Lut->Data); 934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (cmsHTRANSFORM) xform; 939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Multiprofile transforms: Gamut check is not available here, as it is unclear from which profile the gamut comes. 942ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransformTHR(cmsContext ContextID, 943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hProfiles[], 944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number nProfiles, 945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number InputFormat, 946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number OutputFormat, 947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intent, 948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwFlags) 949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i; 951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsBool BPC[256]; 952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intents[256]; 953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFloat64Number AdaptationStates[256]; 954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (nProfiles <= 0 || nProfiles > 255) { 956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles); 957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < nProfiles; i++) { 961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE; 962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Intents[i] = Intent; 963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov AdaptationStates[i] = cmsSetAdaptationStateTHR(ContextID, -1); 964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmsCreateExtendedTransform(ContextID, nProfiles, hProfiles, BPC, Intents, AdaptationStates, NULL, 0, InputFormat, OutputFormat, dwFlags); 968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 972ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[], 973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number nProfiles, 974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number InputFormat, 975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number OutputFormat, 976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intent, 977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwFlags) 978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (nProfiles <= 0 || nProfiles > 255) { 981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(NULL, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles); 982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmsCreateMultiprofileTransformTHR(cmsGetProfileContextID(hProfiles[0]), 986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hProfiles, 987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nProfiles, 988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov InputFormat, 989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov OutputFormat, 990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Intent, 991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dwFlags); 992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 994ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHTRANSFORM CMSEXPORT cmsCreateTransformTHR(cmsContext ContextID, 995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE Input, 996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number InputFormat, 997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE Output, 998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number OutputFormat, 999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intent, 1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwFlags) 1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hArray[2]; 1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hArray[0] = Input; 1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hArray[1] = Output; 1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmsCreateMultiprofileTransformTHR(ContextID, hArray, Output == NULL ? 1 : 2, InputFormat, OutputFormat, Intent, dwFlags); 1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsHPROFILE Input, 1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number InputFormat, 1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE Output, 1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number OutputFormat, 1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intent, 1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwFlags) 1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmsCreateTransformTHR(cmsGetProfileContextID(Input), Input, InputFormat, Output, OutputFormat, Intent, dwFlags); 1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHTRANSFORM CMSEXPORT cmsCreateProofingTransformTHR(cmsContext ContextID, 1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE InputProfile, 1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number InputFormat, 1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE OutputProfile, 1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number OutputFormat, 1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE ProofingProfile, 1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number nIntent, 1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number ProofingIntent, 1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwFlags) 1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hArray[4]; 1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intents[4]; 1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsBool BPC[4]; 1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFloat64Number Adaptation[4]; 1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsBool DoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION) ? TRUE : FALSE; 1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hArray[0] = InputProfile; hArray[1] = ProofingProfile; hArray[2] = ProofingProfile; hArray[3] = OutputProfile; 1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Intents[0] = nIntent; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = ProofingIntent; 1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov BPC[0] = DoBPC; BPC[1] = DoBPC; BPC[2] = 0; BPC[3] = 0; 1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationStateTHR(ContextID, -1); 1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK))) 1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmsCreateTransformTHR(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags); 1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmsCreateExtendedTransform(ContextID, 4, hArray, BPC, Intents, Adaptation, 1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ProofingProfile, 1, InputFormat, OutputFormat, dwFlags); 1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHTRANSFORM CMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile, 1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number InputFormat, 1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE OutputProfile, 1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number OutputFormat, 1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE ProofingProfile, 1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number nIntent, 1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number ProofingIntent, 1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwFlags) 1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmsCreateProofingTransformTHR(cmsGetProfileContextID(InputProfile), 1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov InputProfile, 1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov InputFormat, 1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov OutputProfile, 1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov OutputFormat, 1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ProofingProfile, 1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nIntent, 1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ProofingIntent, 1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dwFlags); 1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed 1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform) 1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; 1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (xform == NULL) return NULL; 1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return xform -> ContextID; 1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Grab the input/output formats 1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetTransformInputFormat(cmsHTRANSFORM hTransform) 1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; 1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (xform == NULL) return 0; 1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return xform->InputFormat; 1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsHTRANSFORM hTransform) 1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; 1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (xform == NULL) return 0; 1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return xform->OutputFormat; 1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// For backwards compatibility 1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform, 1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number InputFormat, 1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number OutputFormat) 1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; 1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFormatter16 FromInput, ToOutput; 1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // We only can afford to change formatters if previous transform is at least 16 bits 1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!(xform ->dwOriginalFlags & cmsFLAGS_CAN_CHANGE_FORMATTER)) { 1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(xform ->ContextID, cmsERROR_NOT_SUITABLE, "cmsChangeBuffersFormat works only on transforms created originally with at least 16 bits of precision"); 1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FromInput = _cmsGetFormatter(xform->ContextID, InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; 1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ToOutput = _cmsGetFormatter(xform->ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; 1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (FromInput == NULL || ToOutput == NULL) { 1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(xform -> ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); 1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->InputFormat = InputFormat; 1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->OutputFormat = OutputFormat; 1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->FromInput = FromInput; 1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform ->ToOutput = ToOutput; 1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1133