1
2//
3//  Little Color Management System
4//  Copyright (c) 1998-2016 Marti Maria Saguer
5//
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:
12//
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15//
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.
23//
24//---------------------------------------------------------------------------------
25//
26
27#ifndef _lcms_internal_H
28
29// Include plug-in foundation
30#ifndef _lcms_plugin_H
31#   include "third_party/lcms/include/lcms2_plugin.h"
32#endif
33
34// ctype is part of C99 as per 7.1.2
35#include <ctype.h>
36
37// assert macro is part of C99 as per 7.2
38#include <assert.h>
39
40// Some needed constants
41#ifndef M_PI
42#       define M_PI        3.14159265358979323846
43#endif
44
45#ifndef M_LOG10E
46#       define M_LOG10E    0.434294481903251827651
47#endif
48
49// BorlandC 5.5, VC2003 are broken on that
50#if defined(__BORLANDC__) || (_MSC_VER < 1400) // 1400 == VC++ 8.0
51#define sinf(x) (float)sin((float)x)
52#define sqrtf(x) (float)sqrt((float)x)
53#endif
54
55
56// Alignment of ICC file format uses 4 bytes (cmsUInt32Number)
57#define _cmsALIGNLONG(x) (((x)+(sizeof(cmsUInt32Number)-1)) & ~(sizeof(cmsUInt32Number)-1))
58
59// Alignment to memory pointer
60
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 *)
66#endif
67
68#define _cmsALIGNMEM(x)  (((x)+(CMS_PTR_ALIGNMENT - 1)) & ~(CMS_PTR_ALIGNMENT - 1))
69
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)
76
77// Maximum of channels for internal pipeline evaluation
78#define MAX_STAGE_CHANNELS  128
79
80// Unused parameter warning supression
81#define cmsUNUSED_PARAMETER(x) ((void)x)
82
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
87#else
88#   define cmsINLINE static inline
89#endif
90
91// Other replacement functions
92#ifdef _MSC_VER
93# ifndef snprintf
94#       define snprintf  _snprintf
95# endif
96# ifndef vsnprintf
97#       define vsnprintf  _vsnprintf
98# endif
99#endif
100
101
102// A fast way to convert from/to 16 <-> 8 bits
103#define FROM_8_TO_16(rgb) (cmsUInt16Number) ((((cmsUInt16Number) (rgb)) << 8)|(rgb))
104#define FROM_16_TO_8(rgb) (cmsUInt8Number) ((((cmsUInt32Number)(rgb) * 65281U + 8388608U) >> 24) & 0xFFU)
105
106// Code analysis is broken on asserts
107#ifdef _MSC_VER
108#    if (_MSC_VER >= 1500)
109#            define _cmsAssert(a)  { assert((a)); __analysis_assume((a)); }
110#     else
111#            define _cmsAssert(a)   assert((a))
112#     endif
113#else
114#      define _cmsAssert(a)   assert((a))
115#endif
116
117//---------------------------------------------------------------------------------
118
119// Determinant lower than that are assumed zero (used on matrix invert)
120#define MATRIX_DET_TOLERANCE    0.0001
121
122//---------------------------------------------------------------------------------
123
124// Fixed point
125#define FIXED_TO_INT(x)         ((x)>>16)
126#define FIXED_REST_TO_INT(x)    ((x)&0xFFFFU)
127#define ROUND_FIXED_TO_INT(x)   (((x)+0x8000)>>16)
128
129cmsINLINE cmsS15Fixed16Number _cmsToFixedDomain(int a)                   { return a + ((a + 0x7fff) / 0xffff); }
130cmsINLINE int                 _cmsFromFixedDomain(cmsS15Fixed16Number a) { return a - ((a + 0x7fff) >> 16); }
131
132// -----------------------------------------------------------------------------------------------------------
133
134// Fast floor conversion logic. Thanks to Sree Kotay and Stuart Nixon
135// note than this only works in the range ..-32767...+32767 because
136// mantissa is interpreted as 15.16 fixed point.
137// The union is to avoid pointer aliasing overoptimization.
138cmsINLINE int _cmsQuickFloor(cmsFloat64Number val)
139{
140#ifdef CMS_DONT_USE_FAST_FLOOR
141    return (int) floor(val);
142#else
143    const cmsFloat64Number _lcms_double2fixmagic = 68719476736.0 * 1.5;  // 2^36 * 1.5, (52-16=36) uses limited precision to floor
144    union {
145        cmsFloat64Number val;
146        int halves[2];
147    } temp;
148
149    temp.val = val + _lcms_double2fixmagic;
150
151#ifdef CMS_USE_BIG_ENDIAN
152    return temp.halves[1] >> 16;
153#else
154    return temp.halves[0] >> 16;
155#endif
156#endif
157}
158
159// Fast floor restricted to 0..65535.0
160cmsINLINE cmsUInt16Number _cmsQuickFloorWord(cmsFloat64Number d)
161{
162    return (cmsUInt16Number) _cmsQuickFloor(d - 32767.0) + 32767U;
163}
164
165// Floor to word, taking care of saturation
166cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d)
167{
168    d += 0.5;
169    if (d <= 0) return 0;
170    if (d >= 65535.0) return 0xffff;
171
172    return _cmsQuickFloorWord(d);
173}
174
175
176// Pthread support --------------------------------------------------------------------
177#ifndef CMS_NO_PTHREADS
178
179// This is the threading support. Unfortunately, it has to be platform-dependent because
180// windows does not support pthreads.
181
182#ifdef CMS_IS_WINDOWS_
183
184#define WIN32_LEAN_AND_MEAN 1
185#include <windows.h>
186
187
188// From: http://locklessinc.com/articles/pthreads_on_windows/
189// The pthreads API has an initialization macro that has no correspondence to anything in
190// the windows API. By investigating the internal definition of the critical section type,
191// one may work out how to initialize one without calling InitializeCriticalSection().
192// The trick here is that InitializeCriticalSection() is not allowed to fail. It tries
193// to allocate a critical section debug object, but if no memory is available, it sets
194// the pointer to a specific value. (One would expect that value to be NULL, but it is
195// actually (void *)-1 for some reason.) Thus we can use this special value for that
196// pointer, and the critical section code will work.
197
198// The other important part of the critical section type to initialize is the number
199// of waiters. This controls whether or not the mutex is locked. Fortunately, this
200// part of the critical section is unlikely to change. Apparently, many programs
201// already test critical sections to see if they are locked using this value, so
202// Microsoft felt that it was necessary to keep it set at -1 for an unlocked critical
203// section, even when they changed the underlying algorithm to be more scalable.
204// The final parts of the critical section object are unimportant, and can be set
205// to zero for their defaults. This yields to an initialization macro:
206
207typedef CRITICAL_SECTION _cmsMutex;
208
209#define CMS_MUTEX_INITIALIZER {(PRTL_CRITICAL_SECTION_DEBUG) -1,-1,0,0,0,0}
210
211#ifdef _MSC_VER
212#    if (_MSC_VER >= 1800)
213#          pragma warning(disable : 26135)
214#    endif
215#endif
216
217cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
218{
219	EnterCriticalSection(m);
220	return 0;
221}
222
223cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m)
224{
225	LeaveCriticalSection(m);
226	return 0;
227}
228
229cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m)
230{
231	InitializeCriticalSection(m);
232	return 0;
233}
234
235cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m)
236{
237	DeleteCriticalSection(m);
238	return 0;
239}
240
241cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m)
242{
243	EnterCriticalSection(m);
244	return 0;
245}
246
247cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m)
248{
249	LeaveCriticalSection(m);
250	return 0;
251}
252
253#else
254
255// Rest of the wide world
256#include <pthread.h>
257
258#define CMS_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
259typedef pthread_mutex_t _cmsMutex;
260
261
262cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
263{
264	return pthread_mutex_lock(m);
265}
266
267cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m)
268{
269	return pthread_mutex_unlock(m);
270}
271
272cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m)
273{
274	return pthread_mutex_init(m, NULL);
275}
276
277cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m)
278{
279	return pthread_mutex_destroy(m);
280}
281
282cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m)
283{
284	return pthread_mutex_lock(m);
285}
286
287cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m)
288{
289	return pthread_mutex_unlock(m);
290}
291
292#endif
293#else
294
295#define CMS_MUTEX_INITIALIZER 0
296typedef int _cmsMutex;
297
298
299cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
300{
301    cmsUNUSED_PARAMETER(m);
302	return 0;
303}
304
305cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m)
306{
307    cmsUNUSED_PARAMETER(m);
308	return 0;
309}
310
311cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m)
312{
313    cmsUNUSED_PARAMETER(m);
314	return 0;
315}
316
317cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m)
318{
319    cmsUNUSED_PARAMETER(m);
320	return 0;
321}
322
323cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m)
324{
325    cmsUNUSED_PARAMETER(m);
326	return 0;
327}
328
329cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m)
330{
331    cmsUNUSED_PARAMETER(m);
332	return 0;
333}
334#endif
335
336// Plug-In registration ---------------------------------------------------------------
337
338// Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once.
339void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size);
340
341// Memory management
342cmsBool   _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
343
344// Interpolation
345cmsBool  _cmsRegisterInterpPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
346
347// Parametric curves
348cmsBool  _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
349
350// Formatters management
351cmsBool  _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
352
353// Tag type management
354cmsBool  _cmsRegisterTagTypePlugin(cmsContext ContextID, cmsPluginBase* Plugin);
355
356// Tag management
357cmsBool  _cmsRegisterTagPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
358
359// Intent management
360cmsBool  _cmsRegisterRenderingIntentPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
361
362// Multi Process elements
363cmsBool  _cmsRegisterMultiProcessElementPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
364
365// Optimization
366cmsBool  _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
367
368// Transform
369cmsBool  _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
370
371// Mutex
372cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
373
374// ---------------------------------------------------------------------------------------------------------
375
376// Suballocators.
377typedef struct _cmsSubAllocator_chunk_st {
378
379    cmsUInt8Number* Block;
380    cmsUInt32Number BlockSize;
381    cmsUInt32Number Used;
382
383    struct _cmsSubAllocator_chunk_st* next;
384
385} _cmsSubAllocator_chunk;
386
387
388typedef struct {
389
390    cmsContext ContextID;
391    _cmsSubAllocator_chunk* h;
392
393} _cmsSubAllocator;
394
395
396_cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial);
397void              _cmsSubAllocDestroy(_cmsSubAllocator* s);
398void*             _cmsSubAlloc(_cmsSubAllocator* s, cmsUInt32Number size);
399void*             _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size);
400
401// ----------------------------------------------------------------------------------
402
403// The context clients.
404typedef enum {
405
406    UserPtr,            // User-defined pointer
407    Logger,
408    AlarmCodesContext,
409    AdaptationStateContext,
410    MemPlugin,
411    InterpPlugin,
412    CurvesPlugin,
413    FormattersPlugin,
414    TagTypePlugin,
415    TagPlugin,
416    IntentPlugin,
417    MPEPlugin,
418    OptimizationPlugin,
419    TransformPlugin,
420    MutexPlugin,
421
422    // Last in list
423    MemoryClientMax
424
425} _cmsMemoryClient;
426
427
428// Container for memory management plug-in.
429typedef struct {
430
431    _cmsMallocFnPtrType     MallocPtr;
432    _cmsMalloZerocFnPtrType MallocZeroPtr;
433    _cmsFreeFnPtrType       FreePtr;
434    _cmsReallocFnPtrType    ReallocPtr;
435    _cmsCallocFnPtrType     CallocPtr;
436    _cmsDupFnPtrType        DupPtr;
437
438} _cmsMemPluginChunkType;
439
440// Copy memory management function pointers from plug-in to chunk, taking care of missing routines
441void  _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr);
442
443// Internal structure for context
444struct _cmsContext_struct {
445
446    struct _cmsContext_struct* Next;  // Points to next context in the new style
447    _cmsSubAllocator* MemPool;        // The memory pool that stores context data
448
449    void* chunks[MemoryClientMax];    // array of pointers to client chunks. Memory itself is hold in the suballocator.
450                                      // If NULL, then it reverts to global Context0
451
452    _cmsMemPluginChunkType DefaultMemoryManager;  // The allocators used for creating the context itself. Cannot be overriden
453};
454
455// Returns a pointer to a valid context structure, including the global one if id is zero.
456// Verifies the magic number.
457struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID);
458
459// Returns the block assigned to the specific zone.
460void*     _cmsContextGetClientChunk(cmsContext id, _cmsMemoryClient mc);
461
462
463// Chunks of context memory by plug-in client -------------------------------------------------------
464
465// Those structures encapsulates all variables needed by the several context clients (mostly plug-ins)
466
467// Container for error logger -- not a plug-in
468typedef struct {
469
470    cmsLogErrorHandlerFunction LogErrorHandler;  // Set to NULL for Context0 fallback
471
472} _cmsLogErrorChunkType;
473
474// The global Context0 storage for error logger
475extern  _cmsLogErrorChunkType  _cmsLogErrorChunk;
476
477// Allocate and init error logger container.
478void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx,
479                            const struct _cmsContext_struct* src);
480
481// Container for alarm codes -- not a plug-in
482typedef struct {
483
484    cmsUInt16Number AlarmCodes[cmsMAXCHANNELS];
485
486} _cmsAlarmCodesChunkType;
487
488// The global Context0 storage for alarm codes
489extern  _cmsAlarmCodesChunkType _cmsAlarmCodesChunk;
490
491// Allocate and init alarm codes container.
492void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx,
493                            const struct _cmsContext_struct* src);
494
495// Container for adaptation state -- not a plug-in
496typedef struct {
497
498    cmsFloat64Number  AdaptationState;
499
500} _cmsAdaptationStateChunkType;
501
502// The global Context0 storage for adaptation state
503extern  _cmsAdaptationStateChunkType    _cmsAdaptationStateChunk;
504
505// Allocate and init adaptation state container.
506void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx,
507                                   const struct _cmsContext_struct* src);
508
509
510// The global Context0 storage for memory management
511extern  _cmsMemPluginChunkType _cmsMemPluginChunk;
512
513// Allocate and init memory management container.
514void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx,
515                             const struct _cmsContext_struct* src);
516
517// Container for interpolation plug-in
518typedef struct {
519
520    cmsInterpFnFactory Interpolators;
521
522} _cmsInterpPluginChunkType;
523
524// The global Context0 storage for interpolation plug-in
525extern  _cmsInterpPluginChunkType _cmsInterpPluginChunk;
526
527// Allocate and init interpolation container.
528void _cmsAllocInterpPluginChunk(struct _cmsContext_struct* ctx,
529                                const struct _cmsContext_struct* src);
530
531// Container for parametric curves plug-in
532typedef struct {
533
534    struct _cmsParametricCurvesCollection_st* ParametricCurves;
535
536} _cmsCurvesPluginChunkType;
537
538// The global Context0 storage for tone curves plug-in
539extern  _cmsCurvesPluginChunkType _cmsCurvesPluginChunk;
540
541// Allocate and init parametric curves container.
542void _cmsAllocCurvesPluginChunk(struct _cmsContext_struct* ctx,
543                                                      const struct _cmsContext_struct* src);
544
545// Container for formatters plug-in
546typedef struct {
547
548    struct _cms_formatters_factory_list* FactoryList;
549
550} _cmsFormattersPluginChunkType;
551
552// The global Context0 storage for formatters plug-in
553extern  _cmsFormattersPluginChunkType _cmsFormattersPluginChunk;
554
555// Allocate and init formatters container.
556void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx,
557                                                       const struct _cmsContext_struct* src);
558
559// This chunk type is shared by TagType plug-in and MPE Plug-in
560typedef struct {
561
562    struct _cmsTagTypeLinkedList_st* TagTypes;
563
564} _cmsTagTypePluginChunkType;
565
566
567// The global Context0 storage for tag types plug-in
568extern  _cmsTagTypePluginChunkType      _cmsTagTypePluginChunk;
569
570
571// The global Context0 storage for mult process elements plug-in
572extern  _cmsTagTypePluginChunkType      _cmsMPETypePluginChunk;
573
574// Allocate and init Tag types container.
575void _cmsAllocTagTypePluginChunk(struct _cmsContext_struct* ctx,
576                                                        const struct _cmsContext_struct* src);
577// Allocate and init MPE container.
578void _cmsAllocMPETypePluginChunk(struct _cmsContext_struct* ctx,
579                                                        const struct _cmsContext_struct* src);
580// Container for tag plug-in
581typedef struct {
582
583    struct _cmsTagLinkedList_st* Tag;
584
585} _cmsTagPluginChunkType;
586
587
588// The global Context0 storage for tag plug-in
589extern  _cmsTagPluginChunkType _cmsTagPluginChunk;
590
591// Allocate and init Tag container.
592void _cmsAllocTagPluginChunk(struct _cmsContext_struct* ctx,
593                                                      const struct _cmsContext_struct* src);
594
595// Container for intents plug-in
596typedef struct {
597
598    struct _cms_intents_list* Intents;
599
600} _cmsIntentsPluginChunkType;
601
602
603// The global Context0 storage for intents plug-in
604extern  _cmsIntentsPluginChunkType _cmsIntentsPluginChunk;
605
606// Allocate and init intents container.
607void _cmsAllocIntentsPluginChunk(struct _cmsContext_struct* ctx,
608                                                        const struct _cmsContext_struct* src);
609
610// Container for optimization plug-in
611typedef struct {
612
613    struct _cmsOptimizationCollection_st* OptimizationCollection;
614
615} _cmsOptimizationPluginChunkType;
616
617
618// The global Context0 storage for optimizers plug-in
619extern  _cmsOptimizationPluginChunkType _cmsOptimizationPluginChunk;
620
621// Allocate and init optimizers container.
622void _cmsAllocOptimizationPluginChunk(struct _cmsContext_struct* ctx,
623                                         const struct _cmsContext_struct* src);
624
625// Container for transform plug-in
626typedef struct {
627
628    struct _cmsTransformCollection_st* TransformCollection;
629
630} _cmsTransformPluginChunkType;
631
632// The global Context0 storage for full-transform replacement plug-in
633extern  _cmsTransformPluginChunkType _cmsTransformPluginChunk;
634
635// Allocate and init transform container.
636void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx,
637                                        const struct _cmsContext_struct* src);
638
639// Container for mutex plug-in
640typedef struct {
641
642    _cmsCreateMutexFnPtrType  CreateMutexPtr;
643    _cmsDestroyMutexFnPtrType DestroyMutexPtr;
644    _cmsLockMutexFnPtrType    LockMutexPtr;
645    _cmsUnlockMutexFnPtrType  UnlockMutexPtr;
646
647} _cmsMutexPluginChunkType;
648
649// The global Context0 storage for mutex plug-in
650extern  _cmsMutexPluginChunkType _cmsMutexPluginChunk;
651
652// Allocate and init mutex container.
653void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx,
654                                        const struct _cmsContext_struct* src);
655
656// ----------------------------------------------------------------------------------
657// MLU internal representation
658typedef struct {
659
660    cmsUInt16Number Language;
661    cmsUInt16Number Country;
662
663    cmsUInt32Number StrW;       // Offset to current unicode string
664    cmsUInt32Number Len;        // Length in bytes
665
666} _cmsMLUentry;
667
668struct _cms_MLU_struct {
669
670    cmsContext ContextID;
671
672    // The directory
673    cmsUInt32Number  AllocatedEntries;
674    cmsUInt32Number  UsedEntries;
675    _cmsMLUentry* Entries;     // Array of pointers to strings allocated in MemPool
676
677    // The Pool
678    cmsUInt32Number PoolSize;  // The maximum allocated size
679    cmsUInt32Number PoolUsed;  // The used size
680    void*  MemPool;            // Pointer to begin of memory pool
681};
682
683// Named color list internal representation
684typedef struct {
685
686    char Name[cmsMAX_PATH];
687    cmsUInt16Number PCS[3];
688    cmsUInt16Number DeviceColorant[cmsMAXCHANNELS];
689
690} _cmsNAMEDCOLOR;
691
692struct _cms_NAMEDCOLORLIST_struct {
693
694    cmsUInt32Number nColors;
695    cmsUInt32Number Allocated;
696    cmsUInt32Number ColorantCount;
697
698    char Prefix[33];      // Prefix and suffix are defined to be 32 characters at most
699    char Suffix[33];
700
701    _cmsNAMEDCOLOR* List;
702
703    cmsContext ContextID;
704};
705
706
707// ----------------------------------------------------------------------------------
708
709// This is the internal struct holding profile details.
710
711// Maximum supported tags in a profile
712#define MAX_TABLE_TAG       100
713
714typedef struct _cms_iccprofile_struct {
715
716    // I/O handler
717    cmsIOHANDLER*            IOhandler;
718
719    // The thread ID
720    cmsContext               ContextID;
721
722    // Creation time
723    struct tm                Created;
724
725    // Only most important items found in ICC profiles
726    cmsUInt32Number          Version;
727    cmsProfileClassSignature DeviceClass;
728    cmsColorSpaceSignature   ColorSpace;
729    cmsColorSpaceSignature   PCS;
730    cmsUInt32Number          RenderingIntent;
731
732    cmsUInt32Number          flags;
733    cmsUInt32Number          manufacturer, model;
734    cmsUInt64Number          attributes;
735    cmsUInt32Number          creator;
736
737    cmsProfileID             ProfileID;
738
739    // Dictionary
740    cmsUInt32Number          TagCount;
741    cmsTagSignature          TagNames[MAX_TABLE_TAG];
742    cmsTagSignature          TagLinked[MAX_TABLE_TAG];           // The tag to which is linked (0=none)
743    cmsUInt32Number          TagSizes[MAX_TABLE_TAG];            // Size on disk
744    cmsUInt32Number          TagOffsets[MAX_TABLE_TAG];
745    cmsBool                  TagSaveAsRaw[MAX_TABLE_TAG];        // True to write uncooked
746    void *                   TagPtrs[MAX_TABLE_TAG];
747    cmsTagTypeHandler*       TagTypeHandlers[MAX_TABLE_TAG];     // Same structure may be serialized on different types
748                                                                 // depending on profile version, so we keep track of the
749                                                                 // type handler for each tag in the list.
750    // Special
751    cmsBool                  IsWrite;
752
753    // Keep a mutex for cmsReadTag -- Note that this only works if the user includes a mutex plugin
754    void *                   UsrMutex;
755
756} _cmsICCPROFILE;
757
758// IO helpers for profiles
759cmsBool              _cmsReadHeader(_cmsICCPROFILE* Icc);
760cmsBool              _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace);
761int                  _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks);
762
763// Tag types
764cmsTagTypeHandler*   _cmsGetTagTypeHandler(cmsContext ContextID, cmsTagTypeSignature sig);
765cmsTagTypeSignature  _cmsGetTagTrueType(cmsHPROFILE hProfile, cmsTagSignature sig);
766cmsTagDescriptor*    _cmsGetTagDescriptor(cmsContext ContextID, cmsTagSignature sig);
767
768// Error logging ---------------------------------------------------------------------------------------------------------
769
770void                 _cmsTagSignature2String(char String[5], cmsTagSignature sig);
771
772// Interpolation ---------------------------------------------------------------------------------------------------------
773
774cmsInterpParams*     _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags);
775cmsInterpParams*     _cmsComputeInterpParamsEx(cmsContext ContextID, const cmsUInt32Number nSamples[], int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags);
776void                 _cmsFreeInterpParams(cmsInterpParams* p);
777cmsBool              _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p);
778
779// Curves ----------------------------------------------------------------------------------------------------------------
780
781// This struct holds information about a segment, plus a pointer to the function that implements the evaluation.
782// In the case of table-based, Eval pointer is set to NULL
783
784// The gamma function main structure
785struct _cms_curve_struct {
786
787    cmsInterpParams*  InterpParams;  // Private optimizations for interpolation
788
789    cmsUInt32Number   nSegments;     // Number of segments in the curve. Zero for a 16-bit based tables
790    cmsCurveSegment*  Segments;      // The segments
791    cmsInterpParams** SegInterp;     // Array of private optimizations for interpolation in table-based segments
792
793    cmsParametricCurveEvaluator* Evals;  // Evaluators (one per segment)
794
795    // 16 bit Table-based representation follows
796    cmsUInt32Number    nEntries;      // Number of table elements
797    cmsUInt16Number*   Table16;       // The table itself.
798};
799
800
801//  Pipelines & Stages ---------------------------------------------------------------------------------------------
802
803// A single stage
804struct _cmsStage_struct {
805
806    cmsContext          ContextID;
807
808    cmsStageSignature   Type;           // Identifies the stage
809    cmsStageSignature   Implements;     // Identifies the *function* of the stage (for optimizations)
810
811    cmsUInt32Number     InputChannels;  // Input channels -- for optimization purposes
812    cmsUInt32Number     OutputChannels; // Output channels -- for optimization purposes
813
814    _cmsStageEvalFn     EvalPtr;        // Points to fn that evaluates the stage (always in floating point)
815    _cmsStageDupElemFn  DupElemPtr;     // Points to a fn that duplicates the *data* of the stage
816    _cmsStageFreeElemFn FreePtr;        // Points to a fn that sets the *data* of the stage free
817
818    // A generic pointer to whatever memory needed by the stage
819    void*               Data;
820
821    // Maintains linked list (used internally)
822    struct _cmsStage_struct* Next;
823};
824
825
826// Special Stages (cannot be saved)
827cmsStage*        _cmsStageAllocLab2XYZ(cmsContext ContextID);
828cmsStage*        _cmsStageAllocXYZ2Lab(cmsContext ContextID);
829cmsStage*        _cmsStageAllocLabPrelin(cmsContext ContextID);
830cmsStage*        _cmsStageAllocLabV2ToV4(cmsContext ContextID);
831cmsStage*        _cmsStageAllocLabV2ToV4curves(cmsContext ContextID);
832cmsStage*        _cmsStageAllocLabV4ToV2(cmsContext ContextID);
833cmsStage*        _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS);
834cmsStage*        _cmsStageAllocIdentityCurves(cmsContext ContextID, int nChannels);
835cmsStage*        _cmsStageAllocIdentityCLut(cmsContext ContextID, int nChan);
836cmsStage*        _cmsStageNormalizeFromLabFloat(cmsContext ContextID);
837cmsStage*        _cmsStageNormalizeFromXyzFloat(cmsContext ContextID);
838cmsStage*        _cmsStageNormalizeToLabFloat(cmsContext ContextID);
839cmsStage*        _cmsStageNormalizeToXyzFloat(cmsContext ContextID);
840cmsStage*        _cmsStageClipNegatives(cmsContext ContextID, int nChannels);
841
842
843// For curve set only
844cmsToneCurve**     _cmsStageGetPtrToCurveSet(const cmsStage* mpe);
845
846
847// Pipeline Evaluator (in floating point)
848typedef void (* _cmsPipelineEvalFloatFn)(const cmsFloat32Number In[],
849                                         cmsFloat32Number Out[],
850                                         const void* Data);
851
852struct _cmsPipeline_struct {
853
854    cmsStage* Elements;                                // Points to elements chain
855    cmsUInt32Number InputChannels, OutputChannels;
856
857    // Data & evaluators
858    void *Data;
859
860   _cmsOPTeval16Fn         Eval16Fn;
861   _cmsPipelineEvalFloatFn EvalFloatFn;
862   _cmsFreeUserDataFn      FreeDataFn;
863   _cmsDupUserDataFn       DupDataFn;
864
865    cmsContext ContextID;            // Environment
866
867    cmsBool  SaveAs8Bits;            // Implementation-specific: save as 8 bits if possible
868};
869
870// LUT reading & creation -------------------------------------------------------------------------------------------
871
872// Read tags using low-level function, provide necessary glue code to adapt versions, etc. All those return a brand new copy
873// of the LUTS, since ownership of original is up to the profile. The user should free allocated resources.
874
875cmsPipeline*      _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent);
876cmsPipeline*      _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent);
877cmsPipeline*      _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent);
878
879// Special values
880cmsBool           _cmsReadMediaWhitePoint(cmsCIEXYZ* Dest, cmsHPROFILE hProfile);
881cmsBool           _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile);
882
883// Profile linker --------------------------------------------------------------------------------------------------
884
885cmsPipeline* _cmsLinkProfiles(cmsContext         ContextID,
886                              cmsUInt32Number    nProfiles,
887                              cmsUInt32Number    TheIntents[],
888                              cmsHPROFILE        hProfiles[],
889                              cmsBool            BPC[],
890                              cmsFloat64Number   AdaptationStates[],
891                              cmsUInt32Number    dwFlags);
892
893// Sequence --------------------------------------------------------------------------------------------------------
894
895cmsSEQ* _cmsReadProfileSequence(cmsHPROFILE hProfile);
896cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq);
897cmsSEQ* _cmsCompileProfileSequence(cmsContext ContextID, cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[]);
898
899
900// LUT optimization ------------------------------------------------------------------------------------------------
901
902cmsUInt16Number  _cmsQuantizeVal(cmsFloat64Number i, int MaxSamples);
903int              _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags);
904
905cmsBool          _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
906                                      cmsUInt16Number **White,
907                                      cmsUInt16Number **Black,
908                                      cmsUInt32Number *nOutputs);
909
910cmsBool          _cmsOptimizePipeline(cmsContext ContextID,
911                                      cmsPipeline**    Lut,
912                                      int              Intent,
913                                      cmsUInt32Number* InputFormat,
914                                      cmsUInt32Number* OutputFormat,
915                                      cmsUInt32Number* dwFlags );
916
917
918// Hi level LUT building ----------------------------------------------------------------------------------------------
919
920cmsPipeline*     _cmsCreateGamutCheckPipeline(cmsContext ContextID,
921                                              cmsHPROFILE hProfiles[],
922                                              cmsBool  BPC[],
923                                              cmsUInt32Number Intents[],
924                                              cmsFloat64Number AdaptationStates[],
925                                              cmsUInt32Number nGamutPCSposition,
926                                              cmsHPROFILE hGamut);
927
928
929// Formatters ------------------------------------------------------------------------------------------------------------
930
931#define cmsFLAGS_CAN_CHANGE_FORMATTER     0x02000000   // Allow change buffer format
932
933cmsBool         _cmsFormatterIsFloat(cmsUInt32Number Type);
934cmsBool         _cmsFormatterIs8bit(cmsUInt32Number Type);
935
936cmsFormatter    _cmsGetFormatter(cmsContext ContextID,
937                                 cmsUInt32Number Type,          // Specific type, i.e. TYPE_RGB_8
938                                 cmsFormatterDirection Dir,
939                                 cmsUInt32Number dwFlags);
940
941
942#ifndef CMS_NO_HALF_SUPPORT
943
944// Half float
945cmsFloat32Number _cmsHalf2Float(cmsUInt16Number h);
946cmsUInt16Number  _cmsFloat2Half(cmsFloat32Number flt);
947
948#endif
949
950// Transform logic ------------------------------------------------------------------------------------------------------
951
952struct _cmstransform_struct;
953
954typedef struct {
955
956    // 1-pixel cache (16 bits only)
957    cmsUInt16Number CacheIn[cmsMAXCHANNELS];
958    cmsUInt16Number CacheOut[cmsMAXCHANNELS];
959
960} _cmsCACHE;
961
962
963
964// Transformation
965typedef struct _cmstransform_struct {
966
967    cmsUInt32Number InputFormat, OutputFormat; // Keep formats for further reference
968
969    // Points to transform code
970    _cmsTransform2Fn xform;
971
972    // Formatters, cannot be embedded into LUT because cache
973    cmsFormatter16 FromInput;
974    cmsFormatter16 ToOutput;
975
976    cmsFormatterFloat FromInputFloat;
977    cmsFormatterFloat ToOutputFloat;
978
979    // 1-pixel cache seed for zero as input (16 bits, read only)
980    _cmsCACHE Cache;
981
982    // A Pipeline holding the full (optimized) transform
983    cmsPipeline* Lut;
984
985    // A Pipeline holding the gamut check. It goes from the input space to bilevel
986    cmsPipeline* GamutCheck;
987
988    // Colorant tables
989    cmsNAMEDCOLORLIST* InputColorant;       // Input Colorant table
990    cmsNAMEDCOLORLIST* OutputColorant;      // Colorant table (for n chans > CMYK)
991
992    // Informational only
993    cmsColorSpaceSignature EntryColorSpace;
994    cmsColorSpaceSignature ExitColorSpace;
995
996    // White points (informative only)
997    cmsCIEXYZ EntryWhitePoint;
998    cmsCIEXYZ ExitWhitePoint;
999
1000    // Profiles used to create the transform
1001    cmsSEQ* Sequence;
1002
1003    cmsUInt32Number  dwOriginalFlags;
1004    cmsFloat64Number AdaptationState;
1005
1006    // The intent of this transform. That is usually the last intent in the profilechain, but may differ
1007    cmsUInt32Number RenderingIntent;
1008
1009    // An id that uniquely identifies the running context. May be null.
1010    cmsContext ContextID;
1011
1012    // A user-defined pointer that can be used to store data for transform plug-ins
1013    void* UserData;
1014    _cmsFreeUserDataFn FreeUserData;
1015
1016    // A way to provide backwards compatibility with full xform plugins
1017    _cmsTransformFn OldXform;
1018
1019} _cmsTRANSFORM;
1020
1021// Copies extra channels from input to output if the original flags in the transform structure
1022// instructs to do so. This function is called on all standard transform functions.
1023void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
1024                             void* out,
1025                             cmsUInt32Number PixelsPerLine,
1026                             cmsUInt32Number LineCount,
1027                             const cmsStride* Stride);
1028
1029// -----------------------------------------------------------------------------------------------------------------------
1030
1031cmsHTRANSFORM _cmsChain2Lab(cmsContext             ContextID,
1032                            cmsUInt32Number        nProfiles,
1033                            cmsUInt32Number        InputFormat,
1034                            cmsUInt32Number        OutputFormat,
1035                            const cmsUInt32Number  Intents[],
1036                            const cmsHPROFILE      hProfiles[],
1037                            const cmsBool          BPC[],
1038                            const cmsFloat64Number AdaptationStates[],
1039                            cmsUInt32Number        dwFlags);
1040
1041
1042cmsToneCurve* _cmsBuildKToneCurve(cmsContext       ContextID,
1043                            cmsUInt32Number        nPoints,
1044                            cmsUInt32Number        nProfiles,
1045                            const cmsUInt32Number  Intents[],
1046                            const cmsHPROFILE      hProfiles[],
1047                            const cmsBool          BPC[],
1048                            const cmsFloat64Number AdaptationStates[],
1049                            cmsUInt32Number        dwFlags);
1050
1051cmsBool   _cmsAdaptationMatrix(cmsMAT3* r, const cmsMAT3* ConeMatrix, const cmsCIEXYZ* FromIll, const cmsCIEXYZ* ToIll);
1052
1053cmsBool   _cmsBuildRGB2XYZtransferMatrix(cmsMAT3* r, const cmsCIExyY* WhitePoint, const cmsCIExyYTRIPLE* Primaries);
1054
1055
1056#define _lcms_internal_H
1057#endif
1058