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