Coverage Report

Created: 2026-09-14 07:34

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