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