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