Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/lcms2mt/src/cmsxform.c
Line
Count
Source (jump to first uncovered line)
1
//---------------------------------------------------------------------------------
2
//
3
//  Little Color Management System
4
//  Copyright (c) 1998-2020 Marti Maria Saguer
5
//
6
// Permission is hereby granted, free of charge, to any person obtaining
7
// a copy of this software and associated documentation files (the "Software"),
8
// to deal in the Software without restriction, including without limitation
9
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
// and/or sell copies of the Software, and to permit persons to whom the Software
11
// is furnished to do so, subject to the following conditions:
12
//
13
// The above copyright notice and this permission notice shall be included in
14
// all copies or substantial portions of the Software.
15
//
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
//
24
//---------------------------------------------------------------------------------
25
//
26
27
#include "lcms2_internal.h"
28
29
#ifdef WITH_CAL
30
#include "cal_cms.h"
31
#endif
32
33
// Transformations stuff
34
// -----------------------------------------------------------------------
35
36
89.2k
#define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0
37
38
// The Context0 observer adaptation state.
39
_cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE };
40
41
// Init and duplicate observer adaptation state
42
void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx,
43
                                   const struct _cmsContext_struct* src)
44
89.2k
{
45
89.2k
    static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE };
46
89.2k
    void* from;
47
48
89.2k
    if (src != NULL) {
49
0
        from = src ->chunks[AdaptationStateContext];
50
0
    }
51
89.2k
    else {
52
89.2k
       from = &AdaptationStateChunk;
53
89.2k
    }
54
55
89.2k
    ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType));
56
89.2k
}
57
58
59
// Sets adaptation state for absolute colorimetric intent in the given context.  Adaptation state applies on all
60
// but cmsCreateExtendedTransform().  Little CMS can handle incomplete adaptation states.
61
// The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine
62
cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsContext ContextID, cmsFloat64Number d)
63
2.47M
{
64
2.47M
    cmsFloat64Number prev;
65
2.47M
    _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext);
66
67
    // Get previous value for return
68
2.47M
    prev = ptr ->AdaptationState;
69
70
    // Set the value if d is positive or zero
71
2.47M
    if (d >= 0.0) {
72
73
0
        ptr ->AdaptationState = d;
74
0
    }
75
76
    // Always return previous value
77
2.47M
    return prev;
78
2.47M
}
79
80
81
// -----------------------------------------------------------------------
82
83
// Alarm codes for 16-bit transformations, because the fixed range of containers there are
84
// no values left to mark out of gamut.
85
86
89.2k
#define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
87
88
_cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE };
89
90
// Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be
91
// encoded in 16 bits.
92
void CMSEXPORT cmsSetAlarmCodes(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS])
93
0
{
94
0
    _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext);
95
96
0
    _cmsAssert(ContextAlarmCodes != NULL); // Can't happen
97
98
0
    memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes));
99
0
}
100
101
// Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context.
102
// Values are meant to be encoded in 16 bits.
103
void CMSEXPORT cmsGetAlarmCodes(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS])
104
0
{
105
0
    _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext);
106
107
0
    _cmsAssert(ContextAlarmCodes != NULL); // Can't happen
108
109
0
    memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes));
110
0
}
111
112
113
// Init and duplicate alarm codes
114
void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx,
115
                              const struct _cmsContext_struct* src)
116
89.2k
{
117
89.2k
    static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE };
118
89.2k
    void* from;
119
120
89.2k
    if (src != NULL) {
121
0
        from = src ->chunks[AlarmCodesContext];
122
0
    }
123
89.2k
    else {
124
89.2k
       from = &AlarmCodesChunk;
125
89.2k
    }
126
127
89.2k
    ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType));
128
89.2k
}
129
130
// -----------------------------------------------------------------------
131
132
// Get rid of transform resources
133
void CMSEXPORT cmsDeleteTransform(cmsContext ContextID, cmsHTRANSFORM hTransform)
134
516k
{
135
516k
    _cmsTRANSFORM* p = (_cmsTRANSFORM*) hTransform;
136
516k
    _cmsTRANSFORMCORE *core;
137
516k
    cmsUInt32Number refs;
138
139
516k
    if (p == NULL)
140
0
        return;
141
142
516k
    core = p->core;
143
144
516k
    _cmsAssert(core != NULL);
145
146
516k
    refs = _cmsAdjustReferenceCount(&core->refs, -1);
147
516k
    _cmsFree(ContextID, (void *) p);
148
149
516k
    if (refs != 0)
150
1.57k
        return;
151
152
514k
    if (core->GamutCheck)
153
0
        cmsPipelineFree(ContextID, core->GamutCheck);
154
155
514k
    if (core->Lut)
156
514k
        cmsPipelineFree(ContextID, core->Lut);
157
158
514k
    if (core->InputColorant)
159
0
        cmsFreeNamedColorList(ContextID, core->InputColorant);
160
161
514k
    if (core->OutputColorant)
162
0
        cmsFreeNamedColorList(ContextID, core->OutputColorant);
163
164
514k
    if (core->Sequence)
165
0
        cmsFreeProfileSequenceDescription(ContextID, core->Sequence);
166
167
514k
    if (core->UserData)
168
0
        core->FreeUserData(ContextID, core->UserData);
169
170
514k
    _cmsFree(ContextID, (void *)core);
171
514k
}
172
173
174
static
175
cmsUInt32Number PixelSize(cmsUInt32Number Format)
176
118M
{
177
118M
    cmsUInt32Number fmt_bytes = T_BYTES(Format);
178
179
    // For double, the T_BYTES field is zero
180
118M
    if (fmt_bytes == 0)
181
1.37M
        return sizeof(cmsUInt64Number);
182
183
    // Otherwise, it is already correct for all formats
184
117M
    return fmt_bytes;
185
118M
}
186
187
188
189
190
// Apply transform.
191
void CMSEXPORT cmsDoTransform(cmsContext ContextID, cmsHTRANSFORM  Transform,
192
                              const void* InputBuffer,
193
                              void* OutputBuffer,
194
                              cmsUInt32Number Size)
195
196
59.2M
{
197
59.2M
    _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
198
59.2M
    cmsStride stride;
199
200
59.2M
    stride.BytesPerLineIn = 0;  // Not used
201
59.2M
    stride.BytesPerLineOut = 0;
202
59.2M
    stride.BytesPerPlaneIn = Size * PixelSize(p->InputFormat);
203
59.2M
    stride.BytesPerPlaneOut = Size * PixelSize(p->OutputFormat);
204
205
59.2M
    p -> xform(ContextID, p, InputBuffer, OutputBuffer, Size, 1, &stride);
206
59.2M
}
207
208
209
// This is a legacy stride for planar
210
void CMSEXPORT cmsDoTransformStride(cmsContext ContextID, cmsHTRANSFORM  Transform,
211
                              const void* InputBuffer,
212
                              void* OutputBuffer,
213
                              cmsUInt32Number Size, cmsUInt32Number Stride)
214
215
0
{
216
0
    _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
217
0
    cmsStride stride;
218
219
0
    stride.BytesPerLineIn = 0;
220
0
    stride.BytesPerLineOut = 0;
221
0
    stride.BytesPerPlaneIn = Stride;
222
0
    stride.BytesPerPlaneOut = Stride;
223
224
0
    p -> xform(ContextID, p, InputBuffer, OutputBuffer, Size, 1, &stride);
225
0
}
226
227
// This is the "fast" function for plugins
228
void CMSEXPORT cmsDoTransformLineStride(cmsContext ContextID, cmsHTRANSFORM  Transform,
229
                              const void* InputBuffer,
230
                              void* OutputBuffer,
231
                              cmsUInt32Number PixelsPerLine,
232
                              cmsUInt32Number LineCount,
233
                              cmsUInt32Number BytesPerLineIn,
234
                              cmsUInt32Number BytesPerLineOut,
235
                              cmsUInt32Number BytesPerPlaneIn,
236
                              cmsUInt32Number BytesPerPlaneOut)
237
238
908k
{
239
908k
    _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
240
908k
    cmsStride stride;
241
242
908k
    stride.BytesPerLineIn = BytesPerLineIn;
243
908k
    stride.BytesPerLineOut = BytesPerLineOut;
244
908k
    stride.BytesPerPlaneIn = BytesPerPlaneIn;
245
908k
    stride.BytesPerPlaneOut = BytesPerPlaneOut;
246
247
908k
    p->xform(ContextID, p, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, &stride);
248
908k
}
249
250
251
252
// Transform routines ----------------------------------------------------------------------------------------------------------
253
254
// Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check.
255
// Note that because extended range, we can use a -1.0 value for out of gamut in this case.
256
static
257
void FloatXFORM(cmsContext ContextID, _cmsTRANSFORM* p,
258
                const void* in,
259
                void* out,
260
                cmsUInt32Number PixelsPerLine,
261
                cmsUInt32Number LineCount,
262
                const cmsStride* Stride)
263
518k
{
264
518k
    cmsUInt8Number* accum;
265
518k
    cmsUInt8Number* output;
266
518k
    cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS];
267
518k
    cmsFloat32Number OutOfGamut;
268
518k
    cmsUInt32Number i, j, c, strideIn, strideOut;
269
518k
    _cmsTRANSFORMCORE *core = p->core;
270
271
518k
    _cmsHandleExtraChannels(ContextID, p, in, out, PixelsPerLine, LineCount, Stride);
272
273
518k
    strideIn = 0;
274
518k
    strideOut = 0;
275
518k
    memset(fIn, 0, sizeof(fIn));
276
518k
    memset(fOut, 0, sizeof(fOut));
277
278
1.03M
    for (i = 0; i < LineCount; i++) {
279
280
518k
        accum = (cmsUInt8Number*)in + strideIn;
281
518k
        output = (cmsUInt8Number*)out + strideOut;
282
283
1.03M
        for (j = 0; j < PixelsPerLine; j++) {
284
285
518k
            accum = p->FromInputFloat(ContextID, p, fIn, accum, Stride->BytesPerPlaneIn);
286
287
            // Any gamut chack to do?
288
518k
            if (core->GamutCheck != NULL) {
289
290
                // Evaluate gamut marker.
291
0
                cmsPipelineEvalFloat(ContextID, fIn, &OutOfGamut, core->GamutCheck);
292
293
                // Is current color out of gamut?
294
0
                if (OutOfGamut > 0.0) {
295
296
                    // Certainly, out of gamut
297
0
                    for (c = 0; c < cmsMAXCHANNELS; c++)
298
0
                        fOut[c] = -1.0;
299
300
0
                }
301
0
                else {
302
                    // No, proceed normally
303
0
                    cmsPipelineEvalFloat(ContextID, fIn, fOut, core->Lut);
304
0
                }
305
0
            }
306
518k
            else {
307
308
                // No gamut check at all
309
518k
                cmsPipelineEvalFloat(ContextID, fIn, fOut, core->Lut);
310
518k
            }
311
312
313
518k
            output = p->ToOutputFloat(ContextID, p, fOut, output, Stride->BytesPerPlaneOut);
314
518k
        }
315
316
518k
        strideIn += Stride->BytesPerLineIn;
317
518k
        strideOut += Stride->BytesPerLineOut;
318
518k
    }
319
320
518k
}
321
322
323
static
324
void NullFloatXFORM(cmsContext ContextID, _cmsTRANSFORM* p,
325
                    const void* in,
326
                    void* out,
327
                    cmsUInt32Number PixelsPerLine,
328
                    cmsUInt32Number LineCount,
329
                    const cmsStride* Stride)
330
331
0
{
332
0
    cmsUInt8Number* accum;
333
0
    cmsUInt8Number* output;
334
0
    cmsFloat32Number fIn[cmsMAXCHANNELS];
335
0
    cmsUInt32Number i, j, strideIn, strideOut;
336
337
0
    _cmsHandleExtraChannels(ContextID, p, in, out, PixelsPerLine, LineCount, Stride);
338
339
0
    strideIn = 0;
340
0
    strideOut = 0;
341
0
    memset(fIn, 0, sizeof(fIn));
342
343
0
    for (i = 0; i < LineCount; i++) {
344
345
0
           accum = (cmsUInt8Number*) in + strideIn;
346
0
           output = (cmsUInt8Number*) out + strideOut;
347
348
0
           for (j = 0; j < PixelsPerLine; j++) {
349
350
0
                  accum = p->FromInputFloat(ContextID, p, fIn, accum, Stride ->BytesPerPlaneIn);
351
0
                  output = p->ToOutputFloat(ContextID, p, fIn, output, Stride->BytesPerPlaneOut);
352
0
           }
353
354
0
           strideIn += Stride->BytesPerLineIn;
355
0
           strideOut += Stride->BytesPerLineOut;
356
0
    }
357
0
}
358
359
cmsINLINE int mul255(cmsUInt32Number a, cmsUInt32Number b)
360
0
{
361
  /* see Jim Blinn's book "Dirty Pixels" for how this works */
362
0
  cmsUInt32Number x = a * b + 128;
363
0
  x += x >> 8;
364
0
  return x >> 8;
365
0
}
366
367
cmsINLINE cmsUInt32Number mul65535(cmsUInt32Number a, cmsUInt32Number b)
368
0
{
369
  /* see Jim Blinn's book "Dirty Pixels" for how this works */
370
0
  cmsUInt32Number x = a * b + 0x8000;
371
0
  x += x >> 16;
372
0
  return x >> 16;
373
0
}
374
375
// 16 bit precision -----------------------------------------------------------------------------------------------------------
376
377
// Null transformation, only applies formatters. No cache
378
static
379
void NullXFORM(cmsContext ContextID,
380
               _cmsTRANSFORM* p,
381
               const void* in,
382
               void* out,
383
               cmsUInt32Number PixelsPerLine,
384
               cmsUInt32Number LineCount,
385
               const cmsStride* Stride)
386
0
{
387
0
    cmsUInt8Number* accum;
388
0
    cmsUInt8Number* output;
389
0
    cmsUInt16Number wIn[cmsMAXCHANNELS];
390
0
    cmsUInt32Number i, j, strideIn, strideOut;
391
392
0
    _cmsHandleExtraChannels(ContextID, p, in, out, PixelsPerLine, LineCount, Stride);
393
394
0
    strideIn = 0;
395
0
    strideOut = 0;
396
0
    memset(wIn, 0, sizeof(wIn));
397
398
0
    for (i = 0; i < LineCount; i++) {
399
400
0
           accum = (cmsUInt8Number*)in + strideIn;
401
0
           output = (cmsUInt8Number*)out + strideOut;
402
403
0
           for (j = 0; j < PixelsPerLine; j++) {
404
405
0
                  accum = p->FromInput(ContextID, p, wIn, accum, Stride->BytesPerPlaneIn);
406
0
                  output = p->ToOutput(ContextID, p, wIn, output, Stride->BytesPerPlaneOut);
407
0
    }
408
409
0
           strideIn += Stride->BytesPerLineIn;
410
0
           strideOut += Stride->BytesPerLineOut;
411
0
    }
412
413
0
}
414
415
416
// No gamut check, no cache, 16 bits
417
#define FUNCTION_NAME PrecalculatedXFORM
418
#include "extra_xform.h"
419
420
// No gamut check, no cache, 16 bits
421
#define PREALPHA
422
#define FUNCTION_NAME PrecalculatedXFORM_P
423
#include "extra_xform.h"
424
425
// No gamut check, no cache, Identity transform, including pack/unpack
426
static
427
void PrecalculatedXFORMIdentity(cmsContext ContextID,
428
                                _cmsTRANSFORM* p,
429
                                const void* in,
430
                                void* out,
431
                                cmsUInt32Number PixelsPerLine,
432
                                cmsUInt32Number LineCount,
433
                                const cmsStride* Stride)
434
15.9M
{
435
15.9M
    cmsUInt32Number bpli = Stride->BytesPerLineIn;
436
15.9M
    cmsUInt32Number bplo = Stride->BytesPerLineOut;
437
15.9M
    int bpp;
438
15.9M
    cmsUNUSED_PARAMETER(ContextID);
439
440
    /* Silence some warnings */
441
15.9M
    (void)bpli;
442
15.9M
    (void)bplo;
443
444
15.9M
    if ((in == out && bpli == bplo) || PixelsPerLine == 0)
445
0
        return;
446
447
15.9M
    bpp = T_BYTES(p->InputFormat);
448
15.9M
    if (bpp == 0)
449
0
        bpp = sizeof(double);
450
15.9M
    bpp *= T_CHANNELS(p->InputFormat) + T_EXTRA(p->InputFormat);
451
15.9M
    PixelsPerLine *= bpp; /* Convert to BytesPerLine */
452
31.8M
    while (LineCount-- > 0)
453
15.9M
    {
454
15.9M
        memmove(out, in, PixelsPerLine);
455
15.9M
        in = (void *)((cmsUInt8Number *)in + bpli);
456
15.9M
        out = (void *)((cmsUInt8Number *)out + bplo);
457
15.9M
    }
458
15.9M
}
459
460
static
461
void PrecalculatedXFORMIdentityPlanar(cmsContext ContextID,
462
                                      _cmsTRANSFORM* p,
463
                                      const void* in,
464
                                      void* out,
465
                                      cmsUInt32Number PixelsPerLine,
466
                                      cmsUInt32Number LineCount,
467
                                      const cmsStride* Stride)
468
0
{
469
0
    cmsUInt32Number bpli = Stride->BytesPerLineIn;
470
0
    cmsUInt32Number bplo = Stride->BytesPerLineOut;
471
0
    cmsUInt32Number bppi = Stride->BytesPerPlaneIn;
472
0
    cmsUInt32Number bppo = Stride->BytesPerPlaneOut;
473
0
    int bpp;
474
0
    int planes;
475
0
    const void *plane_in;
476
0
    void *plane_out;
477
0
    cmsUNUSED_PARAMETER(ContextID);
478
479
    /* Silence some warnings */
480
0
    (void)bpli;
481
0
    (void)bplo;
482
0
    (void)bppi;
483
0
    (void)bppo;
484
485
0
    if ((in == out && bpli == bplo && bppi == bppo) || PixelsPerLine == 0)
486
0
        return;
487
488
0
    bpp = T_BYTES(p->InputFormat);
489
0
    if (bpp == 0)
490
0
        bpp = sizeof(double);
491
0
    PixelsPerLine *= bpp; /* Convert to BytesPerLine */
492
0
    planes = T_CHANNELS(p->InputFormat) + T_EXTRA(p->InputFormat);
493
0
    while (planes-- > 0)
494
0
    {
495
0
        plane_in = in;
496
0
        plane_out = out;
497
0
        while (LineCount-- > 0)
498
0
        {
499
0
            memmove(plane_out, plane_in, PixelsPerLine);
500
0
            plane_in = (void *)((cmsUInt8Number *)plane_in + bpli);
501
0
            plane_out = (void *)((cmsUInt8Number *)plane_out + bplo);
502
0
        }
503
0
        in = (void *)((cmsUInt8Number *)in + bppi);
504
0
        out = (void *)((cmsUInt8Number *)out + bppo);
505
0
    }
506
0
}
507
508
// Auxiliary: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical.
509
static
510
void TransformOnePixelWithGamutCheck(cmsContext ContextID, _cmsTRANSFORM* p,
511
                                     const cmsUInt16Number wIn[],
512
                                     cmsUInt16Number wOut[])
513
0
{
514
0
    cmsUInt16Number wOutOfGamut;
515
0
    _cmsTRANSFORMCORE *core = p->core;
516
517
0
    core->GamutCheck->Eval16Fn(ContextID, wIn, &wOutOfGamut, core->GamutCheck->Data);
518
0
    if (wOutOfGamut >= 1) {
519
520
0
        cmsUInt32Number i;
521
0
        cmsUInt32Number n = core->Lut->OutputChannels;
522
0
        _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext);
523
524
0
        for (i=0; i < n; i++) {
525
526
0
            wOut[i] = ContextAlarmCodes ->AlarmCodes[i];
527
0
        }
528
0
    }
529
0
    else
530
0
        core->Lut->Eval16Fn(ContextID, wIn, wOut, core->Lut->Data);
531
0
}
532
533
// Gamut check, No cache, 16 bits.
534
#define FUNCTION_NAME PrecalculatedXFORMGamutCheck
535
#define GAMUTCHECK
536
#include "extra_xform.h"
537
538
// Gamut check, No cache, 16 bits.
539
#define FUNCTION_NAME PrecalculatedXFORMGamutCheck_P
540
#define PREALPHA
541
#define GAMUTCHECK
542
#include "extra_xform.h"
543
544
// No gamut check, Cache, 16 bits,
545
#define FUNCTION_NAME CachedXFORM
546
#define CACHED
547
#include "extra_xform.h"
548
549
// All those nice features together
550
#define FUNCTION_NAME CachedXFORMGamutCheck
551
#define CACHED
552
#define GAMUTCHECK
553
#include "extra_xform.h"
554
555
// All those nice features together
556
#define FUNCTION_NAME CachedXFORMGamutCheck_P
557
#define CACHED
558
#define PREALPHA
559
#define GAMUTCHECK
560
#include "extra_xform.h"
561
562
// No gamut check, Cache, 16 bits, <= 4 bytes
563
#define FUNCTION_NAME CachedXFORM4
564
#define CACHED
565
#define CMPBYTES 4
566
0
#define NUMEXTRAS 0
567
#include "extra_xform.h"
568
569
// No gamut check, Cache, 16 bits, <= 8 bytes total
570
#define FUNCTION_NAME CachedXFORM8
571
#define CACHED
572
#define CMPBYTES 8
573
4.01k
#define NUMEXTRAS 0
574
#include "extra_xform.h"
575
576
// Special ones for common cases.
577
#define FUNCTION_NAME CachedXFORM1to1
578
#define CACHED
579
0
#define INPACKEDSAMPLESIZE 1
580
0
#define OUTPACKEDSAMPLESIZE 1
581
0
#define NUMINCHANNELS 1
582
0
#define NUMOUTCHANNELS 1
583
0
#define NUMEXTRAS 0
584
0
#define UNPACK(CTX,T,D,S,Z,A)              \
585
0
do {                                       \
586
0
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
587
0
} while (0)
588
0
#define PACK(CTX,T,S,D,Z,A)        \
589
0
do {                               \
590
0
    *(D)++ = FROM_16_TO_8((S)[0]); \
591
0
} while (0)
592
#include "extra_xform.h"
593
594
#define FUNCTION_NAME CachedXFORM1x2to1x2
595
#define CACHED
596
293k
#define INPACKEDSAMPLESIZE 2
597
293k
#define OUTPACKEDSAMPLESIZE 2
598
293k
#define NUMINCHANNELS 1
599
293k
#define NUMOUTCHANNELS 1
600
293k
#define NUMEXTRAS 0
601
293k
#define UNPACK(CTX,T,D,S,Z,A)                      \
602
293k
do {                                               \
603
293k
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
604
293k
} while (0)
605
293k
#define PACK(CTX,T,S,D,Z,A)                     \
606
293k
do {                                            \
607
293k
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
608
293k
} while (0)
609
#include "extra_xform.h"
610
611
#define FUNCTION_NAME CachedXFORM1to3
612
#define CACHED
613
0
#define INPACKEDSAMPLESIZE 1
614
0
#define OUTPACKEDSAMPLESIZE 1
615
0
#define NUMINCHANNELS 1
616
0
#define NUMOUTCHANNELS 3
617
0
#define NUMEXTRAS 0
618
0
#define UNPACK(CTX,T,D,S,Z,A)              \
619
0
do {                                       \
620
0
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
621
0
} while (0)
622
0
#define PACK(CTX,T,S,D,Z,A)        \
623
0
do {                               \
624
0
    *(D)++ = FROM_16_TO_8((S)[0]); \
625
0
    *(D)++ = FROM_16_TO_8((S)[1]); \
626
0
    *(D)++ = FROM_16_TO_8((S)[2]); \
627
0
} while (0)
628
#include "extra_xform.h"
629
630
#define FUNCTION_NAME CachedXFORM1x2to3x2
631
#define CACHED
632
8.51M
#define INPACKEDSAMPLESIZE 2
633
8.51M
#define OUTPACKEDSAMPLESIZE 2
634
8.51M
#define NUMINCHANNELS 1
635
8.51M
#define NUMOUTCHANNELS 3
636
8.51M
#define NUMEXTRAS 0
637
8.51M
#define UNPACK(CTX,T,D,S,Z,A)                      \
638
8.51M
do {                                               \
639
8.51M
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
640
8.51M
} while (0)
641
8.51M
#define PACK(CTX,T,S,D,Z,A)                     \
642
8.51M
do {                                            \
643
8.51M
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
644
8.51M
    *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
645
8.51M
    *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
646
8.51M
} while (0)
647
#include "extra_xform.h"
648
649
#define FUNCTION_NAME CachedXFORM1to4
650
#define CACHED
651
29
#define INPACKEDSAMPLESIZE 1
652
29
#define OUTPACKEDSAMPLESIZE 1
653
29
#define NUMINCHANNELS 1
654
29
#define NUMOUTCHANNELS 4
655
29
#define NUMEXTRAS 0
656
7.42k
#define UNPACK(CTX,T,D,S,Z,A)              \
657
7.42k
do {                                       \
658
7.42k
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
659
7.42k
} while (0)
660
7.42k
#define PACK(CTX,T,S,D,Z,A)        \
661
7.42k
do {                               \
662
7.42k
    *(D)++ = FROM_16_TO_8((S)[0]); \
663
7.42k
    *(D)++ = FROM_16_TO_8((S)[1]); \
664
7.42k
    *(D)++ = FROM_16_TO_8((S)[2]); \
665
7.42k
    *(D)++ = FROM_16_TO_8((S)[3]); \
666
7.42k
} while (0)
667
#include "extra_xform.h"
668
669
#define FUNCTION_NAME CachedXFORM1x2to4x2
670
#define CACHED
671
399k
#define INPACKEDSAMPLESIZE 2
672
399k
#define OUTPACKEDSAMPLESIZE 2
673
399k
#define NUMINCHANNELS 1
674
399k
#define NUMOUTCHANNELS 4
675
399k
#define NUMEXTRAS 0
676
399k
#define UNPACK(CTX,T,D,S,Z,A)                      \
677
399k
do {                                               \
678
399k
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
679
399k
} while (0)
680
399k
#define PACK(CTX,T,S,D,Z,A)                     \
681
399k
do {                                            \
682
399k
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
683
399k
    *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
684
399k
    *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
685
399k
    *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \
686
399k
} while (0)
687
#include "extra_xform.h"
688
689
#define FUNCTION_NAME CachedXFORM3to1
690
#define CACHED
691
151k
#define INPACKEDSAMPLESIZE 1
692
151k
#define OUTPACKEDSAMPLESIZE 1
693
151k
#define NUMINCHANNELS 3
694
151k
#define NUMOUTCHANNELS 1
695
151k
#define NUMEXTRAS 0
696
83.0M
#define UNPACK(CTX,T,D,S,Z,A)               \
697
83.0M
do {                                        \
698
83.0M
        (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
699
83.0M
        (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
700
83.0M
        (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
701
83.0M
} while (0)
702
83.0M
#define PACK(CTX,T,S,D,Z,A)        \
703
83.0M
do {                               \
704
83.0M
    *(D)++ = FROM_16_TO_8((S)[0]); \
705
83.0M
} while (0)
706
#include "extra_xform.h"
707
708
#define FUNCTION_NAME CachedXFORM3x2to1x2
709
#define CACHED
710
242k
#define INPACKEDSAMPLESIZE 2
711
242k
#define OUTPACKEDSAMPLESIZE 2
712
242k
#define NUMINCHANNELS 3
713
242k
#define NUMOUTCHANNELS 1
714
242k
#define NUMEXTRAS 0
715
242k
#define UNPACK(CTX,T,D,S,Z,A)                       \
716
242k
do {                                                \
717
242k
        (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
718
242k
        (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
719
242k
        (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
720
242k
} while (0)
721
242k
#define PACK(CTX,T,S,D,Z,A)                     \
722
242k
do {                                            \
723
242k
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
724
242k
} while (0)
725
#include "extra_xform.h"
726
727
#define FUNCTION_NAME CachedXFORM3to3
728
#define CACHED
729
349k
#define INPACKEDSAMPLESIZE 1
730
349k
#define OUTPACKEDSAMPLESIZE 1
731
349k
#define NUMINCHANNELS 3
732
349k
#define NUMOUTCHANNELS 3
733
349k
#define NUMEXTRAS 0
734
66.5M
#define UNPACK(CTX,T,D,S,Z,A)              \
735
66.5M
do {                                       \
736
66.5M
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
737
66.5M
       (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
738
66.5M
       (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
739
66.5M
} while (0)
740
66.5M
#define PACK(CTX,T,S,D,Z,A)        \
741
66.5M
do {                               \
742
66.5M
    *(D)++ = FROM_16_TO_8((S)[0]); \
743
66.5M
    *(D)++ = FROM_16_TO_8((S)[1]); \
744
66.5M
    *(D)++ = FROM_16_TO_8((S)[2]); \
745
66.5M
} while (0)
746
#include "extra_xform.h"
747
748
#define FUNCTION_NAME CachedXFORM3x2to3x2
749
#define CACHED
750
564k
#define INPACKEDSAMPLESIZE 2
751
564k
#define OUTPACKEDSAMPLESIZE 2
752
564k
#define NUMINCHANNELS 3
753
564k
#define NUMOUTCHANNELS 3
754
564k
#define NUMEXTRAS 0
755
564k
#define UNPACK(CTX,T,D,S,Z,A)                      \
756
564k
do {                                               \
757
564k
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
758
564k
       (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
759
564k
       (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
760
564k
} while (0)
761
564k
#define PACK(CTX,T,S,D,Z,A)                     \
762
564k
do {                                            \
763
564k
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
764
564k
    *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
765
564k
    *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
766
564k
} while (0)
767
#include "extra_xform.h"
768
769
#define FUNCTION_NAME CachedXFORM3to4
770
#define CACHED
771
38
#define INPACKEDSAMPLESIZE 1
772
38
#define OUTPACKEDSAMPLESIZE 1
773
38
#define NUMINCHANNELS 3
774
38
#define NUMOUTCHANNELS 4
775
38
#define NUMEXTRAS 0
776
9.72k
#define UNPACK(CTX,T,D,S,Z,A)              \
777
9.72k
do {                                       \
778
9.72k
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
779
9.72k
       (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
780
9.72k
       (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
781
9.72k
} while (0)
782
9.72k
#define PACK(CTX,T,S,D,Z,A)        \
783
9.72k
do {                               \
784
9.72k
    *(D)++ = FROM_16_TO_8((S)[0]); \
785
9.72k
    *(D)++ = FROM_16_TO_8((S)[1]); \
786
9.72k
    *(D)++ = FROM_16_TO_8((S)[2]); \
787
9.72k
    *(D)++ = FROM_16_TO_8((S)[3]); \
788
9.72k
} while (0)
789
#include "extra_xform.h"
790
791
#define FUNCTION_NAME CachedXFORM3x2to4x2
792
#define CACHED
793
14.7M
#define INPACKEDSAMPLESIZE 2
794
14.7M
#define OUTPACKEDSAMPLESIZE 2
795
14.7M
#define NUMINCHANNELS 3
796
14.7M
#define NUMOUTCHANNELS 4
797
14.7M
#define NUMEXTRAS 0
798
14.7M
#define UNPACK(CTX,T,D,S,Z,A)                      \
799
14.7M
do {                                               \
800
14.7M
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
801
14.7M
       (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
802
14.7M
       (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
803
14.7M
} while (0)
804
14.7M
#define PACK(CTX,T,S,D,Z,A)                     \
805
14.7M
do {                                            \
806
14.7M
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
807
14.7M
    *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
808
14.7M
    *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
809
14.7M
    *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \
810
14.7M
} while (0)
811
#include "extra_xform.h"
812
813
#define FUNCTION_NAME CachedXFORM4to1
814
#define CACHED
815
207k
#define INPACKEDSAMPLESIZE 1
816
207k
#define OUTPACKEDSAMPLESIZE 1
817
207k
#define NUMINCHANNELS 4
818
207k
#define NUMOUTCHANNELS 1
819
207k
#define NUMEXTRAS 0
820
105M
#define UNPACK(CTX,T,D,S,Z,A)              \
821
105M
do {                                       \
822
105M
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
823
105M
       (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
824
105M
       (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
825
105M
       (D)[3] = FROM_8_TO_16(*(S)); (S)++; \
826
105M
} while (0)
827
105M
#define PACK(CTX,T,S,D,Z,A)        \
828
105M
do {                               \
829
105M
    *(D)++ = FROM_16_TO_8((S)[0]); \
830
105M
} while (0)
831
#include "extra_xform.h"
832
833
#define FUNCTION_NAME CachedXFORM4x2to1x2
834
#define CACHED
835
203k
#define INPACKEDSAMPLESIZE 2
836
203k
#define OUTPACKEDSAMPLESIZE 2
837
203k
#define NUMINCHANNELS 4
838
203k
#define NUMOUTCHANNELS 1
839
203k
#define NUMEXTRAS 0
840
203k
#define UNPACK(CTX,T,D,S,Z,A)                      \
841
203k
do {                                               \
842
203k
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
843
203k
       (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
844
203k
       (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
845
203k
       (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \
846
203k
} while (0)
847
203k
#define PACK(CTX,T,S,D,Z,A)                     \
848
203k
do {                                            \
849
203k
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
850
203k
} while (0)
851
#include "extra_xform.h"
852
853
#define FUNCTION_NAME CachedXFORM4to3
854
#define CACHED
855
82.4k
#define INPACKEDSAMPLESIZE 1
856
82.4k
#define OUTPACKEDSAMPLESIZE 1
857
82.4k
#define NUMINCHANNELS 4
858
82.4k
#define NUMOUTCHANNELS 3
859
82.4k
#define NUMEXTRAS 0
860
46.7M
#define UNPACK(CTX,T,D,S,Z,A)              \
861
46.7M
do {                                       \
862
46.7M
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
863
46.7M
       (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
864
46.7M
       (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
865
46.7M
       (D)[3] = FROM_8_TO_16(*(S)); (S)++; \
866
46.7M
} while (0)
867
46.7M
#define PACK(CTX,T,S,D,Z,A)        \
868
46.7M
do {                               \
869
46.7M
    *(D)++ = FROM_16_TO_8((S)[0]); \
870
46.7M
    *(D)++ = FROM_16_TO_8((S)[1]); \
871
46.7M
    *(D)++ = FROM_16_TO_8((S)[2]); \
872
46.7M
} while (0)
873
#include "extra_xform.h"
874
875
#define FUNCTION_NAME CachedXFORM4x2to3x2
876
#define CACHED
877
17.4M
#define INPACKEDSAMPLESIZE 2
878
17.4M
#define OUTPACKEDSAMPLESIZE 2
879
17.4M
#define NUMINCHANNELS 4
880
17.4M
#define NUMOUTCHANNELS 3
881
17.4M
#define NUMEXTRAS 0
882
17.4M
#define UNPACK(CTX,T,D,S,Z,A)                      \
883
17.4M
do {                                               \
884
17.4M
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
885
17.4M
       (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
886
17.4M
       (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
887
17.4M
       (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \
888
17.4M
} while (0)
889
17.4M
#define PACK(CTX,T,S,D,Z,A)                     \
890
17.4M
do {                                            \
891
17.4M
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
892
17.4M
    *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
893
17.4M
    *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
894
17.4M
} while (0)
895
#include "extra_xform.h"
896
897
#define FUNCTION_NAME CachedXFORM4to4
898
#define CACHED
899
0
#define INPACKEDSAMPLESIZE 1
900
0
#define OUTPACKEDSAMPLESIZE 1
901
0
#define NUMINCHANNELS 4
902
0
#define NUMOUTCHANNELS 4
903
0
#define NUMEXTRAS 0
904
0
#define UNPACK(CTX,T,D,S,Z,A)              \
905
0
do {                                       \
906
0
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
907
0
       (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
908
0
       (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
909
0
       (D)[3] = FROM_8_TO_16(*(S)); (S)++; \
910
0
} while (0)
911
0
#define PACK(CTX,T,S,D,Z,A)        \
912
0
do {                               \
913
0
    *(D)++ = FROM_16_TO_8((S)[0]); \
914
0
    *(D)++ = FROM_16_TO_8((S)[1]); \
915
0
    *(D)++ = FROM_16_TO_8((S)[2]); \
916
0
    *(D)++ = FROM_16_TO_8((S)[3]); \
917
0
} while (0)
918
#include "extra_xform.h"
919
920
#define FUNCTION_NAME CachedXFORM4x2to4x2
921
#define CACHED
922
0
#define INPACKEDSAMPLESIZE 2
923
0
#define OUTPACKEDSAMPLESIZE 2
924
0
#define NUMINCHANNELS 4
925
0
#define NUMOUTCHANNELS 4
926
0
#define NUMEXTRAS 0
927
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
928
0
do {                                               \
929
0
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
930
0
       (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
931
0
       (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
932
0
       (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \
933
0
} while (0)
934
0
#define PACK(CTX,T,S,D,Z,A)                     \
935
0
do {                                            \
936
0
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
937
0
    *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
938
0
    *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
939
0
    *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \
940
0
} while (0)
941
#include "extra_xform.h"
942
943
// Same again, but with alpha
944
// Special ones for common cases.
945
#define FUNCTION_NAME CachedXFORM1to1_1
946
#define CACHED
947
0
#define INPACKEDSAMPLESIZE 1
948
0
#define OUTPACKEDSAMPLESIZE 1
949
0
#define NUMINCHANNELS 1
950
0
#define NUMOUTCHANNELS 1
951
0
#define NUMEXTRAS 1
952
0
#define UNPACK(CTX,T,D,S,Z,A)              \
953
0
do {                                       \
954
0
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
955
0
} while (0)
956
0
#define PACK(CTX,T,S,D,Z,A)        \
957
0
do {                               \
958
0
    *(D)++ = FROM_16_TO_8((S)[0]); \
959
0
} while (0)
960
#include "extra_xform.h"
961
962
#define FUNCTION_NAME CachedXFORM1x2to1x2_2
963
#define CACHED
964
0
#define INPACKEDSAMPLESIZE 2
965
0
#define OUTPACKEDSAMPLESIZE 2
966
0
#define NUMINCHANNELS 1
967
0
#define NUMOUTCHANNELS 1
968
0
#define NUMEXTRAS 1
969
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
970
0
do {                                               \
971
0
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
972
0
} while (0)
973
0
#define PACK(CTX,T,S,D,Z,A)                     \
974
0
do {                                            \
975
0
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
976
0
} while (0)
977
#include "extra_xform.h"
978
979
#define FUNCTION_NAME CachedXFORM1to3_1
980
#define CACHED
981
0
#define INPACKEDSAMPLESIZE 1
982
0
#define OUTPACKEDSAMPLESIZE 3
983
0
#define NUMINCHANNELS 1
984
0
#define NUMOUTCHANNELS 1
985
0
#define NUMEXTRAS 1
986
0
#define UNPACK(CTX,T,D,S,Z,A)              \
987
0
do {                                       \
988
0
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
989
0
} while (0)
990
0
#define PACK(CTX,T,S,D,Z,A)        \
991
0
do {                               \
992
0
    *(D)++ = FROM_16_TO_8((S)[0]); \
993
0
    *(D)++ = FROM_16_TO_8((S)[1]); \
994
0
    *(D)++ = FROM_16_TO_8((S)[2]); \
995
0
} while (0)
996
#include "extra_xform.h"
997
998
#define FUNCTION_NAME CachedXFORM1x2to3x2_2
999
#define CACHED
1000
0
#define INPACKEDSAMPLESIZE 2
1001
0
#define OUTPACKEDSAMPLESIZE 2
1002
0
#define NUMINCHANNELS 1
1003
0
#define NUMOUTCHANNELS 3
1004
0
#define NUMEXTRAS 1
1005
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1006
0
do {                                               \
1007
0
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1008
0
} while (0)
1009
0
#define PACK(CTX,T,S,D,Z,A)                     \
1010
0
do {                                            \
1011
0
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1012
0
    *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
1013
0
    *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
1014
0
} while (0)
1015
#include "extra_xform.h"
1016
1017
#define FUNCTION_NAME CachedXFORM1to4_1
1018
#define CACHED
1019
0
#define INPACKEDSAMPLESIZE 1
1020
0
#define OUTPACKEDSAMPLESIZE 1
1021
0
#define NUMINCHANNELS 1
1022
0
#define NUMOUTCHANNELS 4
1023
0
#define NUMEXTRAS 1
1024
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1025
0
do {                                       \
1026
0
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1027
0
} while (0)
1028
0
#define PACK(CTX,T,S,D,Z,A)        \
1029
0
do {                               \
1030
0
    *(D)++ = FROM_16_TO_8((S)[0]); \
1031
0
    *(D)++ = FROM_16_TO_8((S)[1]); \
1032
0
    *(D)++ = FROM_16_TO_8((S)[2]); \
1033
0
    *(D)++ = FROM_16_TO_8((S)[3]); \
1034
0
} while (0)
1035
#include "extra_xform.h"
1036
1037
#define FUNCTION_NAME CachedXFORM1x2to4x2_2
1038
#define CACHED
1039
0
#define INPACKEDSAMPLESIZE 2
1040
0
#define OUTPACKEDSAMPLESIZE 2
1041
0
#define NUMINCHANNELS 1
1042
0
#define NUMOUTCHANNELS 4
1043
0
#define NUMEXTRAS 1
1044
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1045
0
do {                                               \
1046
0
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1047
0
} while (0)
1048
0
#define PACK(CTX,T,S,D,Z,A)                     \
1049
0
do {                                            \
1050
0
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1051
0
    *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
1052
0
    *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
1053
0
    *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \
1054
0
} while (0)
1055
#include "extra_xform.h"
1056
1057
#define FUNCTION_NAME CachedXFORM3to1_1
1058
#define CACHED
1059
0
#define INPACKEDSAMPLESIZE 1
1060
0
#define OUTPACKEDSAMPLESIZE 1
1061
0
#define NUMINCHANNELS 3
1062
0
#define NUMOUTCHANNELS 1
1063
0
#define NUMEXTRAS 1
1064
0
#define UNPACK(CTX,T,D,S,Z,A)               \
1065
0
do {                                        \
1066
0
        (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1067
0
        (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
1068
0
        (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
1069
0
} while (0)
1070
0
#define PACK(CTX,T,S,D,Z,A)        \
1071
0
do {                               \
1072
0
    *(D)++ = FROM_16_TO_8((S)[0]); \
1073
0
} while (0)
1074
#include "extra_xform.h"
1075
1076
#define FUNCTION_NAME CachedXFORM3x2to1x2_2
1077
#define CACHED
1078
0
#define INPACKEDSAMPLESIZE 2
1079
0
#define OUTPACKEDSAMPLESIZE 2
1080
0
#define NUMINCHANNELS 3
1081
0
#define NUMOUTCHANNELS 1
1082
0
#define NUMEXTRAS 1
1083
0
#define UNPACK(CTX,T,D,S,Z,A)                       \
1084
0
do {                                                \
1085
0
        (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1086
0
        (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
1087
0
        (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
1088
0
} while (0)
1089
0
#define PACK(CTX,T,S,D,Z,A)                     \
1090
0
do {                                            \
1091
0
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1092
0
} while (0)
1093
#include "extra_xform.h"
1094
1095
#define FUNCTION_NAME CachedXFORM3to3_1
1096
#define CACHED
1097
0
#define INPACKEDSAMPLESIZE 1
1098
0
#define OUTPACKEDSAMPLESIZE 1
1099
0
#define NUMINCHANNELS 3
1100
0
#define NUMOUTCHANNELS 3
1101
0
#define NUMEXTRAS 1
1102
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1103
0
do {                                       \
1104
0
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1105
0
       (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
1106
0
       (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
1107
0
} while (0)
1108
0
#define PACK(CTX,T,S,D,Z,A)        \
1109
0
do {                               \
1110
0
    *(D)++ = FROM_16_TO_8((S)[0]); \
1111
0
    *(D)++ = FROM_16_TO_8((S)[1]); \
1112
0
    *(D)++ = FROM_16_TO_8((S)[2]); \
1113
0
} while (0)
1114
#include "extra_xform.h"
1115
1116
#define FUNCTION_NAME CachedXFORM3x2to3x2_2
1117
#define CACHED
1118
0
#define INPACKEDSAMPLESIZE 2
1119
0
#define OUTPACKEDSAMPLESIZE 2
1120
0
#define NUMINCHANNELS 3
1121
0
#define NUMOUTCHANNELS 3
1122
0
#define NUMEXTRAS 1
1123
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1124
0
do {                                               \
1125
0
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1126
0
       (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
1127
0
       (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
1128
0
} while (0)
1129
0
#define PACK(CTX,T,S,D,Z,A)                     \
1130
0
do {                                            \
1131
0
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1132
0
    *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
1133
0
    *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
1134
0
} while (0)
1135
#include "extra_xform.h"
1136
1137
#define FUNCTION_NAME CachedXFORM3to4_1
1138
#define CACHED
1139
0
#define INPACKEDSAMPLESIZE 1
1140
0
#define OUTPACKEDSAMPLESIZE 1
1141
0
#define NUMINCHANNELS 3
1142
0
#define NUMOUTCHANNELS 4
1143
0
#define NUMEXTRAS 1
1144
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1145
0
do {                                       \
1146
0
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1147
0
       (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
1148
0
       (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
1149
0
} while (0)
1150
0
#define PACK(CTX,T,S,D,Z,A)        \
1151
0
do {                               \
1152
0
    *(D)++ = FROM_16_TO_8((S)[0]); \
1153
0
    *(D)++ = FROM_16_TO_8((S)[1]); \
1154
0
    *(D)++ = FROM_16_TO_8((S)[2]); \
1155
0
    *(D)++ = FROM_16_TO_8((S)[3]); \
1156
0
} while (0)
1157
#include "extra_xform.h"
1158
1159
#define FUNCTION_NAME CachedXFORM3x2to4x2_2
1160
#define CACHED
1161
0
#define INPACKEDSAMPLESIZE 2
1162
0
#define OUTPACKEDSAMPLESIZE 2
1163
0
#define NUMINCHANNELS 3
1164
0
#define NUMOUTCHANNELS 4
1165
0
#define NUMEXTRAS 1
1166
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1167
0
do {                                               \
1168
0
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1169
0
       (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
1170
0
       (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
1171
0
} while (0)
1172
0
#define PACK(CTX,T,S,D,Z,A)                     \
1173
0
do {                                            \
1174
0
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1175
0
    *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
1176
0
    *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
1177
0
    *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \
1178
0
} while (0)
1179
#include "extra_xform.h"
1180
1181
#define FUNCTION_NAME CachedXFORM4to1_1
1182
#define CACHED
1183
0
#define INPACKEDSAMPLESIZE 1
1184
0
#define OUTPACKEDSAMPLESIZE 1
1185
0
#define NUMINCHANNELS 4
1186
0
#define NUMOUTCHANNELS 1
1187
0
#define NUMEXTRAS 1
1188
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1189
0
do {                                       \
1190
0
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1191
0
       (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
1192
0
       (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
1193
0
       (D)[3] = FROM_8_TO_16(*(S)); (S)++; \
1194
0
} while (0)
1195
0
#define PACK(CTX,T,S,D,Z,A)        \
1196
0
do {                               \
1197
0
    *(D)++ = FROM_16_TO_8((S)[0]); \
1198
0
} while (0)
1199
#include "extra_xform.h"
1200
1201
#define FUNCTION_NAME CachedXFORM4x2to1x2_2
1202
#define CACHED
1203
0
#define INPACKEDSAMPLESIZE 2
1204
0
#define OUTPACKEDSAMPLESIZE 2
1205
0
#define NUMINCHANNELS 1
1206
0
#define NUMOUTCHANNELS 1
1207
0
#define NUMEXTRAS 1
1208
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1209
0
do {                                               \
1210
0
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1211
0
       (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
1212
0
       (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
1213
0
       (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \
1214
0
} while (0)
1215
0
#define PACK(CTX,T,S,D,Z,A)                     \
1216
0
do {                                            \
1217
0
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1218
0
} while (0)
1219
#include "extra_xform.h"
1220
1221
#define FUNCTION_NAME CachedXFORM4to3_1
1222
#define CACHED
1223
0
#define INPACKEDSAMPLESIZE 1
1224
0
#define OUTPACKEDSAMPLESIZE 1
1225
0
#define NUMINCHANNELS 4
1226
0
#define NUMOUTCHANNELS 3
1227
0
#define NUMEXTRAS 1
1228
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1229
0
do {                                       \
1230
0
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1231
0
       (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
1232
0
       (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
1233
0
       (D)[3] = FROM_8_TO_16(*(S)); (S)++; \
1234
0
} while (0)
1235
0
#define PACK(CTX,T,S,D,Z,A)        \
1236
0
do {                               \
1237
0
    *(D)++ = FROM_16_TO_8((S)[0]); \
1238
0
    *(D)++ = FROM_16_TO_8((S)[1]); \
1239
0
    *(D)++ = FROM_16_TO_8((S)[2]); \
1240
0
} while (0)
1241
#include "extra_xform.h"
1242
1243
#define FUNCTION_NAME CachedXFORM4x2to3x2_2
1244
#define CACHED
1245
0
#define INPACKEDSAMPLESIZE 2
1246
0
#define OUTPACKEDSAMPLESIZE 2
1247
0
#define NUMINCHANNELS 4
1248
0
#define NUMOUTCHANNELS 3
1249
0
#define NUMEXTRAS 1
1250
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1251
0
do {                                               \
1252
0
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1253
0
       (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
1254
0
       (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
1255
0
       (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \
1256
0
} while (0)
1257
0
#define PACK(CTX,T,S,D,Z,A)                     \
1258
0
do {                                            \
1259
0
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1260
0
    *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
1261
0
    *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
1262
0
} while (0)
1263
#include "extra_xform.h"
1264
1265
#define FUNCTION_NAME CachedXFORM4to4_1
1266
#define CACHED
1267
0
#define INPACKEDSAMPLESIZE 1
1268
0
#define OUTPACKEDSAMPLESIZE 1
1269
0
#define NUMINCHANNELS 4
1270
0
#define NUMOUTCHANNELS 4
1271
0
#define NUMEXTRAS 1
1272
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1273
0
do {                                       \
1274
0
       (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1275
0
       (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
1276
0
       (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
1277
0
       (D)[3] = FROM_8_TO_16(*(S)); (S)++; \
1278
0
} while (0)
1279
0
#define PACK(CTX,T,S,D,Z,A)        \
1280
0
do {                               \
1281
0
    *(D)++ = FROM_16_TO_8((S)[0]); \
1282
0
    *(D)++ = FROM_16_TO_8((S)[1]); \
1283
0
    *(D)++ = FROM_16_TO_8((S)[2]); \
1284
0
    *(D)++ = FROM_16_TO_8((S)[3]); \
1285
0
} while (0)
1286
#include "extra_xform.h"
1287
1288
#define FUNCTION_NAME CachedXFORM4x2to4x2_2
1289
#define CACHED
1290
0
#define INPACKEDSAMPLESIZE 2
1291
0
#define OUTPACKEDSAMPLESIZE 2
1292
0
#define NUMINCHANNELS 4
1293
0
#define NUMOUTCHANNELS 4
1294
0
#define NUMEXTRAS 1
1295
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1296
0
do {                                               \
1297
0
       (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1298
0
       (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
1299
0
       (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
1300
0
       (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \
1301
0
} while (0)
1302
0
#define PACK(CTX,T,S,D,Z,A)                     \
1303
0
do {                                            \
1304
0
    *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1305
0
    *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
1306
0
    *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
1307
0
    *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \
1308
0
} while (0)
1309
#include "extra_xform.h"
1310
1311
1312
// Same again, but with premultiplied alpha
1313
//
1314
// No gamut check, Cache, 16 bits,
1315
#define FUNCTION_NAME CachedXFORM_P1
1316
#define CACHED
1317
0
#define INPACKEDSAMPLESIZE 1
1318
0
#define OUTPACKEDSAMPLESIZE 1
1319
#define PREALPHA
1320
#include "extra_xform.h"
1321
1322
// No gamut check, Cache, 16 bits,
1323
#define FUNCTION_NAME CachedXFORM_P2
1324
#define CACHED
1325
0
#define INPACKEDSAMPLESIZE 2
1326
0
#define OUTPACKEDSAMPLESIZE 2
1327
#define PREALPHA
1328
#include "extra_xform.h"
1329
1330
// Special ones for common cases.
1331
#define FUNCTION_NAME CachedXFORM1to1_P1
1332
#define CACHED
1333
0
#define INPACKEDSAMPLESIZE 1
1334
0
#define OUTPACKEDSAMPLESIZE 1
1335
0
#define NUMINCHANNELS 1
1336
0
#define NUMOUTCHANNELS 1
1337
0
#define NUMEXTRAS 1
1338
#define PREALPHA
1339
#define UNPACKINCLUDESPREALPHA
1340
#define PACKINCLUDESPREALPHA
1341
0
#define UNPACK(CTX,T,D,S,Z,A)                 \
1342
0
do {                                          \
1343
0
    cmsUInt32Number inva = 0xFFFFU / (A); \
1344
0
    (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1345
0
} while (0)
1346
0
#define PACK(CTX,T,S,D,Z,A)        \
1347
0
do {                               \
1348
0
    *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1349
0
} while (0)
1350
#include "extra_xform.h"
1351
1352
#define FUNCTION_NAME CachedXFORM1x2to1x2_P2
1353
#define CACHED
1354
0
#define INPACKEDSAMPLESIZE 2
1355
0
#define OUTPACKEDSAMPLESIZE 2
1356
0
#define NUMINCHANNELS 1
1357
0
#define NUMOUTCHANNELS 1
1358
0
#define NUMEXTRAS 1
1359
#define PREALPHA
1360
#define UNPACKINCLUDESPREALPHA
1361
#define PACKINCLUDESPREALPHA
1362
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1363
0
do {                                               \
1364
0
    cmsUInt32Number inva = 0xffff0000U / (A); \
1365
0
    (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1366
0
} while (0)
1367
0
#define PACK(CTX,T,S,D,Z,A)                     \
1368
0
do {                                            \
1369
0
    *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1370
0
} while (0)
1371
#include "extra_xform.h"
1372
1373
#define FUNCTION_NAME CachedXFORM1to3_P1
1374
#define CACHED
1375
0
#define INPACKEDSAMPLESIZE 1
1376
0
#define OUTPACKEDSAMPLESIZE 1
1377
0
#define NUMINCHANNELS 1
1378
0
#define NUMOUTCHANNELS 3
1379
0
#define NUMEXTRAS 1
1380
#define PREALPHA
1381
#define UNPACKINCLUDESPREALPHA
1382
#define PACKINCLUDESPREALPHA
1383
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1384
0
do {                                       \
1385
0
    cmsUInt32Number inva = 0xFFFFU / (A); \
1386
0
    (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1387
0
} while (0)
1388
0
#define PACK(CTX,T,S,D,Z,A)        \
1389
0
do {                               \
1390
0
    *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1391
0
    *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \
1392
0
    *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \
1393
0
} while (0)
1394
#include "extra_xform.h"
1395
1396
#define FUNCTION_NAME CachedXFORM1x2to3x2_P2
1397
#define CACHED
1398
0
#define INPACKEDSAMPLESIZE 2
1399
0
#define OUTPACKEDSAMPLESIZE 2
1400
0
#define NUMINCHANNELS 1
1401
0
#define NUMOUTCHANNELS 3
1402
0
#define NUMEXTRAS 1
1403
#define PREALPHA
1404
#define UNPACKINCLUDESPREALPHA
1405
#define PACKINCLUDESPREALPHA
1406
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1407
0
do {                                               \
1408
0
    cmsUInt32Number inva = 0xffff0000U / (A); \
1409
0
    (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1410
0
} while (0)
1411
0
#define PACK(CTX,T,S,D,Z,A)                     \
1412
0
do {                                            \
1413
0
    *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1414
0
    *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \
1415
0
    *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \
1416
0
} while (0)
1417
#include "extra_xform.h"
1418
1419
#define FUNCTION_NAME CachedXFORM1to4_P1
1420
#define CACHED
1421
0
#define INPACKEDSAMPLESIZE 1
1422
0
#define OUTPACKEDSAMPLESIZE 1
1423
0
#define NUMINCHANNELS 1
1424
0
#define NUMOUTCHANNELS 4
1425
0
#define NUMEXTRAS 1
1426
#define PREALPHA
1427
#define UNPACKINCLUDESPREALPHA
1428
#define PACKINCLUDESPREALPHA
1429
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1430
0
do {                                       \
1431
0
    cmsUInt32Number inva = 0xFFFFU / (A); \
1432
0
    (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1433
0
} while (0)
1434
0
#define PACK(CTX,T,S,D,Z,A)        \
1435
0
do {                               \
1436
0
    *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1437
0
    *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \
1438
0
    *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \
1439
0
    *(D)++ = mul255(FROM_16_TO_8((S)[3]),(A)); \
1440
0
} while (0)
1441
#include "extra_xform.h"
1442
1443
#define FUNCTION_NAME CachedXFORM1x2to4x2_P2
1444
#define CACHED
1445
0
#define INPACKEDSAMPLESIZE 2
1446
0
#define OUTPACKEDSAMPLESIZE 2
1447
0
#define NUMINCHANNELS 1
1448
0
#define NUMOUTCHANNELS 4
1449
0
#define NUMEXTRAS 1
1450
#define PREALPHA
1451
#define UNPACKINCLUDESPREALPHA
1452
#define PACKINCLUDESPREALPHA
1453
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1454
0
do {                                               \
1455
0
    cmsUInt32Number inva = 0xffff0000U / (A); \
1456
0
    (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1457
0
} while (0)
1458
0
#define PACK(CTX,T,S,D,Z,A)                     \
1459
0
do {                                            \
1460
0
    *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1461
0
    *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \
1462
0
    *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \
1463
0
    *(cmsUInt16Number *)(D) = mul65535((S)[3],A); (D) += 2; \
1464
0
} while (0)
1465
#include "extra_xform.h"
1466
1467
#define FUNCTION_NAME CachedXFORM3to1_P1
1468
#define CACHED
1469
0
#define INPACKEDSAMPLESIZE 1
1470
0
#define OUTPACKEDSAMPLESIZE 1
1471
0
#define NUMINCHANNELS 3
1472
0
#define NUMOUTCHANNELS 1
1473
0
#define NUMEXTRAS 1
1474
#define PREALPHA
1475
#define UNPACKINCLUDESPREALPHA
1476
#define PACKINCLUDESPREALPHA
1477
0
#define UNPACK(CTX,T,D,S,Z,A)               \
1478
0
do {                                        \
1479
0
    cmsUInt32Number inva = 0xFFFFU / (A); \
1480
0
    (D)[0] = (cmsUInt16Number)((*(S) * inva)); (S)++; \
1481
0
    (D)[1] = (cmsUInt16Number)((*(S) * inva)); (S)++; \
1482
0
    (D)[2] = (cmsUInt16Number)((*(S) * inva)); (S)++; \
1483
0
} while (0)
1484
0
#define PACK(CTX,T,S,D,Z,A)        \
1485
0
do {                               \
1486
0
    *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1487
0
} while (0)
1488
#include "extra_xform.h"
1489
1490
#define FUNCTION_NAME CachedXFORM3x2to1x2_P2
1491
#define CACHED
1492
0
#define INPACKEDSAMPLESIZE 2
1493
0
#define OUTPACKEDSAMPLESIZE 2
1494
0
#define NUMINCHANNELS 3
1495
0
#define NUMOUTCHANNELS 1
1496
0
#define NUMEXTRAS 1
1497
#define PREALPHA
1498
#define UNPACKINCLUDESPREALPHA
1499
#define PACKINCLUDESPREALPHA
1500
0
#define UNPACK(CTX,T,D,S,Z,A)                       \
1501
0
do {                                                \
1502
0
    cmsUInt32Number inva = 0xffff0000U / (A); \
1503
0
    (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1504
0
    (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1505
0
    (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1506
0
} while (0)
1507
0
#define PACK(CTX,T,S,D,Z,A)                     \
1508
0
do {                                            \
1509
0
    *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1510
0
} while (0)
1511
#include "extra_xform.h"
1512
1513
#define FUNCTION_NAME CachedXFORM3to3_P1
1514
#define CACHED
1515
0
#define INPACKEDSAMPLESIZE 1
1516
0
#define OUTPACKEDSAMPLESIZE 1
1517
0
#define NUMINCHANNELS 3
1518
0
#define NUMOUTCHANNELS 3
1519
0
#define NUMEXTRAS 1
1520
#define PREALPHA
1521
#define UNPACKINCLUDESPREALPHA
1522
#define PACKINCLUDESPREALPHA
1523
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1524
0
do {                                       \
1525
0
    cmsUInt32Number inva = 0xFFFFU / (A); \
1526
0
    (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1527
0
    (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1528
0
    (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1529
0
} while (0)
1530
0
#define PACK(CTX,T,S,D,Z,A)        \
1531
0
do {                               \
1532
0
    *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1533
0
    *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \
1534
0
    *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \
1535
0
} while (0)
1536
#include "extra_xform.h"
1537
1538
#define FUNCTION_NAME CachedXFORM3x2to3x2_P2
1539
#define CACHED
1540
0
#define INPACKEDSAMPLESIZE 2
1541
0
#define OUTPACKEDSAMPLESIZE 2
1542
0
#define NUMINCHANNELS 3
1543
0
#define NUMOUTCHANNELS 3
1544
0
#define NUMEXTRAS 1
1545
#define PREALPHA
1546
#define UNPACKINCLUDESPREALPHA
1547
#define PACKINCLUDESPREALPHA
1548
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1549
0
do {                                               \
1550
0
    cmsUInt32Number inva = 0xffff0000U / (A); \
1551
0
    (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1552
0
    (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1553
0
    (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1554
0
} while (0)
1555
0
#define PACK(CTX,T,S,D,Z,A)                     \
1556
0
do {                                            \
1557
0
    *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1558
0
    *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \
1559
0
    *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \
1560
0
} while (0)
1561
#include "extra_xform.h"
1562
1563
#define FUNCTION_NAME CachedXFORM3to4_P1
1564
#define CACHED
1565
0
#define INPACKEDSAMPLESIZE 1
1566
0
#define OUTPACKEDSAMPLESIZE 1
1567
0
#define NUMINCHANNELS 3
1568
0
#define NUMOUTCHANNELS 4
1569
0
#define NUMEXTRAS 1
1570
#define PREALPHA
1571
#define UNPACKINCLUDESPREALPHA
1572
#define PACKINCLUDESPREALPHA
1573
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1574
0
do {                                       \
1575
0
    cmsUInt32Number inva = 0xFFFFU / (A); \
1576
0
    (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1577
0
    (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1578
0
    (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1579
0
} while (0)
1580
0
#define PACK(CTX,T,S,D,Z,A)        \
1581
0
do {                               \
1582
0
    *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1583
0
    *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \
1584
0
    *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \
1585
0
    *(D)++ = mul255(FROM_16_TO_8((S)[3]),(A)); \
1586
0
} while (0)
1587
#include "extra_xform.h"
1588
1589
#define FUNCTION_NAME CachedXFORM3x2to4x2_P2
1590
#define CACHED
1591
0
#define INPACKEDSAMPLESIZE 2
1592
0
#define OUTPACKEDSAMPLESIZE 2
1593
0
#define NUMINCHANNELS 3
1594
0
#define NUMOUTCHANNELS 4
1595
0
#define NUMEXTRAS 1
1596
#define PREALPHA
1597
#define UNPACKINCLUDESPREALPHA
1598
#define PACKINCLUDESPREALPHA
1599
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1600
0
do {                                               \
1601
0
    cmsUInt32Number inva = 0xffff0000U / (A); \
1602
0
    (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1603
0
    (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1604
0
    (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1605
0
} while (0)
1606
0
#define PACK(CTX,T,S,D,Z,A)                     \
1607
0
do {                                            \
1608
0
    *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1609
0
    *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \
1610
0
    *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \
1611
0
    *(cmsUInt16Number *)(D) = mul65535((S)[3],A); (D) += 2; \
1612
0
} while (0)
1613
#include "extra_xform.h"
1614
1615
#define FUNCTION_NAME CachedXFORM4to1_P1
1616
#define CACHED
1617
0
#define INPACKEDSAMPLESIZE 1
1618
0
#define OUTPACKEDSAMPLESIZE 1
1619
0
#define NUMINCHANNELS 4
1620
0
#define NUMOUTCHANNELS 1
1621
0
#define NUMEXTRAS 1
1622
#define PREALPHA
1623
#define UNPACKINCLUDESPREALPHA
1624
#define PACKINCLUDESPREALPHA
1625
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1626
0
do {                                       \
1627
0
    cmsUInt32Number inva = 0xFFFFU / (A); \
1628
0
    (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1629
0
    (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1630
0
    (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1631
0
    (D)[3] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1632
0
} while (0)
1633
0
#define PACK(CTX,T,S,D,Z,A)        \
1634
0
do {                               \
1635
0
    *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1636
0
} while (0)
1637
#include "extra_xform.h"
1638
1639
#define FUNCTION_NAME CachedXFORM4x2to1x2_P2
1640
#define CACHED
1641
0
#define INPACKEDSAMPLESIZE 2
1642
0
#define OUTPACKEDSAMPLESIZE 2
1643
0
#define NUMINCHANNELS 4
1644
0
#define NUMOUTCHANNELS 1
1645
0
#define NUMEXTRAS 1
1646
#define PREALPHA
1647
#define UNPACKINCLUDESPREALPHA
1648
#define PACKINCLUDESPREALPHA
1649
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1650
0
do {                                               \
1651
0
    cmsUInt32Number inva = 0xffff0000U / (A); \
1652
0
    (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1653
0
    (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1654
0
    (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1655
0
    (D)[3] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1656
0
} while (0)
1657
0
#define PACK(CTX,T,S,D,Z,A)                     \
1658
0
do {                                            \
1659
0
    *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1660
0
} while (0)
1661
#include "extra_xform.h"
1662
1663
#define FUNCTION_NAME CachedXFORM4to3_P1
1664
#define CACHED
1665
0
#define INPACKEDSAMPLESIZE 1
1666
0
#define OUTPACKEDSAMPLESIZE 1
1667
0
#define NUMINCHANNELS 4
1668
0
#define NUMOUTCHANNELS 3
1669
0
#define NUMEXTRAS 1
1670
#define PREALPHA
1671
#define UNPACKINCLUDESPREALPHA
1672
#define PACKINCLUDESPREALPHA
1673
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1674
0
do {                                       \
1675
0
    cmsUInt32Number inva = 0xFFFFU / (A); \
1676
0
    (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1677
0
    (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1678
0
    (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1679
0
    (D)[3] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1680
0
} while (0)
1681
0
#define PACK(CTX,T,S,D,Z,A)        \
1682
0
do {                               \
1683
0
    *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1684
0
    *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \
1685
0
    *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \
1686
0
} while (0)
1687
#include "extra_xform.h"
1688
1689
#define FUNCTION_NAME CachedXFORM4x2to3x2_P2
1690
#define CACHED
1691
0
#define INPACKEDSAMPLESIZE 2
1692
0
#define OUTPACKEDSAMPLESIZE 2
1693
0
#define NUMINCHANNELS 4
1694
0
#define NUMOUTCHANNELS 3
1695
0
#define NUMEXTRAS 1
1696
#define PREALPHA
1697
#define UNPACKINCLUDESPREALPHA
1698
#define PACKINCLUDESPREALPHA
1699
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1700
0
do {                                               \
1701
0
    cmsUInt32Number inva = 0xffff0000U / (A); \
1702
0
    (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1703
0
    (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1704
0
    (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1705
0
    (D)[3] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1706
0
} while (0)
1707
0
#define PACK(CTX,T,S,D,Z,A)                     \
1708
0
do {                                            \
1709
0
    *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1710
0
    *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \
1711
0
    *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \
1712
0
} while (0)
1713
#include "extra_xform.h"
1714
1715
#define FUNCTION_NAME CachedXFORM4to4_P1
1716
#define CACHED
1717
0
#define INPACKEDSAMPLESIZE 1
1718
0
#define OUTPACKEDSAMPLESIZE 1
1719
0
#define NUMINCHANNELS 4
1720
0
#define NUMOUTCHANNELS 4
1721
0
#define NUMEXTRAS 1
1722
#define PREALPHA
1723
#define UNPACKINCLUDESPREALPHA
1724
#define PACKINCLUDESPREALPHA
1725
0
#define UNPACK(CTX,T,D,S,Z,A)              \
1726
0
do {                                       \
1727
0
    cmsUInt32Number inva = 0xFFFFU / (A); \
1728
0
    (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1729
0
    (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1730
0
    (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1731
0
    (D)[3] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1732
0
} while (0)
1733
0
#define PACK(CTX,T,S,D,Z,A)        \
1734
0
do {                               \
1735
0
    *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1736
0
    *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \
1737
0
    *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \
1738
0
    *(D)++ = mul255(FROM_16_TO_8((S)[3]),(A)); \
1739
0
} while (0)
1740
#include "extra_xform.h"
1741
1742
#define FUNCTION_NAME CachedXFORM4x2to4x2_P2
1743
#define CACHED
1744
0
#define INPACKEDSAMPLESIZE 2
1745
0
#define OUTPACKEDSAMPLESIZE 2
1746
0
#define NUMINCHANNELS 4
1747
0
#define NUMOUTCHANNELS 4
1748
0
#define NUMEXTRAS 1
1749
#define PREALPHA
1750
#define UNPACKINCLUDESPREALPHA
1751
#define PACKINCLUDESPREALPHA
1752
0
#define UNPACK(CTX,T,D,S,Z,A)                      \
1753
0
do {                                               \
1754
0
    cmsUInt32Number inva = 0xffff0000U / (A); \
1755
0
    (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1756
0
    (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1757
0
    (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1758
0
    (D)[3] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1759
0
} while (0)
1760
0
#define PACK(CTX,T,S,D,Z,A)                     \
1761
0
do {                                            \
1762
0
    *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1763
0
    *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \
1764
0
    *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \
1765
0
    *(cmsUInt16Number *)(D) = mul65535((S)[3],A); (D) += 2; \
1766
0
} while (0)
1767
#include "extra_xform.h"
1768
1769
1770
// Transform plug-ins ----------------------------------------------------------------------------------------------------
1771
1772
// List of used-defined transform factories
1773
typedef struct _cmsTransformCollection_st {
1774
1775
    _cmsTransform2Factory  Factory;
1776
    cmsBool                OldXform;   // Factory returns xform function in the old style
1777
1778
    struct _cmsTransformCollection_st *Next;
1779
1780
} _cmsTransformCollection;
1781
1782
// The linked list head
1783
_cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL };
1784
1785
1786
// Duplicates the zone of memory used by the plug-in in the new context
1787
static
1788
void DupPluginTransformList(struct _cmsContext_struct* ctx,
1789
                                               const struct _cmsContext_struct* src)
1790
0
{
1791
0
   _cmsTransformPluginChunkType newHead = { NULL };
1792
0
   _cmsTransformCollection*  entry;
1793
0
   _cmsTransformCollection*  Anterior = NULL;
1794
0
   _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin];
1795
1796
    // Walk the list copying all nodes
1797
0
   for (entry = head->TransformCollection;
1798
0
        entry != NULL;
1799
0
        entry = entry ->Next) {
1800
1801
0
            _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection));
1802
1803
0
            if (newEntry == NULL)
1804
0
                return;
1805
1806
            // We want to keep the linked list order, so this is a little bit tricky
1807
0
            newEntry -> Next = NULL;
1808
0
            if (Anterior)
1809
0
                Anterior -> Next = newEntry;
1810
1811
0
            Anterior = newEntry;
1812
1813
0
            if (newHead.TransformCollection == NULL)
1814
0
                newHead.TransformCollection = newEntry;
1815
0
    }
1816
1817
0
  ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType));
1818
0
}
1819
1820
// Allocates memory for transform plugin factory
1821
void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx,
1822
                                        const struct _cmsContext_struct* src)
1823
89.2k
{
1824
89.2k
    if (src != NULL) {
1825
1826
        // Copy all linked list
1827
0
        DupPluginTransformList(ctx, src);
1828
0
    }
1829
89.2k
    else {
1830
89.2k
        static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL };
1831
89.2k
        ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType));
1832
89.2k
    }
1833
89.2k
}
1834
1835
// Adaptor for old versions of plug-in
1836
static
1837
void _cmsTransform2toTransformAdaptor(cmsContext ContextID, struct _cmstransform_struct *CMMcargo,
1838
                                      const void* InputBuffer,
1839
                                      void* OutputBuffer,
1840
                                      cmsUInt32Number PixelsPerLine,
1841
                                      cmsUInt32Number LineCount,
1842
                                      const cmsStride* Stride)
1843
0
{
1844
1845
0
       cmsUInt32Number i, strideIn, strideOut;
1846
1847
0
       _cmsHandleExtraChannels(ContextID, CMMcargo, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, Stride);
1848
1849
0
       strideIn = 0;
1850
0
       strideOut = 0;
1851
1852
0
       for (i = 0; i < LineCount; i++) {
1853
1854
0
              void *accum = (cmsUInt8Number*)InputBuffer + strideIn;
1855
0
              void *output = (cmsUInt8Number*)OutputBuffer + strideOut;
1856
1857
0
              CMMcargo->OldXform(ContextID, CMMcargo, accum, output, PixelsPerLine, Stride->BytesPerPlaneIn);
1858
1859
0
              strideIn += Stride->BytesPerLineIn;
1860
0
              strideOut += Stride->BytesPerLineOut;
1861
0
       }
1862
0
}
1863
1864
1865
1866
// Register new ways to transform
1867
cmsBool  _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data)
1868
89.2k
{
1869
89.2k
    cmsPluginTransform* Plugin = (cmsPluginTransform*) Data;
1870
89.2k
    _cmsTransformCollection* fl;
1871
89.2k
    _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin);
1872
1873
89.2k
    if (Data == NULL) {
1874
1875
        // Free the chain. Memory is safely freed at exit
1876
89.2k
        ctx->TransformCollection = NULL;
1877
89.2k
        return TRUE;
1878
89.2k
    }
1879
1880
    // Factory callback is required
1881
0
    if (Plugin->factories.xform == NULL) return FALSE;
1882
1883
1884
0
    fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection));
1885
0
    if (fl == NULL) return FALSE;
1886
1887
    // Check for full xform plug-ins previous to 2.8, we would need an adapter in that case
1888
0
    if ((Plugin->base.ExpectedVersion <= LCMS2MT_VERSION_MAX &&
1889
0
         Plugin->base.ExpectedVersion < 2080-2000) ||
1890
0
        (Plugin->base.ExpectedVersion > LCMS2MT_VERSION_MAX &&
1891
0
         Plugin->base.ExpectedVersion < 2080)) {
1892
0
           fl->OldXform = TRUE;
1893
0
    }
1894
0
    else
1895
0
           fl->OldXform = FALSE;
1896
1897
    // Copy the parameters
1898
0
    fl->Factory = Plugin->factories.xform;
1899
1900
    // Keep linked list
1901
0
    fl ->Next = ctx->TransformCollection;
1902
0
    ctx->TransformCollection = fl;
1903
1904
    // All is ok
1905
0
    return TRUE;
1906
0
}
1907
1908
1909
void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn)
1910
0
{
1911
0
    _cmsAssert(CMMcargo != NULL && CMMcargo->core != NULL);
1912
0
    CMMcargo->core->UserData = ptr;
1913
0
    CMMcargo->core->FreeUserData = FreePrivateDataFn;
1914
0
}
1915
1916
// returns the pointer defined by the plug-in to store private data
1917
void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo)
1918
0
{
1919
0
    _cmsAssert(CMMcargo != NULL && CMMcargo->core != NULL);
1920
0
    return CMMcargo->core->UserData;
1921
0
}
1922
1923
// returns the current formatters
1924
void CMSEXPORT _cmsGetTransformFormatters16(struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput)
1925
0
{
1926
0
     _cmsAssert(CMMcargo != NULL);
1927
0
     if (FromInput) *FromInput = CMMcargo ->FromInput;
1928
0
     if (ToOutput)  *ToOutput  = CMMcargo ->ToOutput;
1929
0
}
1930
1931
void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput)
1932
0
{
1933
0
     _cmsAssert(CMMcargo != NULL);
1934
0
     if (FromInput) *FromInput = CMMcargo ->FromInputFloat;
1935
0
     if (ToOutput)  *ToOutput  = CMMcargo ->ToOutputFloat;
1936
0
}
1937
1938
// returns original flags
1939
cmsUInt32Number CMSEXPORT _cmsGetTransformFlags(struct _cmstransform_struct* CMMcargo)
1940
0
{
1941
0
    _cmsAssert(CMMcargo != NULL);
1942
0
    return CMMcargo->core->dwOriginalFlags;
1943
0
}
1944
1945
void
1946
_cmsFindFormatter(cmsContext ContextID, _cmsTRANSFORM* p, cmsUInt32Number InputFormat, cmsUInt32Number OutputFormat, cmsUInt32Number dwFlags)
1947
505k
{
1948
505k
    int isIdentity;
1949
505k
    if (dwFlags & cmsFLAGS_NULLTRANSFORM) {
1950
0
        p ->xform = NullXFORM;
1951
0
        return;
1952
0
    }
1953
505k
    isIdentity = ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) &&
1954
505k
                  _cmsLutIsIdentity(p->core->Lut));
1955
505k
    if (dwFlags & cmsFLAGS_PREMULT) {
1956
0
        if (dwFlags & cmsFLAGS_NOCACHE) {
1957
0
            if (dwFlags & cmsFLAGS_GAMUTCHECK)
1958
0
                p ->xform = PrecalculatedXFORMGamutCheck_P;  // Gamut check, no cache
1959
0
            else if (isIdentity) {
1960
0
                if (T_PLANAR(InputFormat))
1961
0
                    p ->xform = PrecalculatedXFORMIdentityPlanar;
1962
0
                else
1963
0
                    p ->xform = PrecalculatedXFORMIdentity;
1964
0
            } else
1965
0
                p ->xform = PrecalculatedXFORM_P;  // No cache, no gamut check
1966
0
            return;
1967
0
        }
1968
0
        if (dwFlags & cmsFLAGS_GAMUTCHECK) {
1969
0
            p ->xform = CachedXFORMGamutCheck_P;    // Gamut check, cache
1970
0
            return;
1971
0
        }
1972
0
        if (isIdentity) {
1973
            /* No point in a cache here! */
1974
0
            if (T_PLANAR(InputFormat))
1975
0
                p ->xform = PrecalculatedXFORMIdentityPlanar;
1976
0
            else
1977
0
                p ->xform = PrecalculatedXFORMIdentity;
1978
0
            return;
1979
0
        }
1980
0
    }
1981
505k
    if (dwFlags & cmsFLAGS_NOCACHE) {
1982
348k
        if (dwFlags & cmsFLAGS_GAMUTCHECK)
1983
0
            p ->xform = PrecalculatedXFORMGamutCheck;  // Gamut check, no cache
1984
348k
        else if (isIdentity) {
1985
12.8k
            if (T_PLANAR(InputFormat))
1986
0
                p ->xform = PrecalculatedXFORMIdentityPlanar;
1987
12.8k
            else
1988
12.8k
                p ->xform = PrecalculatedXFORMIdentity;
1989
12.8k
        } else
1990
336k
            p ->xform = PrecalculatedXFORM;  // No cache, no gamut check
1991
348k
        return;
1992
348k
    }
1993
156k
    if (dwFlags & cmsFLAGS_GAMUTCHECK) {
1994
0
        p ->xform = CachedXFORMGamutCheck;    // Gamut check, cache
1995
0
        return;
1996
0
    }
1997
156k
    if (isIdentity) {
1998
        /* No point in a cache here! */
1999
0
        if (T_PLANAR(InputFormat))
2000
0
            p ->xform = PrecalculatedXFORMIdentityPlanar;
2001
0
        else
2002
0
            p ->xform = PrecalculatedXFORMIdentity;
2003
0
        return;
2004
0
    }
2005
#ifdef WITH_CAL
2006
    if (cal_cms_find_formatter_and_xform(ContextID, &p->xform, InputFormat, OutputFormat, &dwFlags)) {
2007
        return;
2008
    }
2009
#endif
2010
156k
    if (T_EXTRA(InputFormat) == 1 && T_EXTRA(OutputFormat) == 1) {
2011
0
        if (dwFlags & cmsFLAGS_PREMULT) {
2012
0
            if ((InputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0 &&
2013
0
                (OutputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0) {
2014
0
                switch ((InputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))|
2015
0
                        ((OutputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))<<6)) {
2016
0
                    case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2017
0
                        p->xform = CachedXFORM1to1_P1;
2018
0
                        return;
2019
0
                    case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2020
0
                        p->xform = CachedXFORM1x2to1x2_P2;
2021
0
                        return;
2022
0
                    case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2023
0
                        p->xform = CachedXFORM1to3_P1;
2024
0
                        return;
2025
0
                    case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2026
0
                        p->xform = CachedXFORM1x2to3x2_P2;
2027
0
                        return;
2028
0
                    case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2029
0
                        p->xform = CachedXFORM1to4_P1;
2030
0
                        return;
2031
0
                    case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2032
0
                        p->xform = CachedXFORM1x2to4x2_P2;
2033
0
                        return;
2034
0
                    case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2035
0
                        p ->xform = CachedXFORM3to1_P1;
2036
0
                        return;
2037
0
                    case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2038
0
                        p ->xform = CachedXFORM3x2to1x2_P2;
2039
0
                        return;
2040
0
                    case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2041
0
                        p->xform = CachedXFORM3to3_P1;
2042
0
                        return;
2043
0
                    case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2044
0
                        p->xform = CachedXFORM3x2to3x2_P2;
2045
0
                        return;
2046
0
                    case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2047
0
                        p->xform = CachedXFORM3to4_P1;
2048
0
                        return;
2049
0
                    case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2050
0
                        p->xform = CachedXFORM3x2to4x2_P2;
2051
0
                        return;
2052
0
                    case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2053
0
                        p->xform = CachedXFORM4to1_P1;
2054
0
                        return;
2055
0
                    case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2056
0
                        p->xform = CachedXFORM4x2to1x2_P2;
2057
0
                        return;
2058
0
                    case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2059
0
                        p->xform = CachedXFORM4to3_P1;
2060
0
                        return;
2061
0
                    case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2062
0
                        p->xform = CachedXFORM4x2to3x2_P2;
2063
0
                        return;
2064
0
                    case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2065
0
                        p->xform = CachedXFORM4to4_P1;
2066
0
                        return;
2067
0
                    case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2068
0
                        p->xform = CachedXFORM4x2to4x2_P2;
2069
0
                        return;
2070
0
                }
2071
0
            }
2072
0
        } else {
2073
0
            if ((InputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0 &&
2074
0
                (OutputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0) {
2075
0
                switch ((InputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))|
2076
0
                        ((OutputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))<<6)) {
2077
0
                    case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2078
0
                        p->xform = CachedXFORM1to1_1;
2079
0
                        return;
2080
0
                    case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2081
0
                        p->xform = CachedXFORM1x2to1x2_2;
2082
0
                        return;
2083
0
                    case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2084
0
                        p->xform = CachedXFORM1to3_1;
2085
0
                        return;
2086
0
                    case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2087
0
                        p->xform = CachedXFORM1x2to3x2_2;
2088
0
                        return;
2089
0
                    case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2090
0
                        p->xform = CachedXFORM1to4_1;
2091
0
                        return;
2092
0
                    case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2093
0
                        p->xform = CachedXFORM1x2to4x2_2;
2094
0
                        return;
2095
0
                    case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2096
0
                        p ->xform = CachedXFORM3to1_1;
2097
0
                        return;
2098
0
                    case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2099
0
                        p ->xform = CachedXFORM3x2to1x2_2;
2100
0
                        return;
2101
0
                    case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2102
0
                        p->xform = CachedXFORM3to3_1;
2103
0
                        return;
2104
0
                    case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2105
0
                        p->xform = CachedXFORM3x2to3x2_2;
2106
0
                        return;
2107
0
                    case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2108
0
                        p->xform = CachedXFORM3to4_1;
2109
0
                        return;
2110
0
                    case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2111
0
                        p->xform = CachedXFORM3x2to4x2_2;
2112
0
                        return;
2113
0
                    case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2114
0
                        p->xform = CachedXFORM4to1_1;
2115
0
                        return;
2116
0
                    case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2117
0
                        p->xform = CachedXFORM4x2to1x2_2;
2118
0
                        return;
2119
0
                    case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2120
0
                        p->xform = CachedXFORM4to3_1;
2121
0
                        return;
2122
0
                    case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2123
0
                        p->xform = CachedXFORM4x2to3x2_2;
2124
0
                        return;
2125
0
                    case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2126
0
                        p->xform = CachedXFORM4to4_1;
2127
0
                        return;
2128
0
                    case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2129
0
                        p->xform = CachedXFORM4x2to4x2_2;
2130
0
                        return;
2131
0
                }
2132
0
            }
2133
0
        }
2134
0
    }
2135
156k
    if (T_EXTRA(InputFormat) != 0) {
2136
0
        if (dwFlags & cmsFLAGS_PREMULT) {
2137
0
            if (T_BYTES(InputFormat) == 1)
2138
0
                p ->xform = CachedXFORM_P1;// No gamut check, cache
2139
0
            else
2140
0
                p ->xform = CachedXFORM_P2;// No gamut check, cache
2141
0
        } else {
2142
0
            p ->xform = CachedXFORM;  // No gamut check, cache
2143
0
        }
2144
0
        return;
2145
0
    }
2146
156k
    if ((InputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3))) == 0 &&
2147
156k
        (OutputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3))) == 0) {
2148
156k
        switch ((InputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))|
2149
156k
                ((OutputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))<<6)) {
2150
0
            case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2151
0
                p->xform = CachedXFORM1to1;
2152
0
                return;
2153
69.2k
            case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2154
69.2k
                p->xform = CachedXFORM1x2to1x2;
2155
69.2k
                return;
2156
0
            case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2157
0
                p->xform = CachedXFORM1to3;
2158
0
                return;
2159
57.4k
            case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2160
57.4k
                p->xform = CachedXFORM1x2to3x2;
2161
57.4k
                return;
2162
27
            case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2163
27
                p->xform = CachedXFORM1to4;
2164
27
                return;
2165
10.5k
            case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2166
10.5k
                p->xform = CachedXFORM1x2to4x2;
2167
10.5k
                return;
2168
388
            case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2169
388
                p ->xform = CachedXFORM3to1;
2170
388
                return;
2171
6.02k
            case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2172
6.02k
                p ->xform = CachedXFORM3x2to1x2;
2173
6.02k
                return;
2174
206
            case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2175
206
                p->xform = CachedXFORM3to3;
2176
206
                return;
2177
4.58k
            case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2178
4.58k
                p->xform = CachedXFORM3x2to3x2;
2179
4.58k
                return;
2180
20
            case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2181
20
                p->xform = CachedXFORM3to4;
2182
20
                return;
2183
1.28k
            case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2184
1.28k
                p->xform = CachedXFORM3x2to4x2;
2185
1.28k
                return;
2186
547
            case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2187
547
                p->xform = CachedXFORM4to1;
2188
547
                return;
2189
2.79k
            case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2190
2.79k
                p->xform = CachedXFORM4x2to1x2;
2191
2.79k
                return;
2192
170
            case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2193
170
                p->xform = CachedXFORM4to3;
2194
170
                return;
2195
3.21k
            case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2196
3.21k
                p->xform = CachedXFORM4x2to3x2;
2197
3.21k
                return;
2198
0
            case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2199
0
                p->xform = CachedXFORM4to4;
2200
0
                return;
2201
371
            case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2202
371
                p->xform = CachedXFORM4x2to4x2;
2203
371
                return;
2204
156k
        }
2205
156k
    }
2206
93
    {
2207
93
        int inwords = T_CHANNELS(InputFormat);
2208
93
        if (inwords <= 2)
2209
0
            p ->xform = CachedXFORM4;
2210
93
        else if (inwords <= 4)
2211
93
            p ->xform = CachedXFORM8;
2212
0
        else
2213
0
            p ->xform = CachedXFORM;  // No gamut check, cache
2214
93
    }
2215
93
}
2216
2217
// Allocate transform struct and set it to defaults. Ask the optimization plug-in about if those formats are proper
2218
// for separated transforms. If this is the case,
2219
static
2220
_cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
2221
                                               cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
2222
514k
{
2223
514k
    _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin);
2224
514k
    _cmsTransformCollection* Plugin;
2225
514k
    _cmsTRANSFORMCORE *core;
2226
2227
    // Allocate needed memory
2228
514k
    _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
2229
514k
    if (!p) {
2230
0
        cmsPipelineFree(ContextID, lut);
2231
0
        return NULL;
2232
0
    }
2233
2234
514k
    core = (_cmsTRANSFORMCORE*)_cmsMallocZero(ContextID, sizeof(*core));
2235
514k
    if (!core) {
2236
0
        _cmsFree(ContextID, p);
2237
0
        cmsPipelineFree(ContextID, lut);
2238
0
        return NULL;
2239
0
    }
2240
2241
514k
    p->core = core;
2242
514k
    core->refs = 1;
2243
    // Store the proposed pipeline
2244
514k
    p->core->Lut = lut;
2245
2246
       // Let's see if any plug-in want to do the transform by itself
2247
514k
       if (core->Lut != NULL) {
2248
514k
           if (!(*dwFlags & cmsFLAGS_NOOPTIMIZE)) {
2249
2250
169k
               for (Plugin = ctx->TransformCollection;
2251
169k
                   Plugin != NULL;
2252
169k
                   Plugin = Plugin->Next) {
2253
2254
0
                   if (Plugin->Factory(ContextID, &p->xform, &core->UserData, &core->FreeUserData, &core->Lut, InputFormat, OutputFormat, dwFlags)) {
2255
2256
                       // Last plugin in the declaration order takes control. We just keep
2257
                       // the original parameters as a logging.
2258
                       // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default
2259
                       // an optimized transform is not reusable. The plug-in can, however, change
2260
                       // the flags and make it suitable.
2261
2262
0
                       p->InputFormat = *InputFormat;
2263
0
                       p->OutputFormat = *OutputFormat;
2264
0
                       core->dwOriginalFlags = *dwFlags;
2265
2266
                       // Fill the formatters just in case the optimized routine is interested.
2267
                       // No error is thrown if the formatter doesn't exist. It is up to the optimization
2268
                       // factory to decide what to do in those cases.
2269
0
                       p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
2270
0
                       p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
2271
0
                       p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
2272
0
                       p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
2273
2274
                       // Save the day? (Ignore the warning)
2275
0
                       if (Plugin->OldXform) {
2276
0
                           p->OldXform = (_cmsTransformFn)(void*) p->xform;
2277
0
                           p->xform = _cmsTransform2toTransformAdaptor;
2278
0
                        }
2279
2280
0
                        return p;
2281
0
                   }
2282
0
               }
2283
169k
     }
2284
2285
           // Not suitable for the transform plug-in, let's check the pipeline plug-in
2286
514k
           _cmsOptimizePipeline(ContextID, &core->Lut, Intent, InputFormat, OutputFormat, dwFlags);
2287
514k
       }
2288
2289
    // Check whatever this is a true floating point transform
2290
514k
    if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) {
2291
2292
        // Get formatter function always return a valid union, but the contents of this union may be NULL.
2293
10.1k
        p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
2294
10.1k
        p ->ToOutputFloat  = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
2295
10.1k
        *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
2296
2297
10.1k
        if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
2298
2299
0
            cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
2300
0
            cmsDeleteTransform(ContextID, p);
2301
0
            return NULL;
2302
0
        }
2303
2304
10.1k
        if (*dwFlags & cmsFLAGS_NULLTRANSFORM) {
2305
2306
0
            p ->xform = NullFloatXFORM;
2307
0
        }
2308
10.1k
        else {
2309
            // Float transforms don't use cache, always are non-NULL
2310
10.1k
            p ->xform = FloatXFORM;
2311
10.1k
        }
2312
2313
10.1k
    }
2314
504k
    else {
2315
2316
504k
        if (*InputFormat == 0 && *OutputFormat == 0) {
2317
0
            p ->FromInput = p ->ToOutput = NULL;
2318
0
            *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
2319
0
        }
2320
504k
        else {
2321
2322
504k
            cmsUInt32Number BytesPerPixelInput;
2323
2324
504k
            p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
2325
504k
            p ->ToOutput  = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
2326
2327
504k
            if (p ->FromInput == NULL || p ->ToOutput == NULL) {
2328
2329
0
                cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
2330
0
                cmsDeleteTransform(ContextID, p);
2331
0
                return NULL;
2332
0
            }
2333
2334
504k
            BytesPerPixelInput = T_BYTES(p ->InputFormat);
2335
504k
            if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2)
2336
504k
                   *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
2337
2338
504k
        }
2339
2340
504k
        _cmsFindFormatter(ContextID, p, *InputFormat, *OutputFormat, *dwFlags);
2341
504k
    }
2342
2343
514k
    p ->InputFormat     = *InputFormat;
2344
514k
    p ->OutputFormat    = *OutputFormat;
2345
514k
    core->dwOriginalFlags = *dwFlags;
2346
514k
    core->UserData        = NULL;
2347
514k
    return p;
2348
514k
}
2349
2350
static
2351
cmsBool GetXFormColorSpaces(cmsContext ContextID, cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output)
2352
1.24M
{
2353
1.24M
    cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut;
2354
1.24M
    cmsColorSpaceSignature PostColorSpace;
2355
1.24M
    cmsUInt32Number i;
2356
2357
1.24M
    if (nProfiles == 0) return FALSE;
2358
1.24M
    if (hProfiles[0] == NULL) return FALSE;
2359
2360
1.24M
    *Input = PostColorSpace = cmsGetColorSpace(ContextID, hProfiles[0]);
2361
2362
3.76M
    for (i=0; i < nProfiles; i++) {
2363
2364
2.51M
        cmsProfileClassSignature cls;
2365
2.51M
        cmsHPROFILE hProfile = hProfiles[i];
2366
2367
2.51M
        int lIsInput = (PostColorSpace != cmsSigXYZData) &&
2368
2.51M
                       (PostColorSpace != cmsSigLabData);
2369
2370
2.51M
        if (hProfile == NULL) return FALSE;
2371
2372
2.51M
        cls = cmsGetDeviceClass(ContextID, hProfile);
2373
2374
2.51M
        if (cls == cmsSigNamedColorClass) {
2375
2376
0
            ColorSpaceIn    = cmsSig1colorData;
2377
0
            ColorSpaceOut   = (nProfiles > 1) ? cmsGetPCS(ContextID, hProfile) : cmsGetColorSpace(ContextID, hProfile);
2378
0
        }
2379
2.51M
        else
2380
2.51M
        if (lIsInput || (cls == cmsSigLinkClass)) {
2381
2382
1.25M
            ColorSpaceIn    = cmsGetColorSpace(ContextID, hProfile);
2383
1.25M
            ColorSpaceOut   = cmsGetPCS(ContextID, hProfile);
2384
1.25M
        }
2385
1.26M
        else
2386
1.26M
        {
2387
1.26M
            ColorSpaceIn    = cmsGetPCS(ContextID, hProfile);
2388
1.26M
            ColorSpaceOut   = cmsGetColorSpace(ContextID, hProfile);
2389
1.26M
        }
2390
2391
2.51M
        if (i==0)
2392
1.24M
            *Input = ColorSpaceIn;
2393
2394
2.51M
        PostColorSpace = ColorSpaceOut;
2395
2.51M
    }
2396
2397
1.24M
    *Output = PostColorSpace;
2398
2399
1.24M
    return TRUE;
2400
1.24M
}
2401
2402
// Check colorspace
2403
static
2404
cmsBool  IsProperColorSpace(cmsContext ContextID, cmsColorSpaceSignature Check, cmsUInt32Number dwFormat)
2405
2.49M
{
2406
2.49M
    int Space1 = (int) T_COLORSPACE(dwFormat);
2407
2.49M
    int Space2 = _cmsLCMScolorSpace(ContextID, Check);
2408
2409
2.49M
    if (Space1 == PT_ANY) return TRUE;
2410
2.49M
    if (Space1 == Space2) return TRUE;
2411
2412
4.77k
    if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE;
2413
4.77k
    if (Space1 == PT_Lab   && Space2 == PT_LabV2) return TRUE;
2414
2415
4.77k
    return FALSE;
2416
4.77k
}
2417
2418
// ----------------------------------------------------------------------------------------------------------------
2419
2420
// Jun-21-2000: Some profiles (those that comes with W2K) comes
2421
// with the media white (media black?) x 100. Add a sanity check
2422
2423
static
2424
void NormalizeXYZ(cmsCIEXYZ* Dest)
2425
1.02M
{
2426
1.02M
    while (Dest -> X > 2. &&
2427
1.02M
           Dest -> Y > 2. &&
2428
1.02M
           Dest -> Z > 2.) {
2429
2430
20
               Dest -> X /= 10.;
2431
20
               Dest -> Y /= 10.;
2432
20
               Dest -> Z /= 10.;
2433
20
       }
2434
1.02M
}
2435
2436
static
2437
void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src)
2438
1.02M
{
2439
1.02M
    if (src == NULL) {
2440
17
        wtPt ->X = cmsD50X;
2441
17
        wtPt ->Y = cmsD50Y;
2442
17
        wtPt ->Z = cmsD50Z;
2443
17
    }
2444
1.02M
    else {
2445
1.02M
        wtPt ->X = src->X;
2446
1.02M
        wtPt ->Y = src->Y;
2447
1.02M
        wtPt ->Z = src->Z;
2448
2449
1.02M
        NormalizeXYZ(wtPt);
2450
1.02M
    }
2451
2452
1.02M
}
2453
2454
// New to lcms 2.0 -- have all parameters available.
2455
cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
2456
                                                   cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[],
2457
                                                   cmsBool  BPC[],
2458
                                                   cmsUInt32Number Intents[],
2459
                                                   cmsFloat64Number AdaptationStates[],
2460
                                                   cmsHPROFILE hGamutProfile,
2461
                                                   cmsUInt32Number nGamutPCSposition,
2462
                                                   cmsUInt32Number InputFormat,
2463
                                                   cmsUInt32Number OutputFormat,
2464
                                                   cmsUInt32Number dwFlags)
2465
1.24M
{
2466
1.24M
    _cmsTRANSFORM* xform;
2467
1.24M
    cmsColorSpaceSignature EntryColorSpace;
2468
1.24M
    cmsColorSpaceSignature ExitColorSpace;
2469
1.24M
    cmsPipeline* Lut;
2470
1.24M
    cmsUInt32Number LastIntent = Intents[nProfiles-1];
2471
2472
    // If it is a fake transform
2473
1.24M
    if (dwFlags & cmsFLAGS_NULLTRANSFORM)
2474
0
    {
2475
0
        return AllocEmptyTransform(ContextID, NULL, INTENT_PERCEPTUAL, &InputFormat, &OutputFormat, &dwFlags);
2476
0
    }
2477
2478
    // If gamut check is requested, make sure we have a gamut profile
2479
1.24M
    if (dwFlags & cmsFLAGS_GAMUTCHECK) {
2480
0
        if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK;
2481
0
    }
2482
2483
    // On floating point transforms, inhibit cache
2484
1.24M
    if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat))
2485
674k
        dwFlags |= cmsFLAGS_NOCACHE;
2486
2487
    // Mark entry/exit spaces
2488
1.24M
    if (!GetXFormColorSpaces(ContextID, nProfiles, hProfiles, &EntryColorSpace, &ExitColorSpace)) {
2489
0
        cmsSignalError(ContextID, cmsERROR_NULL, "NULL input profiles on transform");
2490
0
        return NULL;
2491
0
    }
2492
2493
    // Check if proper colorspaces
2494
1.24M
    if (!IsProperColorSpace(ContextID, EntryColorSpace, InputFormat)) {
2495
0
        cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong input color space on transform");
2496
0
        return NULL;
2497
0
    }
2498
2499
1.24M
    if (!IsProperColorSpace(ContextID, ExitColorSpace, OutputFormat)) {
2500
4.77k
        cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong output color space on transform");
2501
4.77k
        return NULL;
2502
4.77k
    }
2503
2504
    // Check whatever the transform is 16 bits and involves linear RGB in first profile. If so, disable optimizations
2505
1.24M
    if (EntryColorSpace == cmsSigRgbData && T_BYTES(InputFormat) == 2 && !(dwFlags & cmsFLAGS_NOOPTIMIZE))
2506
355k
    {
2507
355k
        cmsFloat64Number gamma = cmsDetectRGBProfileGamma(ContextID, hProfiles[0], 0.1);
2508
2509
355k
        if (gamma > 0 && gamma < 1.6)
2510
71
            dwFlags |= cmsFLAGS_NOOPTIMIZE;
2511
355k
    }
2512
2513
    // Create a pipeline with all transformations
2514
1.24M
    Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags);
2515
1.24M
    if (Lut == NULL) {
2516
728k
        cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Couldn't link the profiles");
2517
728k
        return NULL;
2518
728k
    }
2519
2520
    // Check channel count
2521
514k
    if ((cmsChannelsOf(ContextID, EntryColorSpace) != cmsPipelineInputChannels(ContextID, Lut)) ||
2522
514k
        (cmsChannelsOf(ContextID, ExitColorSpace)  != cmsPipelineOutputChannels(ContextID, Lut))) {
2523
0
        cmsPipelineFree(ContextID, Lut);
2524
0
        cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted");
2525
0
        return NULL;
2526
0
    }
2527
2528
    // Check premultiplication requirements
2529
514k
    if (dwFlags & cmsFLAGS_PREMULT) {
2530
0
        if (T_BYTES(InputFormat) != T_BYTES(OutputFormat)) {
2531
0
        cmsPipelineFree(ContextID, Lut);
2532
0
        cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Premultiplication requires input and output to be in the same format.");
2533
0
        return NULL;
2534
0
        }
2535
2536
0
        if (T_EXTRA(InputFormat) < 1 || T_EXTRA(OutputFormat) < 1 || T_EXTRA(InputFormat) != T_EXTRA(OutputFormat) || (dwFlags & cmsFLAGS_COPY_ALPHA) == 0) {
2537
0
        cmsPipelineFree(ContextID, Lut);
2538
0
        cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Premultiplication must preserve the extra channels");
2539
0
        return NULL;
2540
0
        }
2541
0
    }
2542
2543
2544
    // All seems ok
2545
514k
    xform = AllocEmptyTransform(ContextID, Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags);
2546
514k
    if (xform == NULL) {
2547
0
        return NULL;
2548
0
    }
2549
2550
    // Keep values
2551
514k
    xform->core->EntryColorSpace = EntryColorSpace;
2552
514k
    xform->core->ExitColorSpace  = ExitColorSpace;
2553
514k
    xform->core->RenderingIntent = Intents[nProfiles-1];
2554
2555
    // Take white points
2556
514k
    SetWhitePoint(&xform->core->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(ContextID, hProfiles[0], cmsSigMediaWhitePointTag));
2557
514k
    SetWhitePoint(&xform->core->ExitWhitePoint,  (cmsCIEXYZ*) cmsReadTag(ContextID, hProfiles[nProfiles-1], cmsSigMediaWhitePointTag));
2558
2559
2560
    // Create a gamut check LUT if requested
2561
514k
    if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK))
2562
0
        xform->core->GamutCheck  = _cmsCreateGamutCheckPipeline(ContextID, hProfiles,
2563
0
                                                        BPC, Intents,
2564
0
                                                        AdaptationStates,
2565
0
                                                        nGamutPCSposition,
2566
0
                                                        hGamutProfile);
2567
2568
2569
    // Try to read input and output colorant table
2570
514k
    if (cmsIsTag(ContextID, hProfiles[0], cmsSigColorantTableTag)) {
2571
2572
        // Input table can only come in this way.
2573
0
        xform->core->InputColorant = cmsDupNamedColorList(ContextID, (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hProfiles[0], cmsSigColorantTableTag));
2574
0
    }
2575
2576
    // Output is a little bit more complex.
2577
514k
    if (cmsGetDeviceClass(ContextID, hProfiles[nProfiles-1]) == cmsSigLinkClass) {
2578
2579
        // This tag may exist only on devicelink profiles.
2580
0
        if (cmsIsTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableOutTag)) {
2581
2582
            // It may be NULL if error
2583
0
            xform->core->OutputColorant = cmsDupNamedColorList(ContextID, (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableOutTag));
2584
0
        }
2585
2586
514k
    } else {
2587
2588
514k
        if (cmsIsTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableTag)) {
2589
2590
0
            xform->core->OutputColorant = cmsDupNamedColorList(ContextID, (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableTag));
2591
0
        }
2592
514k
    }
2593
2594
    // Store the sequence of profiles
2595
514k
    if (dwFlags & cmsFLAGS_KEEP_SEQUENCE) {
2596
0
        xform->core->Sequence = _cmsCompileProfileSequence(ContextID, nProfiles, hProfiles);
2597
0
    }
2598
514k
    else
2599
514k
        xform->core->Sequence = NULL;
2600
2601
    // If this is a cached transform, init first value, which is zero (16 bits only)
2602
514k
    if (!(dwFlags & cmsFLAGS_NOCACHE)) {
2603
2604
155k
        memset(&xform ->Cache.CacheIn, 0, sizeof(xform ->Cache.CacheIn));
2605
2606
155k
        if (xform->core->GamutCheck != NULL) {
2607
0
            TransformOnePixelWithGamutCheck(ContextID, xform, xform->Cache.CacheIn, xform->Cache.CacheOut);
2608
0
        }
2609
155k
        else {
2610
2611
155k
            xform->core->Lut->Eval16Fn(ContextID, xform ->Cache.CacheIn, xform->Cache.CacheOut, xform->core->Lut->Data);
2612
155k
        }
2613
2614
155k
    }
2615
2616
514k
    return (cmsHTRANSFORM) xform;
2617
514k
}
2618
2619
// Multiprofile transforms: Gamut check is not available here, as it is unclear from which profile the gamut comes.
2620
cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransform(cmsContext ContextID,
2621
                                                       cmsHPROFILE hProfiles[],
2622
                                                       cmsUInt32Number nProfiles,
2623
                                                       cmsUInt32Number InputFormat,
2624
                                                       cmsUInt32Number OutputFormat,
2625
                                                       cmsUInt32Number Intent,
2626
                                                       cmsUInt32Number dwFlags)
2627
1.23M
{
2628
1.23M
    cmsUInt32Number i;
2629
1.23M
    cmsBool BPC[256];
2630
1.23M
    cmsUInt32Number Intents[256];
2631
1.23M
    cmsFloat64Number AdaptationStates[256];
2632
2633
1.23M
    if (nProfiles <= 0 || nProfiles > 255) {
2634
0
         cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles);
2635
0
        return NULL;
2636
0
    }
2637
2638
3.71M
    for (i=0; i < nProfiles; i++) {
2639
2.47M
        BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE;
2640
2.47M
        Intents[i] = Intent;
2641
2.47M
        AdaptationStates[i] = cmsSetAdaptationState(ContextID, -1);
2642
2.47M
    }
2643
2644
2645
1.23M
    return cmsCreateExtendedTransform(ContextID, nProfiles, hProfiles, BPC, Intents, AdaptationStates, NULL, 0, InputFormat, OutputFormat, dwFlags);
2646
1.23M
}
2647
2648
2649
2650
cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsContext ContextID,
2651
                                           cmsHPROFILE Input,
2652
                                           cmsUInt32Number InputFormat,
2653
                                           cmsHPROFILE Output,
2654
                                           cmsUInt32Number OutputFormat,
2655
                                           cmsUInt32Number Intent,
2656
                                           cmsUInt32Number dwFlags)
2657
1.23M
{
2658
2659
1.23M
    cmsHPROFILE hArray[2];
2660
2661
1.23M
    hArray[0] = Input;
2662
1.23M
    hArray[1] = Output;
2663
2664
1.23M
    return cmsCreateMultiprofileTransform(ContextID, hArray, Output == NULL ? 1U : 2U, InputFormat, OutputFormat, Intent, dwFlags);
2665
1.23M
}
2666
2667
2668
cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransform(cmsContext ContextID,
2669
                                                   cmsHPROFILE InputProfile,
2670
                                                   cmsUInt32Number InputFormat,
2671
                                                   cmsHPROFILE OutputProfile,
2672
                                                   cmsUInt32Number OutputFormat,
2673
                                                   cmsHPROFILE ProofingProfile,
2674
                                                   cmsUInt32Number nIntent,
2675
                                                   cmsUInt32Number ProofingIntent,
2676
                                                   cmsUInt32Number dwFlags)
2677
0
{
2678
0
    cmsHPROFILE hArray[4];
2679
0
    cmsUInt32Number Intents[4];
2680
0
    cmsBool  BPC[4];
2681
0
    cmsFloat64Number Adaptation[4];
2682
0
    cmsBool  DoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION) ? TRUE : FALSE;
2683
2684
2685
0
    hArray[0]  = InputProfile; hArray[1] = ProofingProfile; hArray[2]  = ProofingProfile;               hArray[3] = OutputProfile;
2686
0
    Intents[0] = nIntent;      Intents[1] = nIntent;        Intents[2] = INTENT_RELATIVE_COLORIMETRIC;  Intents[3] = ProofingIntent;
2687
0
    BPC[0]     = DoBPC;        BPC[1] = DoBPC;              BPC[2] = 0;                                 BPC[3] = 0;
2688
2689
0
    Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationState(ContextID, -1);
2690
2691
0
    if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK)))
2692
0
        return cmsCreateTransform(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags);
2693
2694
0
    return cmsCreateExtendedTransform(ContextID, 4, hArray, BPC, Intents, Adaptation,
2695
0
                                        ProofingProfile, 1, InputFormat, OutputFormat, dwFlags);
2696
2697
0
}
2698
2699
2700
2701
// Grab the input/output formats
2702
cmsUInt32Number CMSEXPORT cmsGetTransformInputFormat(cmsContext ContextID, cmsHTRANSFORM hTransform)
2703
58.5M
{
2704
58.5M
    _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
2705
58.5M
    cmsUNUSED_PARAMETER(ContextID);
2706
2707
58.5M
    if (xform == NULL) return 0;
2708
58.5M
    return xform->InputFormat;
2709
58.5M
}
2710
2711
cmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsContext ContextID, cmsHTRANSFORM hTransform)
2712
58.5M
{
2713
58.5M
    _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
2714
58.5M
    cmsUNUSED_PARAMETER(ContextID);
2715
2716
58.5M
    if (xform == NULL) return 0;
2717
58.5M
    return xform->OutputFormat;
2718
58.5M
}
2719
2720
cmsHTRANSFORM cmsCloneTransformChangingFormats(cmsContext ContextID,
2721
                                               const cmsHTRANSFORM hTransform,
2722
                                               cmsUInt32Number InputFormat,
2723
                                               cmsUInt32Number OutputFormat)
2724
1.57k
{
2725
1.57k
    const _cmsTRANSFORM *oldXform = (const _cmsTRANSFORM *)hTransform;
2726
1.57k
    _cmsTRANSFORM *xform;
2727
1.57k
    cmsFormatter16 FromInput, ToOutput;
2728
2729
1.57k
    _cmsAssert(oldXform != NULL && oldXform->core != NULL);
2730
2731
    // We only can afford to change formatters if previous transform is at least 16 bits
2732
1.57k
    if (!(oldXform->core->dwOriginalFlags & cmsFLAGS_CAN_CHANGE_FORMATTER)) {
2733
0
        cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "cmsCloneTransformChangingFormats works only on transforms created originally with at least 16 bits of precision");
2734
0
        return NULL;
2735
0
    }
2736
2737
1.57k
    xform = _cmsMalloc(ContextID, sizeof(*xform));
2738
1.57k
    if (xform == NULL)
2739
0
        return NULL;
2740
2741
1.57k
    memcpy(xform, oldXform, sizeof(*xform));
2742
2743
1.57k
    FromInput = _cmsGetFormatter(ContextID, InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
2744
1.57k
    ToOutput  = _cmsGetFormatter(ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
2745
2746
1.57k
    if (FromInput == NULL || ToOutput == NULL) {
2747
2748
0
        cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
2749
0
        return NULL;
2750
0
    }
2751
2752
1.57k
    xform ->InputFormat  = InputFormat;
2753
1.57k
    xform ->OutputFormat = OutputFormat;
2754
1.57k
    xform ->FromInput    = FromInput;
2755
1.57k
    xform ->ToOutput     = ToOutput;
2756
1.57k
    _cmsFindFormatter(ContextID, xform, InputFormat, OutputFormat, xform->core->dwOriginalFlags);
2757
2758
1.57k
    (void)_cmsAdjustReferenceCount(&xform->core->refs, 1);
2759
2760
1.57k
    return xform;
2761
1.57k
}