1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//---------------------------------------------------------------------------------
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//  Little Color Management System
4d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann//  Copyright (c) 1998-2016 Marti Maria Saguer
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Permission is hereby granted, free of charge, to any person obtaining
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// a copy of this software and associated documentation files (the "Software"),
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// to deal in the Software without restriction, including without limitation
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// the rights to use, copy, modify, merge, publish, distribute, sublicense,
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// and/or sell copies of the Software, and to permit persons to whom the Software
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// is furnished to do so, subject to the following conditions:
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The above copyright notice and this permission notice shall be included in
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// all copies or substantial portions of the Software.
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//---------------------------------------------------------------------------------
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "lcms2_internal.h"
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Transformations stuff
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// -----------------------------------------------------------------------
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The Context0 observer adaptation state.
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov_cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE };
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Init and duplicate observer adaptation state
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx,
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                   const struct _cmsContext_struct* src)
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE };
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void* from;
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (src != NULL) {
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        from = src ->chunks[AdaptationStateContext];
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       from = &AdaptationStateChunk;
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType));
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Sets adaptation state for absolute colorimetric intent in the given context.  Adaptation state applies on all
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// but cmsCreateExtendedTransformTHR().  Little CMS can handle incomplete adaptation states.
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d)
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number prev;
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext);
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get previous value for return
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    prev = ptr ->AdaptationState;
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Set the value if d is positive or zero
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (d >= 0.0) {
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ptr ->AdaptationState = d;
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Always return previous value
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return prev;
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d)
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return cmsSetAdaptationStateTHR(NULL, d);
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// -----------------------------------------------------------------------
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Alarm codes for 16-bit transformations, because the fixed range of containers there are
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// no values left to mark out of gamut.
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov_cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE };
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// encoded in 16 bits.
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS])
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext);
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(ContextAlarmCodes != NULL); // Can't happen
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes));
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context.
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Values are meant to be encoded in 16 bits.
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS])
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext);
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(ContextAlarmCodes != NULL); // Can't happen
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes));
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS])
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(NewAlarm != NULL);
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSetAlarmCodesTHR(NULL, NewAlarm);
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number OldAlarm[cmsMAXCHANNELS])
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(OldAlarm != NULL);
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsGetAlarmCodesTHR(NULL, OldAlarm);
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Init and duplicate alarm codes
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx,
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              const struct _cmsContext_struct* src)
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE };
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void* from;
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (src != NULL) {
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        from = src ->chunks[AlarmCodesContext];
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       from = &AlarmCodesChunk;
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType));
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// -----------------------------------------------------------------------
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Get rid of transform resources
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform)
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTRANSFORM* p = (_cmsTRANSFORM*) hTransform;
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(p != NULL);
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p -> GamutCheck)
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsPipelineFree(p -> GamutCheck);
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p -> Lut)
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsPipelineFree(p -> Lut);
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p ->InputColorant)
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsFreeNamedColorList(p ->InputColorant);
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p -> OutputColorant)
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsFreeNamedColorList(p ->OutputColorant);
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p ->Sequence)
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsFreeProfileSequenceDescription(p ->Sequence);
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (p ->UserData)
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p ->FreeUserData(p ->ContextID, p ->UserData);
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(p ->ContextID, (void *) p);
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Apply transform.
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsDoTransform(cmsHTRANSFORM  Transform,
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              const void* InputBuffer,
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              void* OutputBuffer,
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              cmsUInt32Number Size)
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
182d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsStride stride;
183d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
184d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    stride.BytesPerLineIn = 0;  // Not used
185d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    stride.BytesPerLineOut = 0;
186d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    stride.BytesPerPlaneIn = Size;
187d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    stride.BytesPerPlaneOut = Size;
188d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
189d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    p -> xform(p, InputBuffer, OutputBuffer, Size, 1, &stride);
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
193d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// This is a legacy stride for planar
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM  Transform,
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              const void* InputBuffer,
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              void* OutputBuffer,
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              cmsUInt32Number Size, cmsUInt32Number Stride)
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
201d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsStride stride;
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
203d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    stride.BytesPerLineIn = 0;
204d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    stride.BytesPerLineOut = 0;
205d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    stride.BytesPerPlaneIn = Stride;
206d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    stride.BytesPerPlaneOut = Stride;
207d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
208d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    p -> xform(p, InputBuffer, OutputBuffer, Size, 1, &stride);
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
211d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// This is the "fast" function for plugins
212d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid CMSEXPORT cmsDoTransformLineStride(cmsHTRANSFORM  Transform,
213d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                              const void* InputBuffer,
214d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                              void* OutputBuffer,
215d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                              cmsUInt32Number PixelsPerLine,
216d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                              cmsUInt32Number LineCount,
217d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                              cmsUInt32Number BytesPerLineIn,
218d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                              cmsUInt32Number BytesPerLineOut,
219d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                              cmsUInt32Number BytesPerPlaneIn,
220d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                              cmsUInt32Number BytesPerPlaneOut)
221d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
222d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann{
223d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
224d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsStride stride;
225d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
226d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    stride.BytesPerLineIn = BytesPerLineIn;
227d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    stride.BytesPerLineOut = BytesPerLineOut;
228d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    stride.BytesPerPlaneIn = BytesPerPlaneIn;
229d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    stride.BytesPerPlaneOut = BytesPerPlaneOut;
230d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
231d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    p->xform(p, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, &stride);
232d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
233d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
234d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Transform routines ----------------------------------------------------------------------------------------------------------
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check.
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Note that because extended range, we can use a -1.0 value for out of gamut in this case.
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid FloatXFORM(_cmsTRANSFORM* p,
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                const void* in,
243d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                void* out,
244d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                cmsUInt32Number PixelsPerLine,
245d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                cmsUInt32Number LineCount,
246d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                const cmsStride* Stride)
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* accum;
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* output;
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS];
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number OutOfGamut;
252d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsUInt32Number i, j, c, strideIn, strideOut;
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
254d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
256d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideIn = 0;
257d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideOut = 0;
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
259d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    for (i = 0; i < LineCount; i++) {
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
261d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        accum = (cmsUInt8Number*)in + strideIn;
262d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        output = (cmsUInt8Number*)out + strideOut;
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
264d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        for (j = 0; j < PixelsPerLine; j++) {
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
266d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            accum = p->FromInputFloat(p, fIn, accum, Stride->BytesPerPlaneIn);
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
268d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            // Any gamut chack to do?
269d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            if (p->GamutCheck != NULL) {
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
271d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                // Evaluate gamut marker.
272d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                cmsPipelineEvalFloat(fIn, &OutOfGamut, p->GamutCheck);
273d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
274d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                // Is current color out of gamut?
275d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                if (OutOfGamut > 0.0) {
276d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
277d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                    // Certainly, out of gamut
278d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                    for (c = 0; c < cmsMAXCHANNELS; c++)
279d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                        fOut[c] = -1.0;
280d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
281d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                }
282d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                else {
283d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                    // No, proceed normally
284d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                    cmsPipelineEvalFloat(fIn, fOut, p->Lut);
285d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                }
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            else {
288d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
289d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                // No gamut check at all
290d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                cmsPipelineEvalFloat(fIn, fOut, p->Lut);
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
293d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
294d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            output = p->ToOutputFloat(p, fOut, output, Stride->BytesPerPlaneOut);
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
297d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        strideIn += Stride->BytesPerLineIn;
298d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        strideOut += Stride->BytesPerLineOut;
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
300d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid NullFloatXFORM(_cmsTRANSFORM* p,
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    const void* in,
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    void* out,
308d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                    cmsUInt32Number PixelsPerLine,
309d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                    cmsUInt32Number LineCount,
310d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                    const cmsStride* Stride)
311d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* accum;
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* output;
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number fIn[cmsMAXCHANNELS];
316d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsUInt32Number i, j, strideIn, strideOut;
317d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
318d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
319d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
320d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideIn = 0;
321d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideOut = 0;
322d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
323d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    for (i = 0; i < LineCount; i++) {
324d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
325d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           accum = (cmsUInt8Number*) in + strideIn;
326d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           output = (cmsUInt8Number*) out + strideOut;
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
328d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           for (j = 0; j < PixelsPerLine; j++) {
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
330d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                  accum = p->FromInputFloat(p, fIn, accum, Stride ->BytesPerPlaneIn);
331d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                  output = p->ToOutputFloat(p, fIn, output, Stride->BytesPerPlaneOut);
332d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           }
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
334d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           strideIn += Stride->BytesPerLineIn;
335d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           strideOut += Stride->BytesPerLineOut;
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 16 bit precision -----------------------------------------------------------------------------------------------------------
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
341d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Null transformation, only applies formatters. No cache
342d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannstatic
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid NullXFORM(_cmsTRANSFORM* p,
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               const void* in,
345d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann               void* out,
346d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann               cmsUInt32Number PixelsPerLine,
347d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann               cmsUInt32Number LineCount,
348d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann               const cmsStride* Stride)
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* accum;
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* output;
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number wIn[cmsMAXCHANNELS];
353d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsUInt32Number i, j, strideIn, strideOut;
354d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
355d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
356d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
357d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideIn = 0;
358d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideOut = 0;
359d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
360d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    for (i = 0; i < LineCount; i++) {
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
362d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           accum = (cmsUInt8Number*)in + strideIn;
363d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           output = (cmsUInt8Number*)out + strideOut;
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
365d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           for (j = 0; j < PixelsPerLine; j++) {
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
367d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                  accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
368d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                  output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut);
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
370d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
371d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           strideIn += Stride->BytesPerLineIn;
372d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           strideOut += Stride->BytesPerLineOut;
373d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
374d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// No gamut check, no cache, 16 bits
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid PrecalculatedXFORM(_cmsTRANSFORM* p,
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        const void* in,
382d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                        void* out,
383d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                        cmsUInt32Number PixelsPerLine,
384d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                        cmsUInt32Number LineCount,
385d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                        const cmsStride* Stride)
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    register cmsUInt8Number* accum;
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    register cmsUInt8Number* output;
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
390d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsUInt32Number i, j, strideIn, strideOut;
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
392d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
394d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideIn = 0;
395d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideOut = 0;
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
397d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    for (i = 0; i < LineCount; i++) {
398d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
399d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        accum = (cmsUInt8Number*)in + strideIn;
400d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        output = (cmsUInt8Number*)out + strideOut;
401d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
402d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        for (j = 0; j < PixelsPerLine; j++) {
403d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
404d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
405d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            p->Lut->Eval16Fn(wIn, wOut, p->Lut->Data);
406d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
407d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        }
408d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
409d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        strideIn += Stride->BytesPerLineIn;
410d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        strideOut += Stride->BytesPerLineOut;
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
412d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
416d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Auxiliary: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical.
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p,
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                     const cmsUInt16Number wIn[],
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                     cmsUInt16Number wOut[])
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number wOutOfGamut;
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data);
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (wOutOfGamut >= 1) {
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsUInt16Number i;
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext);
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (i=0; i < p ->Lut->OutputChannels; i++) {
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            wOut[i] = ContextAlarmCodes ->AlarmCodes[i];
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
439d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Gamut check, No cache, 16 bits.
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                  const void* in,
443d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                  void* out,
444d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                  cmsUInt32Number PixelsPerLine,
445d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                  cmsUInt32Number LineCount,
446d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                  const cmsStride* Stride)
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* accum;
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* output;
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
451d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsUInt32Number i, j, strideIn, strideOut;
452d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
453d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
454d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
455d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideIn = 0;
456d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideOut = 0;
457d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
458d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    for (i = 0; i < LineCount; i++) {
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
460d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           accum = (cmsUInt8Number*)in + strideIn;
461d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           output = (cmsUInt8Number*)out + strideOut;
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
463d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           for (j = 0; j < PixelsPerLine; j++) {
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
465d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                  accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
466d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                  TransformOnePixelWithGamutCheck(p, wIn, wOut);
467d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                  output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
468d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           }
469d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
470d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           strideIn += Stride->BytesPerLineIn;
471d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           strideOut += Stride->BytesPerLineOut;
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
476d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// No gamut check, Cache, 16 bits,
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CachedXFORM(_cmsTRANSFORM* p,
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 const void* in,
480d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                 void* out,
481d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                 cmsUInt32Number PixelsPerLine,
482d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                 cmsUInt32Number LineCount,
483d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                 const cmsStride* Stride)
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* accum;
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* output;
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsCACHE Cache;
489d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsUInt32Number i, j, strideIn, strideOut;
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
491d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Empty buffers for quick memcmp
494d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    memset(wIn, 0, sizeof(wIn));
495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memset(wOut, 0, sizeof(wOut));
496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get copy of zero cache
498d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    memcpy(&Cache, &p->Cache, sizeof(Cache));
499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
500d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideIn = 0;
501d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideOut = 0;
502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
503d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    for (i = 0; i < LineCount; i++) {
504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
505d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        accum = (cmsUInt8Number*)in + strideIn;
506d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        output = (cmsUInt8Number*)out + strideOut;
507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
508d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        for (j = 0; j < PixelsPerLine; j++) {
509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
510d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
512d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) {
513d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
514d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut));
515d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            }
516d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            else {
517d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                p->Lut->Eval16Fn(wIn, wOut, p->Lut->Data);
518d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
519d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn));
520d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut));
521d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            }
522d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
523d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
526d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        strideIn += Stride->BytesPerLineIn;
527d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        strideOut += Stride->BytesPerLineOut;
528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// All those nice features together
532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CachedXFORMGamutCheck(_cmsTRANSFORM* p,
534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           const void* in,
535d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                           void* out,
536d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                           cmsUInt32Number PixelsPerLine,
537d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                           cmsUInt32Number LineCount,
538d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                           const cmsStride* Stride)
539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
540d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsUInt8Number* accum;
541d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsUInt8Number* output;
542d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
543d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    _cmsCACHE Cache;
544d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsUInt32Number i, j, strideIn, strideOut;
545d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
546d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
547d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
548d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    // Empty buffers for quick memcmp
549d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    memset(wIn, 0, sizeof(wIn));
550d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    memset(wOut, 0, sizeof(wOut));
551d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
552d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    // Get copy of zero cache
553d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    memcpy(&Cache, &p->Cache, sizeof(Cache));
554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
555d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideIn = 0;
556d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    strideOut = 0;
557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
558d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    for (i = 0; i < LineCount; i++) {
559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
560d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        accum = (cmsUInt8Number*)in + strideIn;
561d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        output = (cmsUInt8Number*)out + strideOut;
562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
563d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        for (j = 0; j < PixelsPerLine; j++) {
564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
565d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) {
568d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
569d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut));
570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            else {
572d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                TransformOnePixelWithGamutCheck(p, wIn, wOut);
573d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
574d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn));
575d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut));
576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
578d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
579d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        }
580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
581d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        strideIn += Stride->BytesPerLineIn;
582d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        strideOut += Stride->BytesPerLineOut;
583d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
586d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Transform plug-ins ----------------------------------------------------------------------------------------------------
587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// List of used-defined transform factories
589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct _cmsTransformCollection_st {
590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
591d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    _cmsTransform2Factory  Factory;
592d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    cmsBool                OldXform;   // Factory returns xform function in the old style
593d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    struct _cmsTransformCollection_st *Next;
595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} _cmsTransformCollection;
597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The linked list head
599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov_cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL };
600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Duplicates the zone of memory used by the plug-in in the new context
603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid DupPluginTransformList(struct _cmsContext_struct* ctx,
605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                               const struct _cmsContext_struct* src)
606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsTransformPluginChunkType newHead = { NULL };
608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsTransformCollection*  entry;
609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsTransformCollection*  Anterior = NULL;
610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin];
611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Walk the list copying all nodes
613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   for (entry = head->TransformCollection;
614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        entry != NULL;
615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        entry = entry ->Next) {
616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection));
618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (newEntry == NULL)
620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return;
621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // We want to keep the linked list order, so this is a little bit tricky
623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            newEntry -> Next = NULL;
624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (Anterior)
625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                Anterior -> Next = newEntry;
626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Anterior = newEntry;
628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (newHead.TransformCollection == NULL)
630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                newHead.TransformCollection = newEntry;
631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType));
634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
636d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Allocates memory for transform plugin factory
637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx,
638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                        const struct _cmsContext_struct* src)
639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (src != NULL) {
641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Copy all linked list
643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        DupPluginTransformList(ctx, src);
644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL };
647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType));
648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
651d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Adaptor for old versions of plug-in
652d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannstatic
653d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid _cmsTransform2toTransformAdaptor(struct _cmstransform_struct *CMMcargo,
654d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                      const void* InputBuffer,
655d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                      void* OutputBuffer,
656d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                      cmsUInt32Number PixelsPerLine,
657d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                      cmsUInt32Number LineCount,
658d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                      const cmsStride* Stride)
659d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann{
660d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
661d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       cmsUInt32Number i, strideIn, strideOut;
662d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
663d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       _cmsHandleExtraChannels(CMMcargo, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, Stride);
664d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
665d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       strideIn = 0;
666d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       strideOut = 0;
667d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
668d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       for (i = 0; i < LineCount; i++) {
669d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
670d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann              void *accum = (cmsUInt8Number*)InputBuffer + strideIn;
671d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann              void *output = (cmsUInt8Number*)OutputBuffer + strideOut;
672d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
673d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann              CMMcargo->OldXform(CMMcargo, accum, output, PixelsPerLine, Stride->BytesPerPlaneIn);
674d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
675d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann              strideIn += Stride->BytesPerLineIn;
676d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann              strideOut += Stride->BytesPerLineOut;
677d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       }
678d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
679d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Register new ways to transform
683ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data)
684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPluginTransform* Plugin = (cmsPluginTransform*) Data;
686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTransformCollection* fl;
687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin);
688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Data == NULL) {
690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Free the chain. Memory is safely freed at exit
692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ctx->TransformCollection = NULL;
693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Factory callback is required
697d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (Plugin->factories.xform == NULL) return FALSE;
698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection));
701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (fl == NULL) return FALSE;
702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
703d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    // Check for full xform plug-ins previous to 2.8, we would need an adapter in that case
704d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (Plugin->base.ExpectedVersion < 2080) {
705d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
706d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           fl->OldXform = TRUE;
707d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
708d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    else
709d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           fl->OldXform = FALSE;
710d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Copy the parameters
712d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    fl->Factory = Plugin->factories.xform;
713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Keep linked list
715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fl ->Next = ctx->TransformCollection;
716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ctx->TransformCollection = fl;
717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // All is ok
719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn)
724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(CMMcargo != NULL);
726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CMMcargo ->UserData = ptr;
727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CMMcargo ->FreeUserData = FreePrivateDataFn;
728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// returns the pointer defined by the plug-in to store private data
731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo)
732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(CMMcargo != NULL);
734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return CMMcargo ->UserData;
735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// returns the current formatters
738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT _cmsGetTransformFormatters16(struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput)
739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     _cmsAssert(CMMcargo != NULL);
741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (FromInput) *FromInput = CMMcargo ->FromInput;
742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (ToOutput)  *ToOutput  = CMMcargo ->ToOutput;
743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput)
746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     _cmsAssert(CMMcargo != NULL);
748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (FromInput) *FromInput = CMMcargo ->FromInputFloat;
749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (ToOutput)  *ToOutput  = CMMcargo ->ToOutputFloat;
750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Allocate transform struct and set it to defaults. Ask the optimization plug-in about if those formats are proper
754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// for separated transforms. If this is the case,
755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov_cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                               cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin);
760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     _cmsTransformCollection* Plugin;
761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
762d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       // Allocate needed memory
763d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
764d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       if (!p) {
765d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          cmsPipelineFree(lut);
766d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          return NULL;
767d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      }
768d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
769d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       // Store the proposed pipeline
770d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       p->Lut = lut;
771d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
772d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       // Let's see if any plug-in want to do the transform by itself
773d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       if (p->Lut != NULL) {
774d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
775d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann              for (Plugin = ctx->TransformCollection;
776d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                     Plugin != NULL;
777d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                     Plugin = Plugin->Next) {
778d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
779d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                     if (Plugin->Factory(&p->xform, &p->UserData, &p->FreeUserData, &p->Lut, InputFormat, OutputFormat, dwFlags)) {
780d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
781d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            // Last plugin in the declaration order takes control. We just keep
782d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            // the original parameters as a logging.
783d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default
784d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            // an optimized transform is not reusable. The plug-in can, however, change
785d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            // the flags and make it suitable.
786d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
787d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            p->ContextID = ContextID;
788d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            p->InputFormat = *InputFormat;
789d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            p->OutputFormat = *OutputFormat;
790d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            p->dwOriginalFlags = *dwFlags;
791d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
792d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            // Fill the formatters just in case the optimized routine is interested.
793d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            // No error is thrown if the formatter doesn't exist. It is up to the optimization
794d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            // factory to decide what to do in those cases.
795d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
796d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
797d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
798d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
799d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
800d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            // Save the day?
801d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            if (Plugin->OldXform) {
802d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                   p->OldXform = (_cmsTransformFn) p->xform;
803d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                   p->xform = _cmsTransform2toTransformAdaptor;
804d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            }
805d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
806d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            return p;
807d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                     }
808d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann              }
809d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
810d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann              // Not suitable for the transform plug-in, let's check  the pipeline plug-in
811d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann              _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
812d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       }
813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Check whatever this is a true floating point transform
815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) {
816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Get formatter function always return a valid union, but the contents of this union may be NULL.
818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p ->ToOutputFloat  = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
8254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            cmsDeleteTransform(p);
826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return NULL;
827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (*dwFlags & cmsFLAGS_NULLTRANSFORM) {
830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            p ->xform = NullFloatXFORM;
832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else {
834d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            // Float transforms don't use cache, always are non-NULL
835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            p ->xform = FloatXFORM;
836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (*InputFormat == 0 && *OutputFormat == 0) {
842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            p ->FromInput = p ->ToOutput = NULL;
843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else {
846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            int BytesPerPixelInput;
848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            p ->ToOutput  = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (p ->FromInput == NULL || p ->ToOutput == NULL) {
853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
8554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                cmsDeleteTransform(p);
856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return NULL;
857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            BytesPerPixelInput = T_BYTES(p ->InputFormat);
860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2)
861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (*dwFlags & cmsFLAGS_NULLTRANSFORM) {
866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            p ->xform = NullXFORM;
868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else {
870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (*dwFlags & cmsFLAGS_NOCACHE) {
871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (*dwFlags & cmsFLAGS_GAMUTCHECK)
873d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                    p ->xform = PrecalculatedXFORMGamutCheck;  // Gamut check, no cache
8744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                else
875d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                    p ->xform = PrecalculatedXFORM;  // No cache, no gamut check
876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            else {
878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (*dwFlags & cmsFLAGS_GAMUTCHECK)
880d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                    p ->xform = CachedXFORMGamutCheck;    // Gamut check, cache
8814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                else
882d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                    p ->xform = CachedXFORM;  // No gamut check, cache
883d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p ->InputFormat     = *InputFormat;
889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p ->OutputFormat    = *OutputFormat;
890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p ->dwOriginalFlags = *dwFlags;
891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p ->ContextID       = ContextID;
892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p ->UserData        = NULL;
893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return p;
894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
897ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool GetXFormColorSpaces(int nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output)
898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut;
900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsColorSpaceSignature PostColorSpace;
901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int i;
902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nProfiles <= 0) return FALSE;
904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (hProfiles[0] == NULL) return FALSE;
905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *Input = PostColorSpace = cmsGetColorSpace(hProfiles[0]);
907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nProfiles; i++) {
909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsProfileClassSignature cls;
911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsHPROFILE hProfile = hProfiles[i];
912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int lIsInput = (PostColorSpace != cmsSigXYZData) &&
914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       (PostColorSpace != cmsSigLabData);
915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (hProfile == NULL) return FALSE;
917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cls = cmsGetDeviceClass(hProfile);
919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (cls == cmsSigNamedColorClass) {
921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ColorSpaceIn    = cmsSig1colorData;
923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ColorSpaceOut   = (nProfiles > 1) ? cmsGetPCS(hProfile) : cmsGetColorSpace(hProfile);
924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (lIsInput || (cls == cmsSigLinkClass)) {
927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ColorSpaceIn    = cmsGetColorSpace(hProfile);
929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ColorSpaceOut   = cmsGetPCS(hProfile);
930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ColorSpaceIn    = cmsGetPCS(hProfile);
934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ColorSpaceOut   = cmsGetColorSpace(hProfile);
935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (i==0)
938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            *Input = ColorSpaceIn;
939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        PostColorSpace = ColorSpaceOut;
941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *Output = PostColorSpace;
944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Check colorspace
949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
950ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwFormat)
951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int Space1 = T_COLORSPACE(dwFormat);
953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int Space2 = _cmsLCMScolorSpace(Check);
954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Space1 == PT_ANY) return TRUE;
956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Space1 == Space2) return TRUE;
957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE;
959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Space1 == PT_Lab   && Space2 == PT_LabV2) return TRUE;
960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FALSE;
962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ----------------------------------------------------------------------------------------------------------------
965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
966d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Jun-21-2000: Some profiles (those that comes with W2K) comes
967d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// with the media white (media black?) x 100. Add a sanity check
968d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
969d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannstatic
970d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid NormalizeXYZ(cmsCIEXYZ* Dest)
971d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann{
972d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    while (Dest -> X > 2. &&
973d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           Dest -> Y > 2. &&
974d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           Dest -> Z > 2.) {
975d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
976d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann               Dest -> X /= 10.;
977d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann               Dest -> Y /= 10.;
978d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann               Dest -> Z /= 10.;
979d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       }
980d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
981d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src)
984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (src == NULL) {
986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        wtPt ->X = cmsD50X;
987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        wtPt ->Y = cmsD50Y;
988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        wtPt ->Z = cmsD50Z;
989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        wtPt ->X = src->X;
992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        wtPt ->Y = src->Y;
993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        wtPt ->Z = src->Z;
994d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
995d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        NormalizeXYZ(wtPt);
996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// New to lcms 2.0 -- have all parameters available.
1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[],
1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsBool  BPC[],
1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number Intents[],
1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsFloat64Number AdaptationStates[],
1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsHPROFILE hGamutProfile,
1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number nGamutPCSposition,
1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number InputFormat,
1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number OutputFormat,
1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number dwFlags)
1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTRANSFORM* xform;
1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsColorSpaceSignature EntryColorSpace;
1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsColorSpaceSignature ExitColorSpace;
1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline* Lut;
1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number LastIntent = Intents[nProfiles-1];
1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // If it is a fake transform
1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (dwFlags & cmsFLAGS_NULLTRANSFORM)
1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return AllocEmptyTransform(ContextID, NULL, INTENT_PERCEPTUAL, &InputFormat, &OutputFormat, &dwFlags);
1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // If gamut check is requested, make sure we have a gamut profile
1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (dwFlags & cmsFLAGS_GAMUTCHECK) {
1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK;
1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // On floating point transforms, inhibit cache
1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat))
1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dwFlags |= cmsFLAGS_NOCACHE;
1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Mark entry/exit spaces
1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!GetXFormColorSpaces(nProfiles, hProfiles, &EntryColorSpace, &ExitColorSpace)) {
1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(ContextID, cmsERROR_NULL, "NULL input profiles on transform");
1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Check if proper colorspaces
1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!IsProperColorSpace(EntryColorSpace, InputFormat)) {
1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong input color space on transform");
1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!IsProperColorSpace(ExitColorSpace, OutputFormat)) {
1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong output color space on transform");
1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Create a pipeline with all transformations
1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags);
1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Lut == NULL) {
1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Couldn't link the profiles");
1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Check channel count
1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ((cmsChannelsOf(EntryColorSpace) != cmsPipelineInputChannels(Lut)) ||
1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        (cmsChannelsOf(ExitColorSpace)  != cmsPipelineOutputChannels(Lut))) {
1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsPipelineFree(Lut);
1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted");
1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // All seems ok
1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xform = AllocEmptyTransform(ContextID, Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags);
1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (xform == NULL) {
1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Keep values
1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xform ->EntryColorSpace = EntryColorSpace;
1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xform ->ExitColorSpace  = ExitColorSpace;
1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xform ->RenderingIntent = Intents[nProfiles-1];
1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Take white points
1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SetWhitePoint(&xform->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[0], cmsSigMediaWhitePointTag));
1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SetWhitePoint(&xform->ExitWhitePoint,  (cmsCIEXYZ*) cmsReadTag(hProfiles[nProfiles-1], cmsSigMediaWhitePointTag));
1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Create a gamut check LUT if requested
1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK))
1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        xform ->GamutCheck  = _cmsCreateGamutCheckPipeline(ContextID, hProfiles,
1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                        BPC, Intents,
1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                        AdaptationStates,
1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                        nGamutPCSposition,
1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                        hGamutProfile);
1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Try to read input and output colorant table
1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (cmsIsTag(hProfiles[0], cmsSigColorantTableTag)) {
1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Input table can only come in this way.
1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        xform ->InputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[0], cmsSigColorantTableTag));
1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Output is a little bit more complex.
1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (cmsGetDeviceClass(hProfiles[nProfiles-1]) == cmsSigLinkClass) {
1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // This tag may exist only on devicelink profiles.
1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)) {
1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // It may be NULL if error
1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            xform ->OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag));
1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)) {
1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            xform -> OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableTag));
1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Store the sequence of profiles
1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (dwFlags & cmsFLAGS_KEEP_SEQUENCE) {
1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        xform ->Sequence = _cmsCompileProfileSequence(ContextID, nProfiles, hProfiles);
1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        xform ->Sequence = NULL;
1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // If this is a cached transform, init first value, which is zero (16 bits only)
1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!(dwFlags & cmsFLAGS_NOCACHE)) {
1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        memset(&xform ->Cache.CacheIn, 0, sizeof(xform ->Cache.CacheIn));
1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (xform ->GamutCheck != NULL) {
1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            TransformOnePixelWithGamutCheck(xform, xform ->Cache.CacheIn, xform->Cache.CacheOut);
1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else {
1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            xform ->Lut ->Eval16Fn(xform ->Cache.CacheIn, xform->Cache.CacheOut, xform -> Lut->Data);
1134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (cmsHTRANSFORM) xform;
1139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Multiprofile transforms: Gamut check is not available here, as it is unclear from which profile the gamut comes.
1142ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransformTHR(cmsContext ContextID,
1143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                       cmsHPROFILE hProfiles[],
1144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                       cmsUInt32Number nProfiles,
1145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                       cmsUInt32Number InputFormat,
1146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                       cmsUInt32Number OutputFormat,
1147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                       cmsUInt32Number Intent,
1148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                       cmsUInt32Number dwFlags)
1149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
1151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsBool BPC[256];
1152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number Intents[256];
1153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number AdaptationStates[256];
1154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nProfiles <= 0 || nProfiles > 255) {
1156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles);
1157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
1158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nProfiles; i++) {
1161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE;
1162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Intents[i] = Intent;
1163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        AdaptationStates[i] = cmsSetAdaptationStateTHR(ContextID, -1);
1164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return cmsCreateExtendedTransform(ContextID, nProfiles, hProfiles, BPC, Intents, AdaptationStates, NULL, 0, InputFormat, OutputFormat, dwFlags);
1168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1172ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
1173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  cmsUInt32Number nProfiles,
1174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  cmsUInt32Number InputFormat,
1175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  cmsUInt32Number OutputFormat,
1176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  cmsUInt32Number Intent,
1177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  cmsUInt32Number dwFlags)
1178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nProfiles <= 0 || nProfiles > 255) {
1181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         cmsSignalError(NULL, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles);
1182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         return NULL;
1183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return cmsCreateMultiprofileTransformTHR(cmsGetProfileContextID(hProfiles[0]),
1186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  hProfiles,
1187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  nProfiles,
1188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  InputFormat,
1189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  OutputFormat,
1190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  Intent,
1191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  dwFlags);
1192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1194ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHTRANSFORM CMSEXPORT cmsCreateTransformTHR(cmsContext ContextID,
1195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                              cmsHPROFILE Input,
1196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                              cmsUInt32Number InputFormat,
1197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                              cmsHPROFILE Output,
1198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                              cmsUInt32Number OutputFormat,
1199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                              cmsUInt32Number Intent,
1200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                              cmsUInt32Number dwFlags)
1201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsHPROFILE hArray[2];
1204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    hArray[0] = Input;
1206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    hArray[1] = Output;
1207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return cmsCreateMultiprofileTransformTHR(ContextID, hArray, Output == NULL ? 1 : 2, InputFormat, OutputFormat, Intent, dwFlags);
1209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1211ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsHPROFILE Input,
1212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  cmsUInt32Number InputFormat,
1213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  cmsHPROFILE Output,
1214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  cmsUInt32Number OutputFormat,
1215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  cmsUInt32Number Intent,
1216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                  cmsUInt32Number dwFlags)
1217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return cmsCreateTransformTHR(cmsGetProfileContextID(Input), Input, InputFormat, Output, OutputFormat, Intent, dwFlags);
1219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1222ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHTRANSFORM CMSEXPORT cmsCreateProofingTransformTHR(cmsContext ContextID,
1223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsHPROFILE InputProfile,
1224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number InputFormat,
1225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsHPROFILE OutputProfile,
1226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number OutputFormat,
1227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsHPROFILE ProofingProfile,
1228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number nIntent,
1229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number ProofingIntent,
1230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number dwFlags)
1231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsHPROFILE hArray[4];
1233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number Intents[4];
1234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsBool  BPC[4];
1235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number Adaptation[4];
1236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsBool  DoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION) ? TRUE : FALSE;
1237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    hArray[0]  = InputProfile; hArray[1] = ProofingProfile; hArray[2]  = ProofingProfile;               hArray[3] = OutputProfile;
1240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Intents[0] = nIntent;      Intents[1] = nIntent;        Intents[2] = INTENT_RELATIVE_COLORIMETRIC;  Intents[3] = ProofingIntent;
1241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BPC[0]     = DoBPC;        BPC[1] = DoBPC;              BPC[2] = 0;                                 BPC[3] = 0;
1242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationStateTHR(ContextID, -1);
1244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK)))
1246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return cmsCreateTransformTHR(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags);
1247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return cmsCreateExtendedTransform(ContextID, 4, hArray, BPC, Intents, Adaptation,
1249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                        ProofingProfile, 1, InputFormat, OutputFormat, dwFlags);
1250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1254ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHTRANSFORM CMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
1255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number InputFormat,
1256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsHPROFILE OutputProfile,
1257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number OutputFormat,
1258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsHPROFILE ProofingProfile,
1259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number nIntent,
1260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number ProofingIntent,
1261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   cmsUInt32Number dwFlags)
1262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return cmsCreateProofingTransformTHR(cmsGetProfileContextID(InputProfile),
1264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   InputProfile,
1265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   InputFormat,
1266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   OutputProfile,
1267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   OutputFormat,
1268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   ProofingProfile,
1269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   nIntent,
1270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   ProofingIntent,
1271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                                   dwFlags);
1272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed
1276ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform)
1277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
1279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (xform == NULL) return NULL;
1281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return xform -> ContextID;
1282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Grab the input/output formats
1285ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetTransformInputFormat(cmsHTRANSFORM hTransform)
1286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
1288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (xform == NULL) return 0;
1290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return xform->InputFormat;
1291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1293ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsHTRANSFORM hTransform)
1294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
1296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (xform == NULL) return 0;
1298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return xform->OutputFormat;
1299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// For backwards compatibility
1302ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform,
1303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                         cmsUInt32Number InputFormat,
1304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                         cmsUInt32Number OutputFormat)
1305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
1307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFormatter16 FromInput, ToOutput;
1308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // We only can afford to change formatters if previous transform is at least 16 bits
1311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!(xform ->dwOriginalFlags & cmsFLAGS_CAN_CHANGE_FORMATTER)) {
1312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(xform ->ContextID, cmsERROR_NOT_SUITABLE, "cmsChangeBuffersFormat works only on transforms created originally with at least 16 bits of precision");
1314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FromInput = _cmsGetFormatter(xform->ContextID, InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
1318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ToOutput  = _cmsGetFormatter(xform->ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
1319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (FromInput == NULL || ToOutput == NULL) {
1321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(xform -> ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
1323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xform ->InputFormat  = InputFormat;
1327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xform ->OutputFormat = OutputFormat;
1328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xform ->FromInput    = FromInput;
1329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xform ->ToOutput     = ToOutput;
1330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1332