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