3 // Little Color Management System
4 // Copyright (c) 1998-2023 Marti Maria Saguer
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the Software
11 // is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 //---------------------------------------------------------------------------------
27 #ifndef _lcms_internal_H
29 // Include plug-in foundation
30 #ifndef _lcms_plugin_H
31 # include "lcms2_plugin.h"
34 // ctype is part of C99 as per 7.1.2
37 // assert macro is part of C99 as per 7.2
40 // Some needed constants
42 # define M_PI 3.14159265358979323846
46 # define M_LOG10E 0.434294481903251827651
49 // BorlandC 5.5, VC2003 are broken on that
50 #if defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER < 1400)) // 1400 == VC++ 8.0
51 #define sinf(x) (float)sin((float)x)
52 #define sqrtf(x) (float)sqrt((float)x)
56 // Alignment of ICC file format uses 4 bytes (cmsUInt32Number)
57 #define _cmsALIGNLONG(x) (((x)+(sizeof(cmsUInt32Number)-1)) & ~(sizeof(cmsUInt32Number)-1))
59 // Alignment to memory pointer
61 // (Ultra)SPARC with gcc requires ptr alignment of 8 bytes
62 // even though sizeof(void *) is only four: for greatest flexibility
63 // allow the build to specify ptr alignment.
64 #ifndef CMS_PTR_ALIGNMENT
65 # define CMS_PTR_ALIGNMENT sizeof(void *)
68 #define _cmsALIGNMEM(x) (((x)+(CMS_PTR_ALIGNMENT - 1)) & ~(CMS_PTR_ALIGNMENT - 1))
70 // Maximum encodeable values in floating point
71 #define MAX_ENCODEABLE_XYZ (1.0 + 32767.0/32768.0)
72 #define MIN_ENCODEABLE_ab2 (-128.0)
73 #define MAX_ENCODEABLE_ab2 ((65535.0/256.0) - 128.0)
74 #define MIN_ENCODEABLE_ab4 (-128.0)
75 #define MAX_ENCODEABLE_ab4 (127.0)
77 // Maximum of channels for internal pipeline evaluation
78 #define MAX_STAGE_CHANNELS 128
80 // Unused parameter warning suppression
81 #define cmsUNUSED_PARAMETER(x) ((void)x)
83 // The specification for "inline" is section 6.7.4 of the C99 standard (ISO/IEC 9899:1999).
84 // unfortunately VisualC++ does not conform that
85 #if defined(_MSC_VER) || defined(__BORLANDC__)
86 # define cmsINLINE __inline
88 # define cmsINLINE static inline
91 // Allow signed overflow, we know this is harmless in this particular context
92 #if defined(__clang__)
93 # define CMS_NO_SANITIZE __attribute__((no_sanitize("signed-integer-overflow")))
95 # define CMS_NO_SANITIZE
98 // Other replacement functions
101 # define snprintf _snprintf
104 # define vsnprintf _vsnprintf
107 /// Properly define some macros to accommodate
108 /// older MSVC versions.
109 # if defined(_MSC_VER) && _MSC_VER <= 1700
112 #define isinf(x) (!_finite((x)))
115 #if !defined(_MSC_VER) && (defined(__STDC_VERSION__) && __STDC_VERSION__ < 199901L)
117 #define isinf(x) (!finite((x)))
124 // A fast way to convert from/to 16 <-> 8 bits
125 #define FROM_8_TO_16(rgb) (cmsUInt16Number) ((((cmsUInt16Number) (rgb)) << 8)|(rgb))
126 #define FROM_16_TO_8(rgb) (cmsUInt8Number) ((((cmsUInt32Number)(rgb) * 65281U + 8388608U) >> 24) & 0xFFU)
128 // Code analysis is broken on asserts
130 # if (_MSC_VER >= 1500)
131 # define _cmsAssert(a) { assert((a)); __analysis_assume((a)); }
133 # define _cmsAssert(a) assert((a))
136 # define _cmsAssert(a) assert((a))
139 //---------------------------------------------------------------------------------
141 // Determinant lower than that are assumed zero (used on matrix invert)
142 #define MATRIX_DET_TOLERANCE 0.0001
144 //---------------------------------------------------------------------------------
147 #define FIXED_TO_INT(x) ((x)>>16)
148 #define FIXED_REST_TO_INT(x) ((x)&0xFFFFU)
149 #define ROUND_FIXED_TO_INT(x) (((x)+0x8000)>>16)
151 cmsINLINE cmsS15Fixed16Number
_cmsToFixedDomain(int a
) { return a
+ ((a
+ 0x7fff) / 0xffff); }
152 cmsINLINE
int _cmsFromFixedDomain(cmsS15Fixed16Number a
) { return a
- ((a
+ 0x7fff) >> 16); }
154 // -----------------------------------------------------------------------------------------------------------
156 // Fast floor conversion logic. Thanks to Sree Kotay and Stuart Nixon
157 // note than this only works in the range ..-32767...+32767 because
158 // mantissa is interpreted as 15.16 fixed point.
159 // The union is to avoid pointer aliasing overoptimization.
160 cmsINLINE
int _cmsQuickFloor(cmsFloat64Number val
)
162 #ifdef CMS_DONT_USE_FAST_FLOOR
163 return (int) floor(val
);
165 const cmsFloat64Number _lcms_double2fixmagic
= 68719476736.0 * 1.5; // 2^36 * 1.5, (52-16=36) uses limited precision to floor
167 cmsFloat64Number val
;
171 temp
.val
= val
+ _lcms_double2fixmagic
;
173 #ifdef CMS_USE_BIG_ENDIAN
174 return temp
.halves
[1] >> 16;
176 return temp
.halves
[0] >> 16;
181 // Fast floor restricted to 0..65535.0
182 cmsINLINE cmsUInt16Number
_cmsQuickFloorWord(cmsFloat64Number d
)
184 return (cmsUInt16Number
) _cmsQuickFloor(d
- 32767.0) + 32767U;
187 // Floor to word, taking care of saturation
188 cmsINLINE cmsUInt16Number
_cmsQuickSaturateWord(cmsFloat64Number d
)
191 if (d
<= 0) return 0;
192 if (d
>= 65535.0) return 0xffff;
194 return _cmsQuickFloorWord(d
);
197 // Test bed entry points---------------------------------------------------------------
198 #define CMSCHECKPOINT CMSAPI
200 // Pthread support --------------------------------------------------------------------
201 #ifndef CMS_NO_PTHREADS
203 // This is the threading support. Unfortunately, it has to be platform-dependent because
204 // windows does not support pthreads.
205 #ifdef CMS_IS_WINDOWS_
207 #define WIN32_LEAN_AND_MEAN 1
211 // The locking scheme in LCMS requires a single 'top level' mutex
212 // to work. This is actually implemented on Windows as a
213 // CriticalSection, because they are lighter weight. With
214 // pthreads, this is statically inited. Unfortunately, windows
215 // can't officially statically init critical sections.
217 // We can work around this in 2 ways.
219 // 1) We can use a proper mutex purely to protect the init
220 // of the CriticalSection. This in turns requires us to protect
221 // the Mutex creation, which we can do using the snappily
222 // named InterlockedCompareExchangePointer API (present on
223 // windows XP and above).
225 // 2) In cases where we want to work on pre-Windows XP, we
226 // can use an even more horrible hack described below.
228 // So why wouldn't we always use 2)? Because not calling
229 // the init function for a critical section means it fails
230 // testing with ApplicationVerifier (and presumably similar
233 // We therefore default to 1, and people who want to be able
234 // to run on pre-Windows XP boxes can build with:
235 // CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
236 // defined. This is automatically set for builds using
237 // versions of MSVC that don't have this API available.
239 // From: http://locklessinc.com/articles/pthreads_on_windows/
240 // The pthreads API has an initialization macro that has no correspondence to anything in
241 // the windows API. By investigating the internal definition of the critical section type,
242 // one may work out how to initialize one without calling InitializeCriticalSection().
243 // The trick here is that InitializeCriticalSection() is not allowed to fail. It tries
244 // to allocate a critical section debug object, but if no memory is available, it sets
245 // the pointer to a specific value. (One would expect that value to be NULL, but it is
246 // actually (void *)-1 for some reason.) Thus we can use this special value for that
247 // pointer, and the critical section code will work.
249 // The other important part of the critical section type to initialize is the number
250 // of waiters. This controls whether or not the mutex is locked. Fortunately, this
251 // part of the critical section is unlikely to change. Apparently, many programs
252 // already test critical sections to see if they are locked using this value, so
253 // Microsoft felt that it was necessary to keep it set at -1 for an unlocked critical
254 // section, even when they changed the underlying algorithm to be more scalable.
255 // The final parts of the critical section object are unimportant, and can be set
256 // to zero for their defaults. This yields to an initialization macro:
258 typedef CRITICAL_SECTION _cmsMutex
;
261 # if (_MSC_VER >= 1800)
262 # pragma warning(disable : 26135)
266 #ifndef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
267 // If we are building with a version of MSVC smaller
268 // than 1400 (i.e. before VS2005) then we don't have
269 // the InterlockedCompareExchangePointer API, so use
273 # define CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
278 #ifdef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
279 # define CMS_MUTEX_INITIALIZER {(PRTL_CRITICAL_SECTION_DEBUG) -1,-1,0,0,0,0}
281 # define CMS_MUTEX_INITIALIZER {(PRTL_CRITICAL_SECTION_DEBUG)NULL,-1,0,0,0,0}
284 cmsINLINE
int _cmsLockPrimitive(_cmsMutex
*m
)
286 EnterCriticalSection(m
);
290 cmsINLINE
int _cmsUnlockPrimitive(_cmsMutex
*m
)
292 LeaveCriticalSection(m
);
296 cmsINLINE
int _cmsInitMutexPrimitive(_cmsMutex
*m
)
298 InitializeCriticalSection(m
);
302 cmsINLINE
int _cmsDestroyMutexPrimitive(_cmsMutex
*m
)
304 DeleteCriticalSection(m
);
308 cmsINLINE
int _cmsEnterCriticalSectionPrimitive(_cmsMutex
*m
)
310 EnterCriticalSection(m
);
314 cmsINLINE
int _cmsLeaveCriticalSectionPrimitive(_cmsMutex
*m
)
316 LeaveCriticalSection(m
);
322 // Rest of the wide world
325 #define CMS_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
326 typedef pthread_mutex_t _cmsMutex
;
329 cmsINLINE
int _cmsLockPrimitive(_cmsMutex
*m
)
331 return pthread_mutex_lock(m
);
334 cmsINLINE
int _cmsUnlockPrimitive(_cmsMutex
*m
)
336 return pthread_mutex_unlock(m
);
339 cmsINLINE
int _cmsInitMutexPrimitive(_cmsMutex
*m
)
341 return pthread_mutex_init(m
, NULL
);
344 cmsINLINE
int _cmsDestroyMutexPrimitive(_cmsMutex
*m
)
346 return pthread_mutex_destroy(m
);
349 cmsINLINE
int _cmsEnterCriticalSectionPrimitive(_cmsMutex
*m
)
351 return pthread_mutex_lock(m
);
354 cmsINLINE
int _cmsLeaveCriticalSectionPrimitive(_cmsMutex
*m
)
356 return pthread_mutex_unlock(m
);
362 #define CMS_MUTEX_INITIALIZER 0
363 typedef int _cmsMutex
;
366 cmsINLINE
int _cmsLockPrimitive(_cmsMutex
*m
)
368 cmsUNUSED_PARAMETER(m
);
372 cmsINLINE
int _cmsUnlockPrimitive(_cmsMutex
*m
)
374 cmsUNUSED_PARAMETER(m
);
378 cmsINLINE
int _cmsInitMutexPrimitive(_cmsMutex
*m
)
380 cmsUNUSED_PARAMETER(m
);
384 cmsINLINE
int _cmsDestroyMutexPrimitive(_cmsMutex
*m
)
386 cmsUNUSED_PARAMETER(m
);
390 cmsINLINE
int _cmsEnterCriticalSectionPrimitive(_cmsMutex
*m
)
392 cmsUNUSED_PARAMETER(m
);
396 cmsINLINE
int _cmsLeaveCriticalSectionPrimitive(_cmsMutex
*m
)
398 cmsUNUSED_PARAMETER(m
);
403 // Plug-In registration ---------------------------------------------------------------
405 // Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once.
406 void* _cmsPluginMalloc(cmsContext ContextID
, cmsUInt32Number size
);
409 cmsBool
_cmsRegisterMemHandlerPlugin(cmsContext ContextID
, cmsPluginBase
* Plugin
);
412 cmsBool
_cmsRegisterInterpPlugin(cmsContext ContextID
, cmsPluginBase
* Plugin
);
415 cmsBool
_cmsRegisterParametricCurvesPlugin(cmsContext ContextID
, cmsPluginBase
* Plugin
);
417 // Formatters management
418 cmsBool
_cmsRegisterFormattersPlugin(cmsContext ContextID
, cmsPluginBase
* Plugin
);
420 // Tag type management
421 cmsBool
_cmsRegisterTagTypePlugin(cmsContext ContextID
, cmsPluginBase
* Plugin
);
424 cmsBool
_cmsRegisterTagPlugin(cmsContext ContextID
, cmsPluginBase
* Plugin
);
427 cmsBool
_cmsRegisterRenderingIntentPlugin(cmsContext ContextID
, cmsPluginBase
* Plugin
);
429 // Multi Process elements
430 cmsBool
_cmsRegisterMultiProcessElementPlugin(cmsContext ContextID
, cmsPluginBase
* Plugin
);
433 cmsBool
_cmsRegisterOptimizationPlugin(cmsContext ContextID
, cmsPluginBase
* Plugin
);
436 cmsBool
_cmsRegisterTransformPlugin(cmsContext ContextID
, cmsPluginBase
* Plugin
);
439 cmsBool
_cmsRegisterMutexPlugin(cmsContext ContextID
, cmsPluginBase
* Plugin
);
442 cmsBool
_cmsRegisterParallelizationPlugin(cmsContext ContextID
, cmsPluginBase
* Plugin
);
444 // ---------------------------------------------------------------------------------------------------------
447 typedef struct _cmsSubAllocator_chunk_st
{
449 cmsUInt8Number
* Block
;
450 cmsUInt32Number BlockSize
;
451 cmsUInt32Number Used
;
453 struct _cmsSubAllocator_chunk_st
* next
;
455 } _cmsSubAllocator_chunk
;
460 cmsContext ContextID
;
461 _cmsSubAllocator_chunk
* h
;
466 _cmsSubAllocator
* _cmsCreateSubAlloc(cmsContext ContextID
, cmsUInt32Number Initial
);
467 void _cmsSubAllocDestroy(_cmsSubAllocator
* s
);
468 void* _cmsSubAlloc(_cmsSubAllocator
* s
, cmsUInt32Number size
);
469 void* _cmsSubAllocDup(_cmsSubAllocator
* s
, const void *ptr
, cmsUInt32Number size
);
471 // ----------------------------------------------------------------------------------
473 // The context clients.
476 UserPtr
, // User-defined pointer
479 AdaptationStateContext
,
491 ParallelizationPlugin
,
499 // Container for memory management plug-in.
502 _cmsMallocFnPtrType MallocPtr
;
503 _cmsMalloZerocFnPtrType MallocZeroPtr
;
504 _cmsFreeFnPtrType FreePtr
;
505 _cmsReallocFnPtrType ReallocPtr
;
506 _cmsCallocFnPtrType CallocPtr
;
507 _cmsDupFnPtrType DupPtr
;
509 } _cmsMemPluginChunkType
;
511 // Copy memory management function pointers from plug-in to chunk, taking care of missing routines
512 void _cmsInstallAllocFunctions(cmsPluginMemHandler
* Plugin
, _cmsMemPluginChunkType
* ptr
);
514 // Internal structure for context
515 struct _cmsContext_struct
{
517 struct _cmsContext_struct
* Next
; // Points to next context in the new style
518 _cmsSubAllocator
* MemPool
; // The memory pool that stores context data
520 void* chunks
[MemoryClientMax
]; // array of pointers to client chunks. Memory itself is hold in the suballocator.
521 // If NULL, then it reverts to global Context0
523 _cmsMemPluginChunkType DefaultMemoryManager
; // The allocators used for creating the context itself. Cannot be overridden
526 // Returns a pointer to a valid context structure, including the global one if id is zero.
527 // Verifies the magic number.
528 struct _cmsContext_struct
* _cmsGetContext(cmsContext ContextID
);
530 // Returns the block assigned to the specific zone.
531 void* _cmsContextGetClientChunk(cmsContext id
, _cmsMemoryClient mc
);
534 // Chunks of context memory by plug-in client -------------------------------------------------------
536 // Those structures encapsulates all variables needed by the several context clients (mostly plug-ins)
538 // Container for error logger -- not a plug-in
541 cmsLogErrorHandlerFunction LogErrorHandler
; // Set to NULL for Context0 fallback
543 } _cmsLogErrorChunkType
;
545 // The global Context0 storage for error logger
546 extern _cmsLogErrorChunkType _cmsLogErrorChunk
;
548 // Allocate and init error logger container.
549 void _cmsAllocLogErrorChunk(struct _cmsContext_struct
* ctx
,
550 const struct _cmsContext_struct
* src
);
552 // Container for alarm codes -- not a plug-in
555 cmsUInt16Number AlarmCodes
[cmsMAXCHANNELS
];
557 } _cmsAlarmCodesChunkType
;
559 // The global Context0 storage for alarm codes
560 extern _cmsAlarmCodesChunkType _cmsAlarmCodesChunk
;
562 // Allocate and init alarm codes container.
563 void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct
* ctx
,
564 const struct _cmsContext_struct
* src
);
566 // Container for adaptation state -- not a plug-in
569 cmsFloat64Number AdaptationState
;
571 } _cmsAdaptationStateChunkType
;
573 // The global Context0 storage for adaptation state
574 extern _cmsAdaptationStateChunkType _cmsAdaptationStateChunk
;
576 // Allocate and init adaptation state container.
577 void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct
* ctx
,
578 const struct _cmsContext_struct
* src
);
581 // The global Context0 storage for memory management
582 extern _cmsMemPluginChunkType _cmsMemPluginChunk
;
584 // Allocate and init memory management container.
585 void _cmsAllocMemPluginChunk(struct _cmsContext_struct
* ctx
,
586 const struct _cmsContext_struct
* src
);
588 // Container for interpolation plug-in
591 cmsInterpFnFactory Interpolators
;
593 } _cmsInterpPluginChunkType
;
595 // The global Context0 storage for interpolation plug-in
596 extern _cmsInterpPluginChunkType _cmsInterpPluginChunk
;
598 // Allocate and init interpolation container.
599 void _cmsAllocInterpPluginChunk(struct _cmsContext_struct
* ctx
,
600 const struct _cmsContext_struct
* src
);
602 // Container for parametric curves plug-in
605 struct _cmsParametricCurvesCollection_st
* ParametricCurves
;
607 } _cmsCurvesPluginChunkType
;
609 // The global Context0 storage for tone curves plug-in
610 extern _cmsCurvesPluginChunkType _cmsCurvesPluginChunk
;
612 // Allocate and init parametric curves container.
613 void _cmsAllocCurvesPluginChunk(struct _cmsContext_struct
* ctx
,
614 const struct _cmsContext_struct
* src
);
616 // Container for formatters plug-in
619 struct _cms_formatters_factory_list
* FactoryList
;
621 } _cmsFormattersPluginChunkType
;
623 // The global Context0 storage for formatters plug-in
624 extern _cmsFormattersPluginChunkType _cmsFormattersPluginChunk
;
626 // Allocate and init formatters container.
627 void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct
* ctx
,
628 const struct _cmsContext_struct
* src
);
630 // This chunk type is shared by TagType plug-in and MPE Plug-in
633 struct _cmsTagTypeLinkedList_st
* TagTypes
;
635 } _cmsTagTypePluginChunkType
;
638 // The global Context0 storage for tag types plug-in
639 extern _cmsTagTypePluginChunkType _cmsTagTypePluginChunk
;
642 // The global Context0 storage for mult process elements plug-in
643 extern _cmsTagTypePluginChunkType _cmsMPETypePluginChunk
;
645 // Allocate and init Tag types container.
646 void _cmsAllocTagTypePluginChunk(struct _cmsContext_struct
* ctx
,
647 const struct _cmsContext_struct
* src
);
648 // Allocate and init MPE container.
649 void _cmsAllocMPETypePluginChunk(struct _cmsContext_struct
* ctx
,
650 const struct _cmsContext_struct
* src
);
651 // Container for tag plug-in
654 struct _cmsTagLinkedList_st
* Tag
;
656 } _cmsTagPluginChunkType
;
659 // The global Context0 storage for tag plug-in
660 extern _cmsTagPluginChunkType _cmsTagPluginChunk
;
662 // Allocate and init Tag container.
663 void _cmsAllocTagPluginChunk(struct _cmsContext_struct
* ctx
,
664 const struct _cmsContext_struct
* src
);
666 // Container for intents plug-in
669 struct _cms_intents_list
* Intents
;
671 } _cmsIntentsPluginChunkType
;
674 // The global Context0 storage for intents plug-in
675 extern _cmsIntentsPluginChunkType _cmsIntentsPluginChunk
;
677 // Allocate and init intents container.
678 void _cmsAllocIntentsPluginChunk(struct _cmsContext_struct
* ctx
,
679 const struct _cmsContext_struct
* src
);
681 // Container for optimization plug-in
684 struct _cmsOptimizationCollection_st
* OptimizationCollection
;
686 } _cmsOptimizationPluginChunkType
;
689 // The global Context0 storage for optimizers plug-in
690 extern _cmsOptimizationPluginChunkType _cmsOptimizationPluginChunk
;
692 // Allocate and init optimizers container.
693 void _cmsAllocOptimizationPluginChunk(struct _cmsContext_struct
* ctx
,
694 const struct _cmsContext_struct
* src
);
696 // Container for transform plug-in
699 struct _cmsTransformCollection_st
* TransformCollection
;
701 } _cmsTransformPluginChunkType
;
703 // The global Context0 storage for full-transform replacement plug-in
704 extern _cmsTransformPluginChunkType _cmsTransformPluginChunk
;
706 // Allocate and init transform container.
707 void _cmsAllocTransformPluginChunk(struct _cmsContext_struct
* ctx
,
708 const struct _cmsContext_struct
* src
);
710 // Container for mutex plug-in
713 _cmsCreateMutexFnPtrType CreateMutexPtr
;
714 _cmsDestroyMutexFnPtrType DestroyMutexPtr
;
715 _cmsLockMutexFnPtrType LockMutexPtr
;
716 _cmsUnlockMutexFnPtrType UnlockMutexPtr
;
718 } _cmsMutexPluginChunkType
;
720 // The global Context0 storage for mutex plug-in
721 extern _cmsMutexPluginChunkType _cmsMutexPluginChunk
;
723 // Allocate and init mutex container.
724 void _cmsAllocMutexPluginChunk(struct _cmsContext_struct
* ctx
,
725 const struct _cmsContext_struct
* src
);
727 // Container for parallelization plug-in
730 cmsInt32Number MaxWorkers
; // Number of workers to do as maximum
731 cmsInt32Number WorkerFlags
; // reserved
732 _cmsTransform2Fn SchedulerFn
; // callback to setup functions
734 } _cmsParallelizationPluginChunkType
;
736 // The global Context0 storage for parallelization plug-in
737 extern _cmsParallelizationPluginChunkType _cmsParallelizationPluginChunk
;
739 // Allocate parallelization container.
740 void _cmsAllocParallelizationPluginChunk(struct _cmsContext_struct
* ctx
,
741 const struct _cmsContext_struct
* src
);
745 // ----------------------------------------------------------------------------------
746 // MLU internal representation
749 cmsUInt16Number Language
;
750 cmsUInt16Number Country
;
752 cmsUInt32Number StrW
; // Offset to current unicode string
753 cmsUInt32Number Len
; // Length in bytes
757 struct _cms_MLU_struct
{
759 cmsContext ContextID
;
762 cmsUInt32Number AllocatedEntries
;
763 cmsUInt32Number UsedEntries
;
764 _cmsMLUentry
* Entries
; // Array of pointers to strings allocated in MemPool
767 cmsUInt32Number PoolSize
; // The maximum allocated size
768 cmsUInt32Number PoolUsed
; // The used size
769 void* MemPool
; // Pointer to begin of memory pool
772 // Named color list internal representation
775 char Name
[cmsMAX_PATH
];
776 cmsUInt16Number PCS
[3];
777 cmsUInt16Number DeviceColorant
[cmsMAXCHANNELS
];
781 struct _cms_NAMEDCOLORLIST_struct
{
783 cmsUInt32Number nColors
;
784 cmsUInt32Number Allocated
;
785 cmsUInt32Number ColorantCount
;
787 char Prefix
[33]; // Prefix and suffix are defined to be 32 characters at most
790 _cmsNAMEDCOLOR
* List
;
792 cmsContext ContextID
;
796 // ----------------------------------------------------------------------------------
798 // This is the internal struct holding profile details.
800 // Maximum supported tags in a profile
801 #define MAX_TABLE_TAG 100
803 typedef struct _cms_iccprofile_struct
{
806 cmsIOHANDLER
* IOhandler
;
809 cmsContext ContextID
;
814 // Only most important items found in ICC profiles
815 cmsUInt32Number Version
;
816 cmsProfileClassSignature DeviceClass
;
817 cmsColorSpaceSignature ColorSpace
;
818 cmsColorSpaceSignature PCS
;
819 cmsUInt32Number RenderingIntent
;
821 cmsUInt32Number flags
;
822 cmsUInt32Number manufacturer
, model
;
823 cmsUInt64Number attributes
;
824 cmsUInt32Number creator
;
826 cmsProfileID ProfileID
;
829 cmsUInt32Number TagCount
;
830 cmsTagSignature TagNames
[MAX_TABLE_TAG
];
831 cmsTagSignature TagLinked
[MAX_TABLE_TAG
]; // The tag to which is linked (0=none)
832 cmsUInt32Number TagSizes
[MAX_TABLE_TAG
]; // Size on disk
833 cmsUInt32Number TagOffsets
[MAX_TABLE_TAG
];
834 cmsBool TagSaveAsRaw
[MAX_TABLE_TAG
]; // True to write uncooked
835 void * TagPtrs
[MAX_TABLE_TAG
];
836 cmsTagTypeHandler
* TagTypeHandlers
[MAX_TABLE_TAG
]; // Same structure may be serialized on different types
837 // depending on profile version, so we keep track of the
838 // type handler for each tag in the list.
842 // Keep a mutex for cmsReadTag -- Note that this only works if the user includes a mutex plugin
847 // IO helpers for profiles
848 cmsBool
_cmsReadHeader(_cmsICCPROFILE
* Icc
);
849 cmsBool
_cmsWriteHeader(_cmsICCPROFILE
* Icc
, cmsUInt32Number UsedSpace
);
850 int _cmsSearchTag(_cmsICCPROFILE
* Icc
, cmsTagSignature sig
, cmsBool lFollowLinks
);
853 cmsTagTypeHandler
* _cmsGetTagTypeHandler(cmsContext ContextID
, cmsTagTypeSignature sig
);
854 cmsTagTypeSignature
_cmsGetTagTrueType(cmsHPROFILE hProfile
, cmsTagSignature sig
);
855 cmsTagDescriptor
* _cmsGetTagDescriptor(cmsContext ContextID
, cmsTagSignature sig
);
857 // Error logging ---------------------------------------------------------------------------------------------------------
859 void _cmsTagSignature2String(char String
[5], cmsTagSignature sig
);
861 // Interpolation ---------------------------------------------------------------------------------------------------------
863 CMSCHECKPOINT cmsInterpParams
* CMSEXPORT
_cmsComputeInterpParams(cmsContext ContextID
, cmsUInt32Number nSamples
, cmsUInt32Number InputChan
, cmsUInt32Number OutputChan
, const void* Table
, cmsUInt32Number dwFlags
);
864 cmsInterpParams
* _cmsComputeInterpParamsEx(cmsContext ContextID
, const cmsUInt32Number nSamples
[], cmsUInt32Number InputChan
, cmsUInt32Number OutputChan
, const void* Table
, cmsUInt32Number dwFlags
);
865 CMSCHECKPOINT
void CMSEXPORT
_cmsFreeInterpParams(cmsInterpParams
* p
);
866 cmsBool
_cmsSetInterpolationRoutine(cmsContext ContextID
, cmsInterpParams
* p
);
868 // Curves ----------------------------------------------------------------------------------------------------------------
870 // This struct holds information about a segment, plus a pointer to the function that implements the evaluation.
871 // In the case of table-based, Eval pointer is set to NULL
873 // The gamma function main structure
874 struct _cms_curve_struct
{
876 cmsInterpParams
* InterpParams
; // Private optimizations for interpolation
878 cmsUInt32Number nSegments
; // Number of segments in the curve. Zero for a 16-bit based tables
879 cmsCurveSegment
* Segments
; // The segments
880 cmsInterpParams
** SegInterp
; // Array of private optimizations for interpolation in table-based segments
882 cmsParametricCurveEvaluator
* Evals
; // Evaluators (one per segment)
884 // 16 bit Table-based representation follows
885 cmsUInt32Number nEntries
; // Number of table elements
886 cmsUInt16Number
* Table16
; // The table itself.
890 // Pipelines & Stages ---------------------------------------------------------------------------------------------
893 struct _cmsStage_struct
{
895 cmsContext ContextID
;
897 cmsStageSignature Type
; // Identifies the stage
898 cmsStageSignature Implements
; // Identifies the *function* of the stage (for optimizations)
900 cmsUInt32Number InputChannels
; // Input channels -- for optimization purposes
901 cmsUInt32Number OutputChannels
; // Output channels -- for optimization purposes
903 _cmsStageEvalFn EvalPtr
; // Points to fn that evaluates the stage (always in floating point)
904 _cmsStageDupElemFn DupElemPtr
; // Points to a fn that duplicates the *data* of the stage
905 _cmsStageFreeElemFn FreePtr
; // Points to a fn that sets the *data* of the stage free
907 // A generic pointer to whatever memory needed by the stage
910 // Maintains linked list (used internally)
911 struct _cmsStage_struct
* Next
;
915 // Special Stages (cannot be saved)
916 CMSCHECKPOINT cmsStage
* CMSEXPORT
_cmsStageAllocLab2XYZ(cmsContext ContextID
);
917 CMSCHECKPOINT cmsStage
* CMSEXPORT
_cmsStageAllocXYZ2Lab(cmsContext ContextID
);
918 cmsStage
* _cmsStageAllocLabPrelin(cmsContext ContextID
);
919 CMSCHECKPOINT cmsStage
* CMSEXPORT
_cmsStageAllocLabV2ToV4(cmsContext ContextID
);
920 cmsStage
* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID
);
921 CMSCHECKPOINT cmsStage
* CMSEXPORT
_cmsStageAllocLabV4ToV2(cmsContext ContextID
);
922 CMSCHECKPOINT cmsStage
* CMSEXPORT
_cmsStageAllocNamedColor(cmsNAMEDCOLORLIST
* NamedColorList
, cmsBool UsePCS
);
923 CMSCHECKPOINT cmsStage
* CMSEXPORT
_cmsStageAllocIdentityCurves(cmsContext ContextID
, cmsUInt32Number nChannels
);
924 CMSCHECKPOINT cmsStage
* CMSEXPORT
_cmsStageAllocIdentityCLut(cmsContext ContextID
, cmsUInt32Number nChan
);
925 cmsStage
* _cmsStageNormalizeFromLabFloat(cmsContext ContextID
);
926 cmsStage
* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID
);
927 cmsStage
* _cmsStageNormalizeToLabFloat(cmsContext ContextID
);
928 cmsStage
* _cmsStageNormalizeToXyzFloat(cmsContext ContextID
);
929 cmsStage
* _cmsStageClipNegatives(cmsContext ContextID
, cmsUInt32Number nChannels
);
932 // For curve set only
933 cmsToneCurve
** _cmsStageGetPtrToCurveSet(const cmsStage
* mpe
);
935 struct _cmsPipeline_struct
{
937 cmsStage
* Elements
; // Points to elements chain
938 cmsUInt32Number InputChannels
, OutputChannels
;
943 _cmsPipelineEval16Fn Eval16Fn
;
944 _cmsPipelineEvalFloatFn EvalFloatFn
;
945 _cmsFreeUserDataFn FreeDataFn
;
946 _cmsDupUserDataFn DupDataFn
;
948 cmsContext ContextID
; // Environment
950 cmsBool SaveAs8Bits
; // Implementation-specific: save as 8 bits if possible
953 // LUT reading & creation -------------------------------------------------------------------------------------------
955 // Read tags using low-level function, provide necessary glue code to adapt versions, etc. All those return a brand new copy
956 // of the LUTS, since ownership of original is up to the profile. The user should free allocated resources.
958 CMSCHECKPOINT cmsPipeline
* CMSEXPORT
_cmsReadInputLUT(cmsHPROFILE hProfile
, cmsUInt32Number Intent
);
959 CMSCHECKPOINT cmsPipeline
* CMSEXPORT
_cmsReadOutputLUT(cmsHPROFILE hProfile
, cmsUInt32Number Intent
);
960 CMSCHECKPOINT cmsPipeline
* CMSEXPORT
_cmsReadDevicelinkLUT(cmsHPROFILE hProfile
, cmsUInt32Number Intent
);
963 cmsBool
_cmsReadMediaWhitePoint(cmsCIEXYZ
* Dest
, cmsHPROFILE hProfile
);
964 cmsBool
_cmsReadCHAD(cmsMAT3
* Dest
, cmsHPROFILE hProfile
);
966 // Profile linker --------------------------------------------------------------------------------------------------
968 // Link several profiles to obtain a single LUT modelling the whole color transform. Intents, Black point
969 // compensation and Adaptation parameters may vary across profiles. BPC and Adaptation refers to the PCS
970 // after the profile. I.e, BPC[0] refers to connexion between profile(0) and profile(1)
971 cmsPipeline
* _cmsLinkProfiles(cmsContext ContextID
,
972 cmsUInt32Number nProfiles
,
973 cmsUInt32Number TheIntents
[],
974 cmsHPROFILE hProfiles
[],
976 cmsFloat64Number AdaptationStates
[],
977 cmsUInt32Number dwFlags
);
979 // Sequence --------------------------------------------------------------------------------------------------------
981 cmsSEQ
* _cmsReadProfileSequence(cmsHPROFILE hProfile
);
982 cmsBool
_cmsWriteProfileSequence(cmsHPROFILE hProfile
, const cmsSEQ
* seq
);
983 cmsSEQ
* _cmsCompileProfileSequence(cmsContext ContextID
, cmsUInt32Number nProfiles
, cmsHPROFILE hProfiles
[]);
986 // LUT optimization ------------------------------------------------------------------------------------------------
988 CMSCHECKPOINT cmsUInt16Number CMSEXPORT
_cmsQuantizeVal(cmsFloat64Number i
, cmsUInt32Number MaxSamples
);
990 CMSAPI cmsUInt32Number CMSEXPORT
_cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace
, cmsUInt32Number dwFlags
);
992 cmsBool
_cmsEndPointsBySpace(cmsColorSpaceSignature Space
,
993 cmsUInt16Number
**White
,
994 cmsUInt16Number
**Black
,
995 cmsUInt32Number
*nOutputs
);
997 CMSAPI cmsBool CMSEXPORT
_cmsOptimizePipeline(cmsContext ContextID
,
999 cmsUInt32Number Intent
,
1000 cmsUInt32Number
* InputFormat
,
1001 cmsUInt32Number
* OutputFormat
,
1002 cmsUInt32Number
* dwFlags
);
1005 // Hi level LUT building ----------------------------------------------------------------------------------------------
1007 cmsPipeline
* _cmsCreateGamutCheckPipeline(cmsContext ContextID
,
1008 cmsHPROFILE hProfiles
[],
1010 cmsUInt32Number Intents
[],
1011 cmsFloat64Number AdaptationStates
[],
1012 cmsUInt32Number nGamutPCSposition
,
1013 cmsHPROFILE hGamut
);
1016 // Formatters ------------------------------------------------------------------------------------------------------------
1018 #define cmsFLAGS_CAN_CHANGE_FORMATTER 0x02000000 // Allow change buffer format
1020 cmsBool
_cmsFormatterIsFloat(cmsUInt32Number Type
);
1021 cmsBool
_cmsFormatterIs8bit(cmsUInt32Number Type
);
1023 CMSCHECKPOINT cmsFormatter CMSEXPORT
_cmsGetFormatter(cmsContext ContextID
,
1024 cmsUInt32Number Type
, // Specific type, i.e. TYPE_RGB_8
1025 cmsFormatterDirection Dir
,
1026 cmsUInt32Number dwFlags
);
1029 #ifndef CMS_NO_HALF_SUPPORT
1032 CMSCHECKPOINT cmsFloat32Number CMSEXPORT
_cmsHalf2Float(cmsUInt16Number h
);
1033 CMSCHECKPOINT cmsUInt16Number CMSEXPORT
_cmsFloat2Half(cmsFloat32Number flt
);
1037 // Transform logic ------------------------------------------------------------------------------------------------------
1039 struct _cmstransform_struct
;
1043 // 1-pixel cache (16 bits only)
1044 cmsUInt16Number CacheIn
[cmsMAXCHANNELS
];
1045 cmsUInt16Number CacheOut
[cmsMAXCHANNELS
];
1052 typedef struct _cmstransform_struct
{
1054 cmsUInt32Number InputFormat
, OutputFormat
; // Keep formats for further reference
1056 // Points to transform code
1057 _cmsTransform2Fn xform
;
1059 // Formatters, cannot be embedded into LUT because cache
1060 cmsFormatter16 FromInput
;
1061 cmsFormatter16 ToOutput
;
1063 cmsFormatterFloat FromInputFloat
;
1064 cmsFormatterFloat ToOutputFloat
;
1066 // 1-pixel cache seed for zero as input (16 bits, read only)
1069 // A Pipeline holding the full (optimized) transform
1072 // A Pipeline holding the gamut check. It goes from the input space to bilevel
1073 cmsPipeline
* GamutCheck
;
1076 cmsNAMEDCOLORLIST
* InputColorant
; // Input Colorant table
1077 cmsNAMEDCOLORLIST
* OutputColorant
; // Colorant table (for n chans > CMYK)
1079 // Informational only
1080 cmsColorSpaceSignature EntryColorSpace
;
1081 cmsColorSpaceSignature ExitColorSpace
;
1083 // White points (informative only)
1084 cmsCIEXYZ EntryWhitePoint
;
1085 cmsCIEXYZ ExitWhitePoint
;
1087 // Profiles used to create the transform
1090 cmsUInt32Number dwOriginalFlags
;
1091 cmsFloat64Number AdaptationState
;
1093 // The intent of this transform. That is usually the last intent in the profilechain, but may differ
1094 cmsUInt32Number RenderingIntent
;
1096 // An id that uniquely identifies the running context. May be null.
1097 cmsContext ContextID
;
1099 // A user-defined pointer that can be used to store data for transform plug-ins
1101 _cmsFreeUserDataFn FreeUserData
;
1103 // A way to provide backwards compatibility with full xform plugins
1104 _cmsTransformFn OldXform
;
1106 // A one-worker transform entry for parallelization
1107 _cmsTransform2Fn Worker
;
1108 cmsInt32Number MaxWorkers
;
1109 cmsUInt32Number WorkerFlags
;
1113 // Copies extra channels from input to output if the original flags in the transform structure
1114 // instructs to do so. This function is called on all standard transform functions.
1115 void _cmsHandleExtraChannels(_cmsTRANSFORM
* p
, const void* in
,
1117 cmsUInt32Number PixelsPerLine
,
1118 cmsUInt32Number LineCount
,
1119 const cmsStride
* Stride
);
1121 // -----------------------------------------------------------------------------------------------------------------------
1123 cmsHTRANSFORM
_cmsChain2Lab(cmsContext ContextID
,
1124 cmsUInt32Number nProfiles
,
1125 cmsUInt32Number InputFormat
,
1126 cmsUInt32Number OutputFormat
,
1127 const cmsUInt32Number Intents
[],
1128 const cmsHPROFILE hProfiles
[],
1129 const cmsBool BPC
[],
1130 const cmsFloat64Number AdaptationStates
[],
1131 cmsUInt32Number dwFlags
);
1134 cmsToneCurve
* _cmsBuildKToneCurve(cmsContext ContextID
,
1135 cmsUInt32Number nPoints
,
1136 cmsUInt32Number nProfiles
,
1137 const cmsUInt32Number Intents
[],
1138 const cmsHPROFILE hProfiles
[],
1139 const cmsBool BPC
[],
1140 const cmsFloat64Number AdaptationStates
[],
1141 cmsUInt32Number dwFlags
);
1143 cmsBool
_cmsAdaptationMatrix(cmsMAT3
* r
, const cmsMAT3
* ConeMatrix
, const cmsCIEXYZ
* FromIll
, const cmsCIEXYZ
* ToIll
);
1145 cmsBool
_cmsBuildRGB2XYZtransferMatrix(cmsMAT3
* r
, const cmsCIExyY
* WhitePoint
, const cmsCIExyYTRIPLE
* Primaries
);
1148 // thread-safe gettime
1149 cmsBool
_cmsGetTime(struct tm
* ptr_time
);
1151 #define _lcms_internal_H