Coverage Report

Created: 2025-11-07 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mupdf/thirdparty/lcms2/src/cmspack.c
Line
Count
Source
1
//---------------------------------------------------------------------------------
2
//
3
//  Little Color Management System
4
//  Copyright (c) 1998-2023 Marti Maria Saguer
5
//
6
// Permission is hereby granted, free of charge, to any person obtaining
7
// a copy of this software and associated documentation files (the "Software"),
8
// to deal in the Software without restriction, including without limitation
9
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
// and/or sell copies of the Software, and to permit persons to whom the Software
11
// is furnished to do so, subject to the following conditions:
12
//
13
// The above copyright notice and this permission notice shall be included in
14
// all copies or substantial portions of the Software.
15
//
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
//
24
//---------------------------------------------------------------------------------
25
//
26
27
#include "lcms2_internal.h"
28
29
// This module handles all formats supported by lcms. There are two flavors, 16 bits and
30
// floating point. Floating point is supported only in a subset, those formats holding
31
// cmsFloat32Number (4 bytes per component) and double (marked as 0 bytes per component
32
// as special case)
33
34
// ---------------------------------------------------------------------------
35
36
37
// This macro return words stored as big endian
38
0
#define CHANGE_ENDIAN(w)    (cmsUInt16Number) ((cmsUInt16Number) ((w)<<8)|((w)>>8))
39
40
// These macros handles reversing (negative)
41
0
#define REVERSE_FLAVOR_8(x)     ((cmsUInt8Number) (0xff-(x)))
42
0
#define REVERSE_FLAVOR_16(x)    ((cmsUInt16Number)(0xffff-(x)))
43
44
// * 0xffff / 0xff00 = (255 * 257) / (255 * 256) = 257 / 256
45
cmsINLINE cmsUInt16Number FomLabV2ToLabV4(cmsUInt16Number x)
46
0
{
47
0
    int a = (x << 8 | x) >> 8;  // * 257 / 256
48
0
    if ( a > 0xffff) return 0xffff;
49
0
    return (cmsUInt16Number) a;
50
0
}
51
52
// * 0xf00 / 0xffff = * 256 / 257
53
cmsINLINE cmsUInt16Number FomLabV4ToLabV2(cmsUInt16Number x)
54
0
{
55
0
    return (cmsUInt16Number) (((x << 8) + 0x80) / 257);
56
0
}
57
58
59
typedef struct {
60
    cmsUInt32Number Type;
61
    cmsUInt32Number Mask;
62
    cmsFormatter16  Frm;
63
64
} cmsFormatters16;
65
66
typedef struct {
67
    cmsUInt32Number    Type;
68
    cmsUInt32Number    Mask;
69
    cmsFormatterFloat  Frm;
70
71
} cmsFormattersFloat;
72
73
74
#define ANYSPACE        COLORSPACE_SH(31)
75
#define ANYCHANNELS     CHANNELS_SH(15)
76
#define ANYEXTRA        EXTRA_SH(63)
77
#define ANYPLANAR       PLANAR_SH(1)
78
#define ANYENDIAN       ENDIAN16_SH(1)
79
#define ANYSWAP         DOSWAP_SH(1)
80
#define ANYSWAPFIRST    SWAPFIRST_SH(1)
81
#define ANYFLAVOR       FLAVOR_SH(1)
82
#define ANYPREMUL       PREMUL_SH(1)
83
84
85
// Suppress waning about info never being used
86
87
#ifdef _MSC_VER
88
#pragma warning(disable : 4100)
89
#endif
90
91
// Unpacking routines (16 bits) ----------------------------------------------------------------------------------------
92
93
94
// Does almost everything but is slow
95
static
96
cmsUInt8Number* UnrollChunkyBytes(cmsContext ContextID,
97
                                  CMSREGISTER _cmsTRANSFORM* info,
98
                                  CMSREGISTER cmsUInt16Number wIn[],
99
                                  CMSREGISTER cmsUInt8Number* accum,
100
                                  CMSREGISTER cmsUInt32Number Stride)
101
0
{
102
0
    cmsUInt32Number nChan      = T_CHANNELS(info -> InputFormat);
103
0
    cmsUInt32Number DoSwap     = T_DOSWAP(info ->InputFormat);
104
0
    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
105
0
    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
106
0
    cmsUInt32Number Extra      = T_EXTRA(info -> InputFormat);
107
0
    cmsUInt32Number Premul     = T_PREMUL(info->InputFormat);
108
109
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
110
0
    cmsUInt32Number v;
111
0
    cmsUInt32Number i;
112
0
    cmsUInt32Number alpha_factor = 1;
113
114
0
    if (ExtraFirst) {
115
116
0
        if (Premul && Extra)
117
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[0]));
118
119
0
        accum += Extra;
120
0
    }
121
0
    else
122
0
    {
123
0
        if (Premul && Extra)
124
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[nChan]));
125
0
    }
126
127
0
    for (i=0; i < nChan; i++) {
128
129
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
130
131
0
        v = FROM_8_TO_16(*accum);
132
0
        v = Reverse ? REVERSE_FLAVOR_16(v) : v;
133
134
0
        if (Premul && alpha_factor > 0)
135
0
        {
136
0
            v = ((cmsUInt32Number)((cmsUInt32Number)v << 16) / alpha_factor);
137
0
            if (v > 0xffff) v = 0xffff;
138
0
        }
139
140
0
        wIn[index] = (cmsUInt16Number) v;
141
0
        accum++;
142
0
    }
143
144
0
    if (!ExtraFirst) {
145
0
        accum += Extra;
146
0
    }
147
148
0
    if (Extra == 0 && SwapFirst) {
149
0
        cmsUInt16Number tmp = wIn[0];
150
151
0
        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
152
0
        wIn[nChan-1] = tmp;
153
0
    }
154
155
0
    return accum;
156
157
0
    cmsUNUSED_PARAMETER(info);
158
0
    cmsUNUSED_PARAMETER(Stride);
159
160
0
}
161
162
163
// Extra channels are just ignored because come in the next planes
164
static
165
cmsUInt8Number* UnrollPlanarBytes(cmsContext ContextID,
166
                                  CMSREGISTER _cmsTRANSFORM* info,
167
                                  CMSREGISTER cmsUInt16Number wIn[],
168
                                  CMSREGISTER cmsUInt8Number* accum,
169
                                  CMSREGISTER cmsUInt32Number Stride)
170
0
{
171
0
    cmsUInt32Number nChan     = T_CHANNELS(info -> InputFormat);
172
0
    cmsUInt32Number DoSwap    = T_DOSWAP(info ->InputFormat);
173
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->InputFormat);
174
0
    cmsUInt32Number Reverse   = T_FLAVOR(info ->InputFormat);
175
0
    cmsUInt32Number i;
176
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
177
0
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
178
0
    cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
179
0
    cmsUInt8Number* Init = accum;
180
0
    cmsUInt32Number alpha_factor = 1;
181
182
0
    if (ExtraFirst) {
183
184
0
        if (Premul && Extra)
185
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[0]));
186
187
188
0
        accum += Extra * Stride;
189
0
    }
190
0
    else
191
0
    {
192
0
        if (Premul && Extra)
193
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[(nChan) * Stride]));
194
0
    }
195
196
0
    for (i=0; i < nChan; i++) {
197
198
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
199
0
        cmsUInt32Number v = FROM_8_TO_16(*accum);
200
201
0
        v = Reverse ? REVERSE_FLAVOR_16(v) : v;
202
203
0
        if (Premul && alpha_factor > 0)
204
0
        {
205
0
            v = ((cmsUInt32Number)((cmsUInt32Number)v << 16) / alpha_factor);
206
0
            if (v > 0xffff) v = 0xffff;
207
0
        }
208
209
0
        wIn[index] = (cmsUInt16Number) v;
210
0
        accum += Stride;
211
0
    }
212
213
0
    return (Init + 1);
214
0
}
215
216
217
// Special cases, provided for performance
218
static
219
cmsUInt8Number* Unroll4Bytes(cmsContext ContextID,
220
                             CMSREGISTER _cmsTRANSFORM* info,
221
                             CMSREGISTER cmsUInt16Number wIn[],
222
                             CMSREGISTER cmsUInt8Number* accum,
223
                             CMSREGISTER cmsUInt32Number Stride)
224
0
{
225
0
    wIn[0] = FROM_8_TO_16(*accum); accum++; // C
226
0
    wIn[1] = FROM_8_TO_16(*accum); accum++; // M
227
0
    wIn[2] = FROM_8_TO_16(*accum); accum++; // Y
228
0
    wIn[3] = FROM_8_TO_16(*accum); accum++; // K
229
230
0
    return accum;
231
232
0
    cmsUNUSED_PARAMETER(info);
233
0
    cmsUNUSED_PARAMETER(Stride);
234
0
}
235
236
static
237
cmsUInt8Number* Unroll4BytesReverse(cmsContext ContextID,
238
                                    CMSREGISTER _cmsTRANSFORM* info,
239
                                    CMSREGISTER cmsUInt16Number wIn[],
240
                                    CMSREGISTER cmsUInt8Number* accum,
241
                                    CMSREGISTER cmsUInt32Number Stride)
242
0
{
243
0
    wIn[0] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // C
244
0
    wIn[1] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // M
245
0
    wIn[2] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // Y
246
0
    wIn[3] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // K
247
248
0
    return accum;
249
250
0
    cmsUNUSED_PARAMETER(info);
251
0
    cmsUNUSED_PARAMETER(Stride);
252
0
}
253
254
static
255
cmsUInt8Number* Unroll4BytesSwapFirst(cmsContext ContextID,
256
                                      CMSREGISTER _cmsTRANSFORM* info,
257
                                      CMSREGISTER cmsUInt16Number wIn[],
258
                                      CMSREGISTER cmsUInt8Number* accum,
259
                                      CMSREGISTER cmsUInt32Number Stride)
260
0
{
261
0
    wIn[3] = FROM_8_TO_16(*accum); accum++; // K
262
0
    wIn[0] = FROM_8_TO_16(*accum); accum++; // C
263
0
    wIn[1] = FROM_8_TO_16(*accum); accum++; // M
264
0
    wIn[2] = FROM_8_TO_16(*accum); accum++; // Y
265
266
0
    return accum;
267
268
0
    cmsUNUSED_PARAMETER(info);
269
0
    cmsUNUSED_PARAMETER(Stride);
270
0
}
271
272
// KYMC
273
static
274
cmsUInt8Number* Unroll4BytesSwap(cmsContext ContextID,
275
                                 CMSREGISTER _cmsTRANSFORM* info,
276
                                 CMSREGISTER cmsUInt16Number wIn[],
277
                                 CMSREGISTER cmsUInt8Number* accum,
278
                                 CMSREGISTER cmsUInt32Number Stride)
279
0
{
280
0
    wIn[3] = FROM_8_TO_16(*accum); accum++;  // K
281
0
    wIn[2] = FROM_8_TO_16(*accum); accum++;  // Y
282
0
    wIn[1] = FROM_8_TO_16(*accum); accum++;  // M
283
0
    wIn[0] = FROM_8_TO_16(*accum); accum++;  // C
284
285
0
    return accum;
286
287
0
    cmsUNUSED_PARAMETER(info);
288
0
    cmsUNUSED_PARAMETER(Stride);
289
0
}
290
291
static
292
cmsUInt8Number* Unroll4BytesSwapSwapFirst(cmsContext ContextID,
293
                                          CMSREGISTER _cmsTRANSFORM* info,
294
                                          CMSREGISTER cmsUInt16Number wIn[],
295
                                          CMSREGISTER cmsUInt8Number* accum,
296
                                          CMSREGISTER cmsUInt32Number Stride)
297
0
{
298
0
    wIn[2] = FROM_8_TO_16(*accum); accum++;  // K
299
0
    wIn[1] = FROM_8_TO_16(*accum); accum++;  // Y
300
0
    wIn[0] = FROM_8_TO_16(*accum); accum++;  // M
301
0
    wIn[3] = FROM_8_TO_16(*accum); accum++;  // C
302
303
0
    return accum;
304
305
0
    cmsUNUSED_PARAMETER(info);
306
0
    cmsUNUSED_PARAMETER(Stride);
307
0
}
308
309
static
310
cmsUInt8Number* Unroll3Bytes(cmsContext ContextID,
311
                             CMSREGISTER _cmsTRANSFORM* info,
312
                             CMSREGISTER cmsUInt16Number wIn[],
313
                             CMSREGISTER cmsUInt8Number* accum,
314
                             CMSREGISTER cmsUInt32Number Stride)
315
0
{
316
0
    wIn[0] = FROM_8_TO_16(*accum); accum++;     // R
317
0
    wIn[1] = FROM_8_TO_16(*accum); accum++;     // G
318
0
    wIn[2] = FROM_8_TO_16(*accum); accum++;     // B
319
320
0
    return accum;
321
322
0
    cmsUNUSED_PARAMETER(info);
323
0
    cmsUNUSED_PARAMETER(Stride);
324
0
}
325
326
static
327
cmsUInt8Number* Unroll3BytesSkip1Swap(cmsContext ContextID,
328
                                      CMSREGISTER _cmsTRANSFORM* info,
329
                                      CMSREGISTER cmsUInt16Number wIn[],
330
                                      CMSREGISTER cmsUInt8Number* accum,
331
                                      CMSREGISTER cmsUInt32Number Stride)
332
0
{
333
0
    accum++; // A
334
0
    wIn[2] = FROM_8_TO_16(*accum); accum++; // B
335
0
    wIn[1] = FROM_8_TO_16(*accum); accum++; // G
336
0
    wIn[0] = FROM_8_TO_16(*accum); accum++; // R
337
338
0
    return accum;
339
340
0
    cmsUNUSED_PARAMETER(info);
341
0
    cmsUNUSED_PARAMETER(Stride);
342
0
}
343
344
static
345
cmsUInt8Number* Unroll3BytesSkip1SwapSwapFirst(cmsContext ContextID,
346
                                               CMSREGISTER _cmsTRANSFORM* info,
347
                                               CMSREGISTER cmsUInt16Number wIn[],
348
                                               CMSREGISTER cmsUInt8Number* accum,
349
                                               CMSREGISTER cmsUInt32Number Stride)
350
0
{
351
0
    wIn[2] = FROM_8_TO_16(*accum); accum++; // B
352
0
    wIn[1] = FROM_8_TO_16(*accum); accum++; // G
353
0
    wIn[0] = FROM_8_TO_16(*accum); accum++; // R
354
0
    accum++; // A
355
356
0
    return accum;
357
358
0
    cmsUNUSED_PARAMETER(info);
359
0
    cmsUNUSED_PARAMETER(Stride);
360
0
}
361
362
static
363
cmsUInt8Number* Unroll3BytesSkip1SwapFirst(cmsContext ContextID,
364
                                           CMSREGISTER _cmsTRANSFORM* info,
365
                                           CMSREGISTER cmsUInt16Number wIn[],
366
                                           CMSREGISTER cmsUInt8Number* accum,
367
                                           CMSREGISTER cmsUInt32Number Stride)
368
0
{
369
0
    accum++; // A
370
0
    wIn[0] = FROM_8_TO_16(*accum); accum++; // R
371
0
    wIn[1] = FROM_8_TO_16(*accum); accum++; // G
372
0
    wIn[2] = FROM_8_TO_16(*accum); accum++; // B
373
374
0
    return accum;
375
376
0
    cmsUNUSED_PARAMETER(info);
377
0
    cmsUNUSED_PARAMETER(Stride);
378
0
}
379
380
381
// BRG
382
static
383
cmsUInt8Number* Unroll3BytesSwap(cmsContext ContextID,
384
                                 CMSREGISTER _cmsTRANSFORM* info,
385
                                 CMSREGISTER cmsUInt16Number wIn[],
386
                                 CMSREGISTER cmsUInt8Number* accum,
387
                                 CMSREGISTER cmsUInt32Number Stride)
388
0
{
389
0
    wIn[2] = FROM_8_TO_16(*accum); accum++;     // B
390
0
    wIn[1] = FROM_8_TO_16(*accum); accum++;     // G
391
0
    wIn[0] = FROM_8_TO_16(*accum); accum++;     // R
392
393
0
    return accum;
394
395
0
    cmsUNUSED_PARAMETER(info);
396
0
    cmsUNUSED_PARAMETER(Stride);
397
0
}
398
399
static
400
cmsUInt8Number* UnrollLabV2_8(cmsContext ContextID,
401
                              CMSREGISTER _cmsTRANSFORM* info,
402
                              CMSREGISTER cmsUInt16Number wIn[],
403
                              CMSREGISTER cmsUInt8Number* accum,
404
                              CMSREGISTER cmsUInt32Number Stride)
405
0
{
406
0
    wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // L
407
0
    wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // a
408
0
    wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // b
409
410
0
    return accum;
411
412
0
    cmsUNUSED_PARAMETER(info);
413
0
    cmsUNUSED_PARAMETER(Stride);
414
0
}
415
416
static
417
cmsUInt8Number* UnrollALabV2_8(cmsContext ContextID,
418
                               CMSREGISTER _cmsTRANSFORM* info,
419
                               CMSREGISTER cmsUInt16Number wIn[],
420
                               CMSREGISTER cmsUInt8Number* accum,
421
                               CMSREGISTER cmsUInt32Number Stride)
422
0
{
423
0
    accum++;  // A
424
0
    wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // L
425
0
    wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // a
426
0
    wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // b
427
428
0
    return accum;
429
430
0
    cmsUNUSED_PARAMETER(info);
431
0
    cmsUNUSED_PARAMETER(Stride);
432
0
}
433
434
static
435
cmsUInt8Number* UnrollLabV2_16(cmsContext ContextID,
436
                               CMSREGISTER _cmsTRANSFORM* info,
437
                               CMSREGISTER cmsUInt16Number wIn[],
438
                               CMSREGISTER cmsUInt8Number* accum,
439
                               CMSREGISTER cmsUInt32Number Stride)
440
0
{
441
0
    wIn[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // L
442
0
    wIn[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // a
443
0
    wIn[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // b
444
445
0
    return accum;
446
447
0
    cmsUNUSED_PARAMETER(info);
448
0
    cmsUNUSED_PARAMETER(Stride);
449
0
}
450
451
// for duplex
452
static
453
cmsUInt8Number* Unroll2Bytes(cmsContext ContextID,
454
                             CMSREGISTER _cmsTRANSFORM* info,
455
                             CMSREGISTER cmsUInt16Number wIn[],
456
                             CMSREGISTER cmsUInt8Number* accum,
457
                             CMSREGISTER cmsUInt32Number Stride)
458
0
{
459
0
    wIn[0] = FROM_8_TO_16(*accum); accum++;     // ch1
460
0
    wIn[1] = FROM_8_TO_16(*accum); accum++;     // ch2
461
462
0
    return accum;
463
464
0
    cmsUNUSED_PARAMETER(info);
465
0
    cmsUNUSED_PARAMETER(Stride);
466
0
}
467
468
469
470
471
// Monochrome duplicates L into RGB for null-transforms
472
static
473
cmsUInt8Number* Unroll1Byte(cmsContext ContextID,
474
                            CMSREGISTER _cmsTRANSFORM* info,
475
                            CMSREGISTER cmsUInt16Number wIn[],
476
                            CMSREGISTER cmsUInt8Number* accum,
477
                            CMSREGISTER cmsUInt32Number Stride)
478
0
{
479
0
    wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++;     // L
480
481
0
    return accum;
482
483
0
    cmsUNUSED_PARAMETER(info);
484
0
    cmsUNUSED_PARAMETER(Stride);
485
0
}
486
487
488
static
489
cmsUInt8Number* Unroll1ByteSkip1(cmsContext ContextID,
490
                                 CMSREGISTER _cmsTRANSFORM* info,
491
                                 CMSREGISTER cmsUInt16Number wIn[],
492
                                 CMSREGISTER cmsUInt8Number* accum,
493
                                 CMSREGISTER cmsUInt32Number Stride)
494
0
{
495
0
    wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++;     // L
496
0
    accum += 1;
497
498
0
    return accum;
499
500
0
    cmsUNUSED_PARAMETER(info);
501
0
    cmsUNUSED_PARAMETER(Stride);
502
0
}
503
504
static
505
cmsUInt8Number* Unroll1ByteSkip2(cmsContext ContextID,
506
                                 CMSREGISTER _cmsTRANSFORM* info,
507
                                 CMSREGISTER cmsUInt16Number wIn[],
508
                                 CMSREGISTER cmsUInt8Number* accum,
509
                                 CMSREGISTER cmsUInt32Number Stride)
510
0
{
511
0
    wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++;     // L
512
0
    accum += 2;
513
514
0
    return accum;
515
516
0
    cmsUNUSED_PARAMETER(info);
517
0
    cmsUNUSED_PARAMETER(Stride);
518
0
}
519
520
static
521
cmsUInt8Number* Unroll1ByteReversed(cmsContext ContextID,
522
                                    CMSREGISTER _cmsTRANSFORM* info,
523
                                    CMSREGISTER cmsUInt16Number wIn[],
524
                                    CMSREGISTER cmsUInt8Number* accum,
525
                                    CMSREGISTER cmsUInt32Number Stride)
526
0
{
527
0
    wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(FROM_8_TO_16(*accum)); accum++;     // L
528
529
0
    return accum;
530
531
0
    cmsUNUSED_PARAMETER(info);
532
0
    cmsUNUSED_PARAMETER(Stride);
533
0
}
534
535
536
static
537
cmsUInt8Number* UnrollAnyWords(cmsContext ContextID,
538
                               CMSREGISTER _cmsTRANSFORM* info,
539
                               CMSREGISTER cmsUInt16Number wIn[],
540
                               CMSREGISTER cmsUInt8Number* accum,
541
                               CMSREGISTER cmsUInt32Number Stride)
542
0
{
543
0
   cmsUInt32Number nChan       = T_CHANNELS(info -> InputFormat);
544
0
   cmsUInt32Number SwapEndian  = T_ENDIAN16(info -> InputFormat);
545
0
   cmsUInt32Number DoSwap      = T_DOSWAP(info ->InputFormat);
546
0
   cmsUInt32Number Reverse     = T_FLAVOR(info ->InputFormat);
547
0
   cmsUInt32Number SwapFirst   = T_SWAPFIRST(info -> InputFormat);
548
0
   cmsUInt32Number Extra       = T_EXTRA(info -> InputFormat);
549
0
   cmsUInt32Number ExtraFirst  = DoSwap ^ SwapFirst;
550
0
   cmsUInt32Number i;
551
552
0
    if (ExtraFirst) {
553
0
        accum += Extra * sizeof(cmsUInt16Number);
554
0
    }
555
556
0
    for (i=0; i < nChan; i++) {
557
558
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
559
0
        cmsUInt16Number v = *(cmsUInt16Number*) accum;
560
561
0
        if (SwapEndian)
562
0
            v = CHANGE_ENDIAN(v);
563
564
0
        wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;
565
566
0
        accum += sizeof(cmsUInt16Number);
567
0
    }
568
569
0
    if (!ExtraFirst) {
570
0
        accum += Extra * sizeof(cmsUInt16Number);
571
0
    }
572
573
0
    if (Extra == 0 && SwapFirst) {
574
575
0
        cmsUInt16Number tmp = wIn[0];
576
577
0
        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
578
0
        wIn[nChan-1] = tmp;
579
0
    }
580
581
0
    return accum;
582
583
0
    cmsUNUSED_PARAMETER(Stride);
584
0
}
585
586
587
static
588
cmsUInt8Number* UnrollAnyWordsPremul(cmsContext ContextID,
589
                                     CMSREGISTER _cmsTRANSFORM* info,
590
                                     CMSREGISTER cmsUInt16Number wIn[],
591
                                     CMSREGISTER cmsUInt8Number* accum,
592
                                     CMSREGISTER cmsUInt32Number Stride)
593
0
{
594
0
   cmsUInt32Number nChan       = T_CHANNELS(info -> InputFormat);
595
0
   cmsUInt32Number SwapEndian  = T_ENDIAN16(info -> InputFormat);
596
0
   cmsUInt32Number DoSwap      = T_DOSWAP(info ->InputFormat);
597
0
   cmsUInt32Number Reverse     = T_FLAVOR(info ->InputFormat);
598
0
   cmsUInt32Number SwapFirst   = T_SWAPFIRST(info -> InputFormat);
599
0
   cmsUInt32Number ExtraFirst  = DoSwap ^ SwapFirst;
600
0
   cmsUInt32Number i;
601
602
0
   cmsUInt16Number alpha = (ExtraFirst ? accum[0] : accum[nChan - 1]);
603
0
   cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));
604
605
0
    if (ExtraFirst) {
606
0
        accum += sizeof(cmsUInt16Number);
607
0
    }
608
609
0
    for (i=0; i < nChan; i++) {
610
611
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
612
0
        cmsUInt32Number v = *(cmsUInt16Number*) accum;
613
614
0
        if (SwapEndian)
615
0
            v = CHANGE_ENDIAN(v);
616
617
0
        if (alpha_factor > 0) {
618
619
0
            v = (v << 16) / alpha_factor;
620
0
            if (v > 0xffff) v = 0xffff;
621
0
        }
622
623
0
        wIn[index] = (cmsUInt16Number) (Reverse ? REVERSE_FLAVOR_16(v) : v);
624
625
0
        accum += sizeof(cmsUInt16Number);
626
0
    }
627
628
0
    if (!ExtraFirst) {
629
0
        accum += sizeof(cmsUInt16Number);
630
0
    }
631
632
0
    return accum;
633
634
0
    cmsUNUSED_PARAMETER(Stride);
635
0
}
636
637
638
639
static
640
cmsUInt8Number* UnrollPlanarWords(cmsContext ContextID,
641
                                  CMSREGISTER _cmsTRANSFORM* info,
642
                                  CMSREGISTER cmsUInt16Number wIn[],
643
                                  CMSREGISTER cmsUInt8Number* accum,
644
                                  CMSREGISTER cmsUInt32Number Stride)
645
0
{
646
0
    cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
647
0
    cmsUInt32Number DoSwap= T_DOSWAP(info ->InputFormat);
648
0
    cmsUInt32Number Reverse= T_FLAVOR(info ->InputFormat);
649
0
    cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);
650
0
    cmsUInt32Number i;
651
0
    cmsUInt8Number* Init = accum;
652
653
0
    if (DoSwap) {
654
0
        accum += T_EXTRA(info -> InputFormat) * Stride;
655
0
    }
656
657
0
    for (i=0; i < nChan; i++) {
658
659
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
660
0
        cmsUInt16Number v = *(cmsUInt16Number*) accum;
661
662
0
        if (SwapEndian)
663
0
            v = CHANGE_ENDIAN(v);
664
665
0
        wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;
666
667
0
        accum +=  Stride;
668
0
    }
669
670
0
    return (Init + sizeof(cmsUInt16Number));
671
0
}
672
673
static
674
cmsUInt8Number* UnrollPlanarWordsPremul(cmsContext ContextID,
675
                                        CMSREGISTER _cmsTRANSFORM* info,
676
                                        CMSREGISTER cmsUInt16Number wIn[],
677
                                        CMSREGISTER cmsUInt8Number* accum,
678
                                        CMSREGISTER cmsUInt32Number Stride)
679
0
{
680
0
    cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
681
0
    cmsUInt32Number DoSwap= T_DOSWAP(info ->InputFormat);
682
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
683
0
    cmsUInt32Number Reverse= T_FLAVOR(info ->InputFormat);
684
0
    cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);
685
0
    cmsUInt32Number i;
686
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
687
0
    cmsUInt8Number* Init = accum;
688
689
0
    cmsUInt16Number  alpha = (ExtraFirst ? accum[0] : accum[(nChan - 1) * Stride]);
690
0
    cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));
691
692
0
    if (ExtraFirst) {
693
0
        accum += Stride;
694
0
    }
695
696
0
    for (i=0; i < nChan; i++) {
697
698
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
699
0
        cmsUInt32Number v = (cmsUInt32Number) *(cmsUInt16Number*) accum;
700
701
0
        if (SwapEndian)
702
0
            v = CHANGE_ENDIAN(v);
703
704
0
        if (alpha_factor > 0) {
705
706
0
            v = (v << 16) / alpha_factor;
707
0
            if (v > 0xffff) v = 0xffff;
708
0
        }
709
710
0
        wIn[index] = (cmsUInt16Number) (Reverse ? REVERSE_FLAVOR_16(v) : v);
711
712
0
        accum +=  Stride;
713
0
    }
714
715
0
    return (Init + sizeof(cmsUInt16Number));
716
0
}
717
718
static
719
cmsUInt8Number* Unroll4Words(cmsContext ContextID,
720
                             CMSREGISTER _cmsTRANSFORM* info,
721
                             CMSREGISTER cmsUInt16Number wIn[],
722
                             CMSREGISTER cmsUInt8Number* accum,
723
                             CMSREGISTER cmsUInt32Number Stride)
724
0
{
725
0
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
726
0
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
727
0
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
728
0
    wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
729
730
0
    return accum;
731
732
0
    cmsUNUSED_PARAMETER(info);
733
0
    cmsUNUSED_PARAMETER(Stride);
734
0
}
735
736
static
737
cmsUInt8Number* Unroll4WordsReverse(cmsContext ContextID,
738
                                    CMSREGISTER _cmsTRANSFORM* info,
739
                                    CMSREGISTER cmsUInt16Number wIn[],
740
                                    CMSREGISTER cmsUInt8Number* accum,
741
                                    CMSREGISTER cmsUInt32Number Stride)
742
0
{
743
0
    wIn[0] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // C
744
0
    wIn[1] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // M
745
0
    wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // Y
746
0
    wIn[3] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // K
747
748
0
    return accum;
749
750
0
    cmsUNUSED_PARAMETER(info);
751
0
    cmsUNUSED_PARAMETER(Stride);
752
0
}
753
754
static
755
cmsUInt8Number* Unroll4WordsSwapFirst(cmsContext ContextID,
756
                                      CMSREGISTER _cmsTRANSFORM* info,
757
                                      CMSREGISTER cmsUInt16Number wIn[],
758
                                      CMSREGISTER cmsUInt8Number* accum,
759
                                      CMSREGISTER cmsUInt32Number Stride)
760
0
{
761
0
    wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
762
0
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
763
0
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
764
0
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
765
766
0
    return accum;
767
768
0
    cmsUNUSED_PARAMETER(info);
769
0
    cmsUNUSED_PARAMETER(Stride);
770
0
}
771
772
// KYMC
773
static
774
cmsUInt8Number* Unroll4WordsSwap(cmsContext ContextID,
775
                                 CMSREGISTER _cmsTRANSFORM* info,
776
                                 CMSREGISTER cmsUInt16Number wIn[],
777
                                 CMSREGISTER cmsUInt8Number* accum,
778
                                 CMSREGISTER cmsUInt32Number Stride)
779
0
{
780
0
    wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
781
0
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
782
0
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
783
0
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
784
785
0
    return accum;
786
787
0
    cmsUNUSED_PARAMETER(info);
788
0
    cmsUNUSED_PARAMETER(Stride);
789
0
}
790
791
static
792
cmsUInt8Number* Unroll4WordsSwapSwapFirst(cmsContext ContextID,
793
                                          CMSREGISTER _cmsTRANSFORM* info,
794
                                          CMSREGISTER cmsUInt16Number wIn[],
795
                                          CMSREGISTER cmsUInt8Number* accum,
796
                                          CMSREGISTER cmsUInt32Number Stride)
797
0
{
798
0
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // K
799
0
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // Y
800
0
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // M
801
0
    wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // C
802
803
0
    return accum;
804
805
0
    cmsUNUSED_PARAMETER(info);
806
0
    cmsUNUSED_PARAMETER(Stride);
807
0
}
808
809
static
810
cmsUInt8Number* Unroll3Words(cmsContext ContextID,
811
                             CMSREGISTER _cmsTRANSFORM* info,
812
                             CMSREGISTER cmsUInt16Number wIn[],
813
                             CMSREGISTER cmsUInt8Number* accum,
814
                             CMSREGISTER cmsUInt32Number Stride)
815
0
{
816
0
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2;  // C R
817
0
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2;  // M G
818
0
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2;  // Y B
819
820
0
    return accum;
821
822
0
    cmsUNUSED_PARAMETER(info);
823
0
    cmsUNUSED_PARAMETER(Stride);
824
0
}
825
826
static
827
cmsUInt8Number* Unroll3WordsSwap(cmsContext ContextID,
828
                                 CMSREGISTER _cmsTRANSFORM* info,
829
                                 CMSREGISTER cmsUInt16Number wIn[],
830
                                 CMSREGISTER cmsUInt8Number* accum,
831
                                 CMSREGISTER cmsUInt32Number Stride)
832
0
{
833
0
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2;  // C R
834
0
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2;  // M G
835
0
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2;  // Y B
836
837
0
    return accum;
838
839
0
    cmsUNUSED_PARAMETER(info);
840
0
    cmsUNUSED_PARAMETER(Stride);
841
0
}
842
843
static
844
cmsUInt8Number* Unroll3WordsSkip1Swap(cmsContext ContextID,
845
                                      CMSREGISTER _cmsTRANSFORM* info,
846
                                      CMSREGISTER cmsUInt16Number wIn[],
847
                                      CMSREGISTER cmsUInt8Number* accum,
848
                                      CMSREGISTER cmsUInt32Number Stride)
849
0
{
850
0
    accum += 2; // A
851
0
    wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // R
852
0
    wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G
853
0
    wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // B
854
855
0
    return accum;
856
857
0
    cmsUNUSED_PARAMETER(info);
858
0
    cmsUNUSED_PARAMETER(Stride);
859
0
}
860
861
static
862
cmsUInt8Number* Unroll3WordsSkip1SwapFirst(cmsContext ContextID,
863
                                           CMSREGISTER _cmsTRANSFORM* info,
864
                                           CMSREGISTER cmsUInt16Number wIn[],
865
                                           CMSREGISTER cmsUInt8Number* accum,
866
                                           CMSREGISTER cmsUInt32Number Stride)
867
0
{
868
0
    accum += 2; // A
869
0
    wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // R
870
0
    wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G
871
0
    wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // B
872
873
0
    return accum;
874
875
0
    cmsUNUSED_PARAMETER(info);
876
0
    cmsUNUSED_PARAMETER(Stride);
877
0
}
878
879
static
880
cmsUInt8Number* Unroll1Word(cmsContext ContextID,
881
                            CMSREGISTER _cmsTRANSFORM* info,
882
                            CMSREGISTER cmsUInt16Number wIn[],
883
                            CMSREGISTER cmsUInt8Number* accum,
884
                            CMSREGISTER cmsUInt32Number Stride)
885
0
{
886
0
    wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum; accum+= 2;   // L
887
888
0
    return accum;
889
890
0
    cmsUNUSED_PARAMETER(info);
891
0
    cmsUNUSED_PARAMETER(Stride);
892
0
}
893
894
static
895
cmsUInt8Number* Unroll1WordReversed(cmsContext ContextID,
896
                                    CMSREGISTER _cmsTRANSFORM* info,
897
                                    CMSREGISTER cmsUInt16Number wIn[],
898
                                    CMSREGISTER cmsUInt8Number* accum,
899
                                    CMSREGISTER cmsUInt32Number Stride)
900
0
{
901
0
    wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2;
902
903
0
    return accum;
904
905
0
    cmsUNUSED_PARAMETER(info);
906
0
    cmsUNUSED_PARAMETER(Stride);
907
0
}
908
909
static
910
cmsUInt8Number* Unroll1WordSkip3(cmsContext ContextID,
911
                                 CMSREGISTER _cmsTRANSFORM* info,
912
                                 CMSREGISTER cmsUInt16Number wIn[],
913
                                 CMSREGISTER cmsUInt8Number* accum,
914
                                 CMSREGISTER cmsUInt32Number Stride)
915
0
{
916
0
    wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum;
917
918
0
    accum += 8;
919
920
0
    return accum;
921
922
0
    cmsUNUSED_PARAMETER(info);
923
0
    cmsUNUSED_PARAMETER(Stride);
924
0
}
925
926
static
927
cmsUInt8Number* Unroll2Words(cmsContext ContextID,
928
                             CMSREGISTER _cmsTRANSFORM* info,
929
                             CMSREGISTER cmsUInt16Number wIn[],
930
                             CMSREGISTER cmsUInt8Number* accum,
931
                             CMSREGISTER cmsUInt32Number Stride)
932
0
{
933
0
    wIn[0] = *(cmsUInt16Number*) accum; accum += 2;    // ch1
934
0
    wIn[1] = *(cmsUInt16Number*) accum; accum += 2;    // ch2
935
936
0
    return accum;
937
938
0
    cmsUNUSED_PARAMETER(info);
939
0
    cmsUNUSED_PARAMETER(Stride);
940
0
}
941
942
943
// This is a conversion of Lab double to 16 bits
944
static
945
cmsUInt8Number* UnrollLabDoubleTo16(cmsContext ContextID,
946
                                    CMSREGISTER _cmsTRANSFORM* info,
947
                                    CMSREGISTER cmsUInt16Number wIn[],
948
                                    CMSREGISTER cmsUInt8Number* accum,
949
                                    CMSREGISTER cmsUInt32Number  Stride)
950
0
{
951
0
    if (T_PLANAR(info -> InputFormat)) {
952
953
0
        cmsCIELab Lab;
954
0
        cmsUInt8Number* pos_L;
955
0
        cmsUInt8Number* pos_a;
956
0
        cmsUInt8Number* pos_b;
957
958
0
        pos_L = accum;
959
0
        pos_a = accum + Stride;
960
0
        pos_b = accum + Stride * 2;
961
962
0
        Lab.L = *(cmsFloat64Number*) pos_L;
963
0
        Lab.a = *(cmsFloat64Number*) pos_a;
964
0
        Lab.b = *(cmsFloat64Number*) pos_b;
965
966
0
        cmsFloat2LabEncoded(ContextID, wIn, &Lab);
967
0
        return accum + sizeof(cmsFloat64Number);
968
0
    }
969
0
    else {
970
971
0
        cmsFloat2LabEncoded(ContextID, wIn, (cmsCIELab*) accum);
972
0
        accum += sizeof(cmsCIELab) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number);
973
0
        return accum;
974
0
    }
975
0
}
976
977
978
// This is a conversion of Lab float to 16 bits
979
static
980
cmsUInt8Number* UnrollLabFloatTo16(cmsContext ContextID,
981
                                   CMSREGISTER _cmsTRANSFORM* info,
982
                                   CMSREGISTER cmsUInt16Number wIn[],
983
                                   CMSREGISTER cmsUInt8Number* accum,
984
                                   CMSREGISTER cmsUInt32Number  Stride)
985
0
{
986
0
    cmsCIELab Lab;
987
988
0
    if (T_PLANAR(info -> InputFormat)) {
989
990
0
        cmsUInt8Number* pos_L;
991
0
        cmsUInt8Number* pos_a;
992
0
        cmsUInt8Number* pos_b;
993
994
0
        pos_L = accum;
995
0
        pos_a = accum + Stride;
996
0
        pos_b = accum + Stride * 2;
997
998
0
        Lab.L = *(cmsFloat32Number*)pos_L;
999
0
        Lab.a = *(cmsFloat32Number*)pos_a;
1000
0
        Lab.b = *(cmsFloat32Number*)pos_b;
1001
1002
0
        cmsFloat2LabEncoded(ContextID, wIn, &Lab);
1003
0
        return accum + sizeof(cmsFloat32Number);
1004
0
    }
1005
0
    else {
1006
1007
0
        Lab.L = ((cmsFloat32Number*) accum)[0];
1008
0
        Lab.a = ((cmsFloat32Number*) accum)[1];
1009
0
        Lab.b = ((cmsFloat32Number*) accum)[2];
1010
1011
0
        cmsFloat2LabEncoded(ContextID, wIn, &Lab);
1012
0
        accum += (3 + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat32Number);
1013
0
        return accum;
1014
0
    }
1015
0
}
1016
1017
// This is a conversion of XYZ double to 16 bits
1018
static
1019
cmsUInt8Number* UnrollXYZDoubleTo16(cmsContext ContextID,
1020
                                    CMSREGISTER _cmsTRANSFORM* info,
1021
                                    CMSREGISTER cmsUInt16Number wIn[],
1022
                                    CMSREGISTER cmsUInt8Number* accum,
1023
                                    CMSREGISTER cmsUInt32Number Stride)
1024
0
{
1025
0
    if (T_PLANAR(info -> InputFormat)) {
1026
1027
0
        cmsCIEXYZ XYZ;
1028
0
        cmsUInt8Number* pos_X;
1029
0
        cmsUInt8Number* pos_Y;
1030
0
        cmsUInt8Number* pos_Z;
1031
1032
0
        pos_X = accum;
1033
0
        pos_Y = accum + Stride;
1034
0
        pos_Z = accum + Stride * 2;
1035
1036
0
        XYZ.X = *(cmsFloat64Number*)pos_X;
1037
0
        XYZ.Y = *(cmsFloat64Number*)pos_Y;
1038
0
        XYZ.Z = *(cmsFloat64Number*)pos_Z;
1039
1040
0
        cmsFloat2XYZEncoded(ContextID, wIn, &XYZ);
1041
1042
0
        return accum + sizeof(cmsFloat64Number);
1043
1044
0
    }
1045
1046
0
    else {
1047
0
        cmsFloat2XYZEncoded(ContextID, wIn, (cmsCIEXYZ*) accum);
1048
0
        accum += sizeof(cmsCIEXYZ) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number);
1049
1050
0
        return accum;
1051
0
    }
1052
0
}
1053
1054
// This is a conversion of XYZ float to 16 bits
1055
static
1056
cmsUInt8Number* UnrollXYZFloatTo16(cmsContext ContextID,
1057
                                   CMSREGISTER _cmsTRANSFORM* info,
1058
                                   CMSREGISTER cmsUInt16Number wIn[],
1059
                                   CMSREGISTER cmsUInt8Number* accum,
1060
                                   CMSREGISTER cmsUInt32Number Stride)
1061
0
{
1062
0
    if (T_PLANAR(info -> InputFormat)) {
1063
1064
0
        cmsCIEXYZ XYZ;
1065
0
        cmsUInt8Number* pos_X;
1066
0
        cmsUInt8Number* pos_Y;
1067
0
        cmsUInt8Number* pos_Z;
1068
1069
0
        pos_X = accum;
1070
0
        pos_Y = accum + Stride;
1071
0
        pos_Z = accum + Stride * 2;
1072
1073
0
        XYZ.X = *(cmsFloat32Number*)pos_X;
1074
0
        XYZ.Y = *(cmsFloat32Number*)pos_Y;
1075
0
        XYZ.Z = *(cmsFloat32Number*)pos_Z;
1076
1077
0
        cmsFloat2XYZEncoded(ContextID, wIn, &XYZ);
1078
1079
0
        return accum + sizeof(cmsFloat32Number);
1080
1081
0
    }
1082
1083
0
    else {
1084
0
        cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
1085
0
        cmsCIEXYZ XYZ;
1086
1087
0
        XYZ.X = Pt[0];
1088
0
        XYZ.Y = Pt[1];
1089
0
        XYZ.Z = Pt[2];
1090
0
        cmsFloat2XYZEncoded(ContextID, wIn, &XYZ);
1091
1092
0
        accum += 3 * sizeof(cmsFloat32Number) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat32Number);
1093
1094
0
        return accum;
1095
0
    }
1096
0
}
1097
1098
// Check if space is marked as ink
1099
cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type)
1100
0
{
1101
0
    switch (T_COLORSPACE(Type)) {
1102
1103
0
     case PT_CMY:
1104
0
     case PT_CMYK:
1105
0
     case PT_MCH5:
1106
0
     case PT_MCH6:
1107
0
     case PT_MCH7:
1108
0
     case PT_MCH8:
1109
0
     case PT_MCH9:
1110
0
     case PT_MCH10:
1111
0
     case PT_MCH11:
1112
0
     case PT_MCH12:
1113
0
     case PT_MCH13:
1114
0
     case PT_MCH14:
1115
0
     case PT_MCH15: return TRUE;
1116
1117
0
     default: return FALSE;
1118
0
    }
1119
0
}
1120
1121
// Return the size in bytes of a given formatter
1122
static
1123
cmsUInt32Number PixelSize(cmsUInt32Number Format)
1124
6
{
1125
6
    cmsUInt32Number fmt_bytes = T_BYTES(Format);
1126
1127
    // For double, the T_BYTES field is zero
1128
6
    if (fmt_bytes == 0)
1129
0
        return sizeof(cmsUInt64Number);
1130
1131
    // Otherwise, it is already correct for all formats
1132
6
    return fmt_bytes;
1133
6
}
1134
1135
// Inks does come in percentage, remaining cases are between 0..1.0, again to 16 bits
1136
static
1137
cmsUInt8Number* UnrollDoubleTo16(cmsContext ContextID,
1138
                                 CMSREGISTER _cmsTRANSFORM* info,
1139
                                 CMSREGISTER cmsUInt16Number wIn[],
1140
                                 CMSREGISTER cmsUInt8Number* accum,
1141
                                 CMSREGISTER cmsUInt32Number Stride)
1142
0
{
1143
1144
0
    cmsUInt32Number nChan      = T_CHANNELS(info -> InputFormat);
1145
0
    cmsUInt32Number DoSwap     = T_DOSWAP(info ->InputFormat);
1146
0
    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
1147
0
    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
1148
0
    cmsUInt32Number Extra      = T_EXTRA(info -> InputFormat);
1149
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1150
0
    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
1151
0
    cmsFloat64Number v;
1152
0
    cmsUInt16Number  vi;
1153
0
    cmsUInt32Number i, start = 0;
1154
0
    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
1155
1156
1157
0
    Stride /= PixelSize(info->InputFormat);
1158
1159
0
    if (ExtraFirst)
1160
0
            start = Extra;
1161
1162
0
    for (i=0; i < nChan; i++) {
1163
1164
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1165
1166
0
        if (Planar)
1167
0
            v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[(i + start) * Stride];
1168
0
        else
1169
0
            v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[i + start];
1170
1171
0
        vi = _cmsQuickSaturateWord(v * maximum);
1172
1173
0
        if (Reverse)
1174
0
            vi = REVERSE_FLAVOR_16(vi);
1175
1176
0
        wIn[index] = vi;
1177
0
    }
1178
1179
1180
0
    if (Extra == 0 && SwapFirst) {
1181
0
        cmsUInt16Number tmp = wIn[0];
1182
1183
0
        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
1184
0
        wIn[nChan-1] = tmp;
1185
0
    }
1186
1187
0
    if (T_PLANAR(info -> InputFormat))
1188
0
        return accum + sizeof(cmsFloat64Number);
1189
0
    else
1190
0
        return accum + (nChan + Extra) * sizeof(cmsFloat64Number);
1191
0
}
1192
1193
1194
1195
static
1196
cmsUInt8Number* UnrollFloatTo16(cmsContext ContextID,
1197
                                CMSREGISTER _cmsTRANSFORM* info,
1198
                                CMSREGISTER cmsUInt16Number wIn[],
1199
                                CMSREGISTER cmsUInt8Number* accum,
1200
                                CMSREGISTER cmsUInt32Number Stride)
1201
0
{
1202
1203
0
    cmsUInt32Number nChan  = T_CHANNELS(info -> InputFormat);
1204
0
    cmsUInt32Number DoSwap   = T_DOSWAP(info ->InputFormat);
1205
0
    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
1206
0
    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
1207
0
    cmsUInt32Number Extra   = T_EXTRA(info -> InputFormat);
1208
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1209
0
    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
1210
0
    cmsFloat32Number v;
1211
0
    cmsUInt16Number  vi;
1212
0
    cmsUInt32Number i, start = 0;
1213
0
    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
1214
1215
0
    Stride /= PixelSize(info->InputFormat);
1216
1217
0
    if (ExtraFirst)
1218
0
            start = Extra;
1219
1220
0
    for (i=0; i < nChan; i++) {
1221
1222
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1223
1224
0
        if (Planar)
1225
0
            v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride];
1226
0
        else
1227
0
            v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[i + start];
1228
1229
0
        vi = _cmsQuickSaturateWord(v * maximum);
1230
1231
0
        if (Reverse)
1232
0
            vi = REVERSE_FLAVOR_16(vi);
1233
1234
0
        wIn[index] = vi;
1235
0
    }
1236
1237
1238
0
    if (Extra == 0 && SwapFirst) {
1239
0
        cmsUInt16Number tmp = wIn[0];
1240
1241
0
        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
1242
0
        wIn[nChan-1] = tmp;
1243
0
    }
1244
1245
0
    if (T_PLANAR(info -> InputFormat))
1246
0
        return accum + sizeof(cmsFloat32Number);
1247
0
    else
1248
0
        return accum + (nChan + Extra) * sizeof(cmsFloat32Number);
1249
0
}
1250
1251
1252
1253
1254
// For 1 channel, we need to duplicate data (it comes in 0..1.0 range)
1255
static
1256
cmsUInt8Number* UnrollDouble1Chan(cmsContext ContextID,
1257
                                  CMSREGISTER _cmsTRANSFORM* info,
1258
                                  CMSREGISTER cmsUInt16Number wIn[],
1259
                                  CMSREGISTER cmsUInt8Number* accum,
1260
                                  CMSREGISTER cmsUInt32Number Stride)
1261
0
{
1262
0
    cmsFloat64Number* Inks = (cmsFloat64Number*) accum;
1263
1264
0
    wIn[0] = wIn[1] = wIn[2] = _cmsQuickSaturateWord(Inks[0] * 65535.0);
1265
1266
0
    return accum + sizeof(cmsFloat64Number);
1267
1268
0
    cmsUNUSED_PARAMETER(info);
1269
0
    cmsUNUSED_PARAMETER(Stride);
1270
0
}
1271
1272
//-------------------------------------------------------------------------------------------------------------------
1273
1274
// For anything going from cmsUInt8Number
1275
static
1276
cmsUInt8Number* Unroll8ToFloat(cmsContext ContextID,
1277
                               _cmsTRANSFORM* info,
1278
                               cmsFloat32Number wIn[],
1279
                               cmsUInt8Number* accum,
1280
                               cmsUInt32Number Stride)
1281
0
{
1282
1283
0
    cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
1284
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
1285
0
    cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
1286
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
1287
0
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
1288
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1289
0
    cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
1290
0
    cmsFloat32Number v;
1291
0
    cmsUInt32Number i, start = 0;
1292
1293
0
    Stride /= PixelSize(info->InputFormat);
1294
1295
0
    if (ExtraFirst)
1296
0
        start = Extra;
1297
1298
0
    for (i = 0; i < nChan; i++) {
1299
1300
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1301
1302
0
        if (Planar)
1303
0
            v = (cmsFloat32Number) ((cmsUInt8Number *)accum)[(i + start) * Stride];
1304
0
        else
1305
0
            v = (cmsFloat32Number) ((cmsUInt8Number *)accum)[i + start];
1306
1307
0
        v /= 255.0F;
1308
1309
0
        wIn[index] = Reverse ? 1 - v : v;
1310
0
    }
1311
1312
1313
0
    if (Extra == 0 && SwapFirst) {
1314
0
        cmsFloat32Number tmp = wIn[0];
1315
1316
0
        memmove(&wIn[0], &wIn[1], (nChan - 1) * sizeof(cmsFloat32Number));
1317
0
        wIn[nChan - 1] = tmp;
1318
0
    }
1319
1320
0
    if (T_PLANAR(info->InputFormat))
1321
0
        return accum + sizeof(cmsUInt8Number);
1322
0
    else
1323
0
        return accum + (nChan + Extra) * sizeof(cmsUInt8Number);
1324
0
}
1325
1326
1327
// For anything going from cmsUInt16Number
1328
static
1329
cmsUInt8Number* Unroll16ToFloat(cmsContext ContextID,
1330
                                _cmsTRANSFORM* info,
1331
                                cmsFloat32Number wIn[],
1332
                                cmsUInt8Number* accum,
1333
                                cmsUInt32Number Stride)
1334
6
{
1335
1336
6
    cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
1337
6
    cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
1338
6
    cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
1339
6
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
1340
6
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
1341
6
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1342
6
    cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
1343
6
    cmsFloat32Number v;
1344
6
    cmsUInt32Number i, start = 0;
1345
1346
6
    Stride /= PixelSize(info->InputFormat);
1347
1348
6
    if (ExtraFirst)
1349
0
        start = Extra;
1350
1351
18
    for (i = 0; i < nChan; i++) {
1352
1353
12
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1354
1355
12
        if (Planar)
1356
0
            v = (cmsFloat32Number)((cmsUInt16Number*)accum)[(i + start) * Stride];
1357
12
        else
1358
12
            v = (cmsFloat32Number)((cmsUInt16Number*)accum)[i + start];
1359
1360
12
        v /= 65535.0F;
1361
1362
12
        wIn[index] = Reverse ? 1 - v : v;
1363
12
    }
1364
1365
1366
6
    if (Extra == 0 && SwapFirst) {
1367
0
        cmsFloat32Number tmp = wIn[0];
1368
1369
0
        memmove(&wIn[0], &wIn[1], (nChan - 1) * sizeof(cmsFloat32Number));
1370
0
        wIn[nChan - 1] = tmp;
1371
0
    }
1372
1373
6
    if (T_PLANAR(info->InputFormat))
1374
0
        return accum + sizeof(cmsUInt16Number);
1375
6
    else
1376
6
        return accum + (nChan + Extra) * sizeof(cmsUInt16Number);
1377
6
}
1378
1379
1380
// For anything going from cmsFloat32Number
1381
static
1382
cmsUInt8Number* UnrollFloatsToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
1383
                                    cmsFloat32Number wIn[],
1384
                                    cmsUInt8Number* accum,
1385
                                    cmsUInt32Number Stride)
1386
0
{
1387
1388
0
    cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
1389
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
1390
0
    cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
1391
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
1392
0
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
1393
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1394
0
    cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
1395
0
    cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
1396
0
    cmsFloat32Number v;
1397
0
    cmsUInt32Number i, start = 0;
1398
0
    cmsFloat32Number maximum = IsInkSpace(info->InputFormat) ? 100.0F : 1.0F;
1399
0
    cmsFloat32Number alpha_factor = 1.0f;
1400
0
    cmsFloat32Number* ptr = (cmsFloat32Number*)accum;
1401
1402
0
    Stride /= PixelSize(info->InputFormat);
1403
1404
0
    if (Premul && Extra)
1405
0
    {
1406
0
        if (Planar)
1407
0
            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan * Stride]) / maximum;
1408
0
        else
1409
0
            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
1410
0
    }
1411
1412
0
    if (ExtraFirst)
1413
0
            start = Extra;
1414
1415
0
    for (i=0; i < nChan; i++) {
1416
1417
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1418
1419
0
        if (Planar)
1420
0
            v = ptr[(i + start) * Stride];
1421
0
        else
1422
0
            v = ptr[i + start];
1423
1424
0
        if (Premul && alpha_factor > 0)
1425
0
            v /= alpha_factor;
1426
1427
0
        v /= maximum;
1428
1429
0
        wIn[index] = Reverse ? 1 - v : v;
1430
0
    }
1431
1432
1433
0
    if (Extra == 0 && SwapFirst) {
1434
0
        cmsFloat32Number tmp = wIn[0];
1435
1436
0
        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));
1437
0
        wIn[nChan-1] = tmp;
1438
0
    }
1439
1440
0
    if (T_PLANAR(info -> InputFormat))
1441
0
        return accum + sizeof(cmsFloat32Number);
1442
0
    else
1443
0
        return accum + (nChan + Extra) * sizeof(cmsFloat32Number);
1444
0
}
1445
1446
// For anything going from double
1447
1448
static
1449
cmsUInt8Number* UnrollDoublesToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
1450
                                    cmsFloat32Number wIn[],
1451
                                    cmsUInt8Number* accum,
1452
                                    cmsUInt32Number Stride)
1453
0
{
1454
1455
0
    cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
1456
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
1457
0
    cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
1458
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
1459
0
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
1460
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1461
0
    cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
1462
0
    cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
1463
0
    cmsFloat64Number v;
1464
0
    cmsUInt32Number i, start = 0;
1465
0
    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0;
1466
0
    cmsFloat64Number alpha_factor = 1.0;
1467
0
    cmsFloat64Number* ptr = (cmsFloat64Number*)accum;
1468
1469
0
    Stride /= PixelSize(info->InputFormat);
1470
1471
0
    if (Premul && Extra)
1472
0
    {
1473
0
        if (Planar)
1474
0
            alpha_factor = (ExtraFirst ? ptr[0] : ptr[(nChan) * Stride]) / maximum;
1475
0
        else
1476
0
            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
1477
0
    }
1478
1479
0
    if (ExtraFirst)
1480
0
            start = Extra;
1481
1482
0
    for (i=0; i < nChan; i++) {
1483
1484
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1485
1486
0
        if (Planar)
1487
0
            v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[(i + start)  * Stride];
1488
0
        else
1489
0
            v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[i + start];
1490
1491
1492
0
        if (Premul && alpha_factor > 0)
1493
0
            v /= alpha_factor;
1494
1495
0
        v /= maximum;
1496
1497
0
        wIn[index] = (cmsFloat32Number) (Reverse ? 1.0 - v : v);
1498
0
    }
1499
1500
1501
0
    if (Extra == 0 && SwapFirst) {
1502
0
        cmsFloat32Number tmp = wIn[0];
1503
1504
0
        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));
1505
0
        wIn[nChan-1] = tmp;
1506
0
    }
1507
1508
0
    if (T_PLANAR(info -> InputFormat))
1509
0
        return accum + sizeof(cmsFloat64Number);
1510
0
    else
1511
0
        return accum + (nChan + Extra) * sizeof(cmsFloat64Number);
1512
0
}
1513
1514
1515
1516
// From Lab double to cmsFloat32Number
1517
static
1518
cmsUInt8Number* UnrollLabDoubleToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
1519
                                       cmsFloat32Number wIn[],
1520
                                       cmsUInt8Number* accum,
1521
                                       cmsUInt32Number Stride)
1522
0
{
1523
0
    cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
1524
1525
0
    if (T_PLANAR(info -> InputFormat)) {
1526
1527
0
        Stride /= PixelSize(info->InputFormat);
1528
1529
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);                 // from 0..100 to 0..1
1530
0
        wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0);    // form -128..+127 to 0..1
1531
0
        wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);
1532
1533
0
        return accum + sizeof(cmsFloat64Number);
1534
0
    }
1535
0
    else {
1536
1537
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);            // from 0..100 to 0..1
1538
0
        wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0);    // form -128..+127 to 0..1
1539
0
        wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);
1540
1541
0
        accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat));
1542
0
        return accum;
1543
0
    }
1544
0
}
1545
1546
// From Lab double to cmsFloat32Number
1547
static
1548
cmsUInt8Number* UnrollLabFloatToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
1549
                                      cmsFloat32Number wIn[],
1550
                                      cmsUInt8Number* accum,
1551
                                      cmsUInt32Number Stride)
1552
0
{
1553
0
    cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
1554
1555
0
    if (T_PLANAR(info -> InputFormat)) {
1556
1557
0
        Stride /= PixelSize(info->InputFormat);
1558
1559
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);                 // from 0..100 to 0..1
1560
0
        wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0);    // form -128..+127 to 0..1
1561
0
        wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);
1562
1563
0
        return accum + sizeof(cmsFloat32Number);
1564
0
    }
1565
0
    else {
1566
1567
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);            // from 0..100 to 0..1
1568
0
        wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0);    // form -128..+127 to 0..1
1569
0
        wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);
1570
1571
0
        accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat));
1572
0
        return accum;
1573
0
    }
1574
0
}
1575
1576
// 1.15 fixed point, that means maximum value is MAX_ENCODEABLE_XYZ (0xFFFF)
1577
static
1578
cmsUInt8Number* UnrollXYZDoubleToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
1579
                                       cmsFloat32Number wIn[],
1580
                                       cmsUInt8Number* accum,
1581
                                       cmsUInt32Number Stride)
1582
0
{
1583
0
    cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
1584
1585
0
    if (T_PLANAR(info -> InputFormat)) {
1586
1587
0
        Stride /= PixelSize(info->InputFormat);
1588
1589
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
1590
0
        wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);
1591
0
        wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);
1592
1593
0
        return accum + sizeof(cmsFloat64Number);
1594
0
    }
1595
0
    else {
1596
1597
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
1598
0
        wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);
1599
0
        wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);
1600
1601
0
        accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat));
1602
0
        return accum;
1603
0
    }
1604
0
}
1605
1606
static
1607
cmsUInt8Number* UnrollXYZFloatToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
1608
                                      cmsFloat32Number wIn[],
1609
                                      cmsUInt8Number* accum,
1610
                                      cmsUInt32Number Stride)
1611
0
{
1612
0
    cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
1613
1614
0
    if (T_PLANAR(info -> InputFormat)) {
1615
1616
0
        Stride /= PixelSize(info->InputFormat);
1617
1618
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
1619
0
        wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);
1620
0
        wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);
1621
1622
0
        return accum + sizeof(cmsFloat32Number);
1623
0
    }
1624
0
    else {
1625
1626
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
1627
0
        wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);
1628
0
        wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);
1629
1630
0
        accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat));
1631
0
        return accum;
1632
0
    }
1633
0
}
1634
1635
1636
cmsINLINE void lab4toFloat(cmsFloat32Number wIn[], cmsUInt16Number lab4[3])
1637
0
{
1638
0
    cmsFloat32Number L = (cmsFloat32Number) lab4[0] / 655.35F;
1639
0
    cmsFloat32Number a = ((cmsFloat32Number) lab4[1] / 257.0F) - 128.0F;
1640
0
    cmsFloat32Number b = ((cmsFloat32Number) lab4[2] / 257.0F) - 128.0F;
1641
1642
0
    wIn[0] = (L / 100.0F);                    // from 0..100 to 0..1
1643
0
    wIn[1] = ((a + 128.0F) / 255.0F);         // form -128..+127 to 0..1
1644
0
    wIn[2] = ((b + 128.0F) / 255.0F);
1645
1646
0
}
1647
1648
static
1649
cmsUInt8Number* UnrollLabV2_8ToFloat(cmsContext ContextID,
1650
                                      _cmsTRANSFORM* info,
1651
                                      cmsFloat32Number wIn[],
1652
                                      cmsUInt8Number* accum,
1653
                                      cmsUInt32Number Stride)
1654
0
{
1655
0
    cmsUInt16Number lab4[3];
1656
1657
0
    lab4[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // L
1658
0
    lab4[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // a
1659
0
    lab4[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // b
1660
1661
0
    lab4toFloat(wIn, lab4);
1662
1663
0
    return accum;
1664
1665
0
    cmsUNUSED_PARAMETER(info);
1666
0
    cmsUNUSED_PARAMETER(Stride);
1667
0
}
1668
1669
static
1670
cmsUInt8Number* UnrollALabV2_8ToFloat(cmsContext ContextID,
1671
                                      _cmsTRANSFORM* info,
1672
                                      cmsFloat32Number wIn[],
1673
                                      cmsUInt8Number* accum,
1674
                                      cmsUInt32Number Stride)
1675
0
{
1676
0
    cmsUInt16Number lab4[3];
1677
1678
0
    accum++;  // A
1679
0
    lab4[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // L
1680
0
    lab4[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // a
1681
0
    lab4[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // b
1682
1683
0
    lab4toFloat(wIn, lab4);
1684
1685
0
    return accum;
1686
1687
0
    cmsUNUSED_PARAMETER(info);
1688
0
    cmsUNUSED_PARAMETER(Stride);
1689
0
}
1690
1691
static
1692
cmsUInt8Number* UnrollLabV2_16ToFloat(cmsContext ContextID,
1693
                                      _cmsTRANSFORM* info,
1694
                                      cmsFloat32Number wIn[],
1695
                                      cmsUInt8Number* accum,
1696
                                      cmsUInt32Number Stride)
1697
0
{
1698
0
    cmsUInt16Number lab4[3];
1699
1700
0
    lab4[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // L
1701
0
    lab4[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // a
1702
0
    lab4[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // b
1703
1704
0
    lab4toFloat(wIn, lab4);
1705
1706
0
    return accum;
1707
1708
0
    cmsUNUSED_PARAMETER(info);
1709
0
    cmsUNUSED_PARAMETER(Stride);
1710
0
}
1711
1712
1713
// Packing routines -----------------------------------------------------------------------------------------------------------
1714
1715
1716
// Generic chunky for byte
1717
static
1718
cmsUInt8Number* PackChunkyBytes(cmsContext ContextID,
1719
                                CMSREGISTER _cmsTRANSFORM* info,
1720
                                CMSREGISTER cmsUInt16Number wOut[],
1721
                                CMSREGISTER cmsUInt8Number* output,
1722
                                CMSREGISTER cmsUInt32Number Stride)
1723
0
{
1724
0
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
1725
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
1726
0
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
1727
0
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
1728
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
1729
0
    cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
1730
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1731
0
    cmsUInt8Number* swap1;
1732
0
    cmsUInt16Number v = 0;
1733
0
    cmsUInt32Number i;
1734
0
    cmsUInt32Number alpha_factor = 0;
1735
1736
0
    swap1 = output;
1737
1738
0
    if (ExtraFirst) {
1739
1740
0
        if (Premul && Extra)
1741
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[0]));
1742
1743
0
        output += Extra;
1744
0
    }
1745
0
    else
1746
0
    {
1747
0
        if (Premul && Extra)
1748
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[nChan]));
1749
0
    }
1750
1751
0
    for (i=0; i < nChan; i++) {
1752
1753
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1754
1755
0
        v = wOut[index];
1756
1757
0
        if (Reverse)
1758
0
            v = REVERSE_FLAVOR_16(v);
1759
1760
0
        if (Premul)
1761
0
        {
1762
0
            v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
1763
0
        }
1764
1765
0
        *output++ = FROM_16_TO_8(v);
1766
0
    }
1767
1768
0
    if (!ExtraFirst) {
1769
0
        output += Extra;
1770
0
    }
1771
1772
0
    if (Extra == 0 && SwapFirst) {
1773
1774
0
        memmove(swap1 + 1, swap1, nChan-1);
1775
0
        *swap1 = FROM_16_TO_8(v);
1776
0
    }
1777
1778
0
    return output;
1779
1780
0
    cmsUNUSED_PARAMETER(Stride);
1781
0
}
1782
1783
static
1784
cmsUInt8Number* PackChunkyWords(cmsContext ContextID,
1785
                                CMSREGISTER _cmsTRANSFORM* info,
1786
                                CMSREGISTER cmsUInt16Number wOut[],
1787
                                CMSREGISTER cmsUInt8Number* output,
1788
                                CMSREGISTER cmsUInt32Number Stride)
1789
0
{
1790
0
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
1791
0
    cmsUInt32Number SwapEndian = T_ENDIAN16(info->OutputFormat);
1792
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
1793
0
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
1794
0
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
1795
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
1796
0
    cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
1797
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1798
0
    cmsUInt16Number* swap1;
1799
0
    cmsUInt16Number v = 0;
1800
0
    cmsUInt32Number i;
1801
0
    cmsUInt32Number alpha_factor = 0;
1802
1803
0
    swap1 = (cmsUInt16Number*) output;
1804
1805
0
    if (ExtraFirst) {
1806
1807
0
        if (Premul && Extra)
1808
0
            alpha_factor = _cmsToFixedDomain(*(cmsUInt16Number*) output);
1809
1810
0
        output += Extra * sizeof(cmsUInt16Number);
1811
0
    }
1812
0
    else
1813
0
    {
1814
0
        if (Premul && Extra)
1815
0
            alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*) output)[nChan]);
1816
0
    }
1817
1818
0
    for (i=0; i < nChan; i++) {
1819
1820
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1821
1822
0
        v = wOut[index];
1823
1824
0
        if (SwapEndian)
1825
0
            v = CHANGE_ENDIAN(v);
1826
1827
0
        if (Reverse)
1828
0
            v = REVERSE_FLAVOR_16(v);
1829
1830
0
        if (Premul)
1831
0
        {
1832
0
            v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
1833
0
        }
1834
1835
0
        *(cmsUInt16Number*) output = v;
1836
1837
0
        output += sizeof(cmsUInt16Number);
1838
0
    }
1839
1840
0
    if (!ExtraFirst) {
1841
0
        output += Extra * sizeof(cmsUInt16Number);
1842
0
    }
1843
1844
0
    if (Extra == 0 && SwapFirst) {
1845
1846
0
        memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number));
1847
0
        *swap1 = v;
1848
0
    }
1849
1850
0
    return output;
1851
1852
0
    cmsUNUSED_PARAMETER(Stride);
1853
0
}
1854
1855
1856
1857
static
1858
cmsUInt8Number* PackPlanarBytes(cmsContext ContextID,
1859
                                CMSREGISTER _cmsTRANSFORM* info,
1860
                                CMSREGISTER cmsUInt16Number wOut[],
1861
                                CMSREGISTER cmsUInt8Number* output,
1862
                                CMSREGISTER cmsUInt32Number Stride)
1863
0
{
1864
0
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
1865
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
1866
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
1867
0
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
1868
0
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
1869
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1870
0
    cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
1871
0
    cmsUInt32Number i;
1872
0
    cmsUInt8Number* Init = output;
1873
0
    cmsUInt32Number alpha_factor = 0;
1874
1875
1876
0
    if (ExtraFirst) {
1877
1878
0
        if (Premul && Extra)
1879
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[0]));
1880
1881
0
        output += Extra * Stride;
1882
0
    }
1883
0
    else
1884
0
    {
1885
0
        if (Premul && Extra)
1886
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[nChan * Stride]));
1887
0
    }
1888
1889
1890
0
    for (i=0; i < nChan; i++) {
1891
1892
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1893
0
        cmsUInt16Number v = wOut[index];
1894
1895
0
        if (Reverse)
1896
0
            v = REVERSE_FLAVOR_16(v);
1897
1898
0
        if (Premul)
1899
0
        {
1900
0
            v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
1901
0
        }
1902
1903
0
        *(cmsUInt8Number*)output = FROM_16_TO_8(v);
1904
1905
0
        output += Stride;
1906
0
    }
1907
1908
0
    return (Init + 1);
1909
1910
0
    cmsUNUSED_PARAMETER(Stride);
1911
0
}
1912
1913
1914
static
1915
cmsUInt8Number* PackPlanarWords(cmsContext ContextID,
1916
                                CMSREGISTER _cmsTRANSFORM* info,
1917
                                CMSREGISTER cmsUInt16Number wOut[],
1918
                                CMSREGISTER cmsUInt8Number* output,
1919
                                CMSREGISTER cmsUInt32Number Stride)
1920
0
{
1921
0
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
1922
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
1923
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
1924
0
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
1925
0
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
1926
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1927
0
    cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
1928
0
    cmsUInt32Number SwapEndian = T_ENDIAN16(info->OutputFormat);
1929
0
    cmsUInt32Number i;
1930
0
    cmsUInt8Number* Init = output;
1931
0
    cmsUInt16Number v;
1932
0
    cmsUInt32Number alpha_factor = 0;
1933
1934
0
    if (ExtraFirst) {
1935
1936
0
        if (Premul && Extra)
1937
0
            alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*) output)[0]);
1938
1939
0
        output += Extra * Stride;
1940
0
    }
1941
0
    else
1942
0
    {
1943
0
        if (Premul && Extra)
1944
0
            alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*)output)[nChan * Stride]);
1945
0
    }
1946
1947
0
    for (i=0; i < nChan; i++) {
1948
1949
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1950
1951
0
        v = wOut[index];
1952
1953
0
        if (SwapEndian)
1954
0
            v = CHANGE_ENDIAN(v);
1955
1956
0
        if (Reverse)
1957
0
            v =  REVERSE_FLAVOR_16(v);
1958
1959
0
        if (Premul)
1960
0
        {
1961
0
            v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
1962
0
        }
1963
1964
0
        *(cmsUInt16Number*) output = v;
1965
0
        output += Stride;
1966
0
    }
1967
1968
0
    return (Init + sizeof(cmsUInt16Number));
1969
0
}
1970
1971
// CMYKcm (unrolled for speed)
1972
1973
static
1974
cmsUInt8Number* Pack6Bytes(cmsContext ContextID,
1975
                           CMSREGISTER _cmsTRANSFORM* info,
1976
                           CMSREGISTER cmsUInt16Number wOut[],
1977
                           CMSREGISTER cmsUInt8Number* output,
1978
                           CMSREGISTER cmsUInt32Number Stride)
1979
0
{
1980
0
    *output++ = FROM_16_TO_8(wOut[0]);
1981
0
    *output++ = FROM_16_TO_8(wOut[1]);
1982
0
    *output++ = FROM_16_TO_8(wOut[2]);
1983
0
    *output++ = FROM_16_TO_8(wOut[3]);
1984
0
    *output++ = FROM_16_TO_8(wOut[4]);
1985
0
    *output++ = FROM_16_TO_8(wOut[5]);
1986
1987
0
    return output;
1988
1989
0
    cmsUNUSED_PARAMETER(info);
1990
0
    cmsUNUSED_PARAMETER(Stride);
1991
0
}
1992
1993
// KCMYcm
1994
1995
static
1996
cmsUInt8Number* Pack6BytesSwap(cmsContext ContextID,
1997
                               CMSREGISTER _cmsTRANSFORM* info,
1998
                               CMSREGISTER cmsUInt16Number wOut[],
1999
                               CMSREGISTER cmsUInt8Number* output,
2000
                               CMSREGISTER cmsUInt32Number Stride)
2001
0
{
2002
0
    *output++ = FROM_16_TO_8(wOut[5]);
2003
0
    *output++ = FROM_16_TO_8(wOut[4]);
2004
0
    *output++ = FROM_16_TO_8(wOut[3]);
2005
0
    *output++ = FROM_16_TO_8(wOut[2]);
2006
0
    *output++ = FROM_16_TO_8(wOut[1]);
2007
0
    *output++ = FROM_16_TO_8(wOut[0]);
2008
2009
0
    return output;
2010
2011
0
    cmsUNUSED_PARAMETER(info);
2012
0
    cmsUNUSED_PARAMETER(Stride);
2013
0
}
2014
2015
// CMYKcm
2016
static
2017
cmsUInt8Number* Pack6Words(cmsContext ContextID,
2018
                           CMSREGISTER _cmsTRANSFORM* info,
2019
                           CMSREGISTER cmsUInt16Number wOut[],
2020
                           CMSREGISTER cmsUInt8Number* output,
2021
                           CMSREGISTER cmsUInt32Number Stride)
2022
0
{
2023
0
    *(cmsUInt16Number*) output = wOut[0];
2024
0
    output+= 2;
2025
0
    *(cmsUInt16Number*) output = wOut[1];
2026
0
    output+= 2;
2027
0
    *(cmsUInt16Number*) output = wOut[2];
2028
0
    output+= 2;
2029
0
    *(cmsUInt16Number*) output = wOut[3];
2030
0
    output+= 2;
2031
0
    *(cmsUInt16Number*) output = wOut[4];
2032
0
    output+= 2;
2033
0
    *(cmsUInt16Number*) output = wOut[5];
2034
0
    output+= 2;
2035
2036
0
    return output;
2037
2038
0
    cmsUNUSED_PARAMETER(info);
2039
0
    cmsUNUSED_PARAMETER(Stride);
2040
0
}
2041
2042
// KCMYcm
2043
static
2044
cmsUInt8Number* Pack6WordsSwap(cmsContext ContextID,
2045
                               CMSREGISTER _cmsTRANSFORM* info,
2046
                               CMSREGISTER cmsUInt16Number wOut[],
2047
                               CMSREGISTER cmsUInt8Number* output,
2048
                               CMSREGISTER cmsUInt32Number Stride)
2049
0
{
2050
0
    *(cmsUInt16Number*) output = wOut[5];
2051
0
    output+= 2;
2052
0
    *(cmsUInt16Number*) output = wOut[4];
2053
0
    output+= 2;
2054
0
    *(cmsUInt16Number*) output = wOut[3];
2055
0
    output+= 2;
2056
0
    *(cmsUInt16Number*) output = wOut[2];
2057
0
    output+= 2;
2058
0
    *(cmsUInt16Number*) output = wOut[1];
2059
0
    output+= 2;
2060
0
    *(cmsUInt16Number*) output = wOut[0];
2061
0
    output+= 2;
2062
2063
0
    return output;
2064
2065
0
    cmsUNUSED_PARAMETER(info);
2066
0
    cmsUNUSED_PARAMETER(Stride);
2067
0
}
2068
2069
2070
static
2071
cmsUInt8Number* Pack4Bytes(cmsContext ContextID,
2072
                           CMSREGISTER _cmsTRANSFORM* info,
2073
                           CMSREGISTER cmsUInt16Number wOut[],
2074
                           CMSREGISTER cmsUInt8Number* output,
2075
                           CMSREGISTER cmsUInt32Number Stride)
2076
0
{
2077
0
    *output++ = FROM_16_TO_8(wOut[0]);
2078
0
    *output++ = FROM_16_TO_8(wOut[1]);
2079
0
    *output++ = FROM_16_TO_8(wOut[2]);
2080
0
    *output++ = FROM_16_TO_8(wOut[3]);
2081
2082
0
    return output;
2083
2084
0
    cmsUNUSED_PARAMETER(info);
2085
0
    cmsUNUSED_PARAMETER(Stride);
2086
0
}
2087
2088
static
2089
cmsUInt8Number* Pack4BytesReverse(cmsContext ContextID,
2090
                                  CMSREGISTER _cmsTRANSFORM* info,
2091
                                  CMSREGISTER cmsUInt16Number wOut[],
2092
                                  CMSREGISTER cmsUInt8Number* output,
2093
                                  CMSREGISTER cmsUInt32Number Stride)
2094
0
{
2095
0
    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[0]));
2096
0
    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[1]));
2097
0
    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[2]));
2098
0
    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[3]));
2099
2100
0
    return output;
2101
2102
0
    cmsUNUSED_PARAMETER(info);
2103
0
    cmsUNUSED_PARAMETER(Stride);
2104
0
}
2105
2106
2107
static
2108
cmsUInt8Number* Pack4BytesSwapFirst(cmsContext ContextID,
2109
                                    CMSREGISTER _cmsTRANSFORM* info,
2110
                                    CMSREGISTER cmsUInt16Number wOut[],
2111
                                    CMSREGISTER cmsUInt8Number* output,
2112
                                    CMSREGISTER cmsUInt32Number Stride)
2113
0
{
2114
0
    *output++ = FROM_16_TO_8(wOut[3]);
2115
0
    *output++ = FROM_16_TO_8(wOut[0]);
2116
0
    *output++ = FROM_16_TO_8(wOut[1]);
2117
0
    *output++ = FROM_16_TO_8(wOut[2]);
2118
2119
0
    return output;
2120
2121
0
    cmsUNUSED_PARAMETER(info);
2122
0
    cmsUNUSED_PARAMETER(Stride);
2123
0
}
2124
2125
// ABGR
2126
static
2127
cmsUInt8Number* Pack4BytesSwap(cmsContext ContextID,
2128
                               CMSREGISTER _cmsTRANSFORM* info,
2129
                               CMSREGISTER cmsUInt16Number wOut[],
2130
                               CMSREGISTER cmsUInt8Number* output,
2131
                               CMSREGISTER cmsUInt32Number Stride)
2132
0
{
2133
0
    *output++ = FROM_16_TO_8(wOut[3]);
2134
0
    *output++ = FROM_16_TO_8(wOut[2]);
2135
0
    *output++ = FROM_16_TO_8(wOut[1]);
2136
0
    *output++ = FROM_16_TO_8(wOut[0]);
2137
2138
0
    return output;
2139
2140
0
    cmsUNUSED_PARAMETER(info);
2141
0
    cmsUNUSED_PARAMETER(Stride);
2142
0
}
2143
2144
static
2145
cmsUInt8Number* Pack4BytesSwapSwapFirst(cmsContext ContextID,
2146
                                        CMSREGISTER _cmsTRANSFORM* info,
2147
                                        CMSREGISTER cmsUInt16Number wOut[],
2148
                                        CMSREGISTER cmsUInt8Number* output,
2149
                                        CMSREGISTER cmsUInt32Number Stride)
2150
0
{
2151
0
    *output++ = FROM_16_TO_8(wOut[2]);
2152
0
    *output++ = FROM_16_TO_8(wOut[1]);
2153
0
    *output++ = FROM_16_TO_8(wOut[0]);
2154
0
    *output++ = FROM_16_TO_8(wOut[3]);
2155
2156
0
    return output;
2157
2158
0
    cmsUNUSED_PARAMETER(info);
2159
0
    cmsUNUSED_PARAMETER(Stride);
2160
0
}
2161
2162
static
2163
cmsUInt8Number* Pack4Words(cmsContext ContextID,
2164
                           CMSREGISTER _cmsTRANSFORM* info,
2165
                           CMSREGISTER cmsUInt16Number wOut[],
2166
                           CMSREGISTER cmsUInt8Number* output,
2167
                           CMSREGISTER cmsUInt32Number Stride)
2168
0
{
2169
0
    *(cmsUInt16Number*) output = wOut[0];
2170
0
    output+= 2;
2171
0
    *(cmsUInt16Number*) output = wOut[1];
2172
0
    output+= 2;
2173
0
    *(cmsUInt16Number*) output = wOut[2];
2174
0
    output+= 2;
2175
0
    *(cmsUInt16Number*) output = wOut[3];
2176
0
    output+= 2;
2177
2178
0
    return output;
2179
2180
0
    cmsUNUSED_PARAMETER(info);
2181
0
    cmsUNUSED_PARAMETER(Stride);
2182
0
}
2183
2184
static
2185
cmsUInt8Number* Pack4WordsReverse(cmsContext ContextID,
2186
                                  CMSREGISTER _cmsTRANSFORM* info,
2187
                                  CMSREGISTER cmsUInt16Number wOut[],
2188
                                  CMSREGISTER cmsUInt8Number* output,
2189
                                  CMSREGISTER cmsUInt32Number Stride)
2190
0
{
2191
0
    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]);
2192
0
    output+= 2;
2193
0
    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[1]);
2194
0
    output+= 2;
2195
0
    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[2]);
2196
0
    output+= 2;
2197
0
    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[3]);
2198
0
    output+= 2;
2199
2200
0
    return output;
2201
2202
0
    cmsUNUSED_PARAMETER(info);
2203
0
    cmsUNUSED_PARAMETER(Stride);
2204
0
}
2205
2206
// ABGR
2207
static
2208
cmsUInt8Number* Pack4WordsSwap(cmsContext ContextID,
2209
                               CMSREGISTER _cmsTRANSFORM* info,
2210
                               CMSREGISTER cmsUInt16Number wOut[],
2211
                               CMSREGISTER cmsUInt8Number* output,
2212
                               CMSREGISTER cmsUInt32Number Stride)
2213
0
{
2214
0
    *(cmsUInt16Number*) output = wOut[3];
2215
0
    output+= 2;
2216
0
    *(cmsUInt16Number*) output = wOut[2];
2217
0
    output+= 2;
2218
0
    *(cmsUInt16Number*) output = wOut[1];
2219
0
    output+= 2;
2220
0
    *(cmsUInt16Number*) output = wOut[0];
2221
0
    output+= 2;
2222
2223
0
    return output;
2224
2225
0
    cmsUNUSED_PARAMETER(info);
2226
0
    cmsUNUSED_PARAMETER(Stride);
2227
0
}
2228
2229
// CMYK
2230
static
2231
cmsUInt8Number* Pack4WordsBigEndian(cmsContext ContextID,
2232
                                    CMSREGISTER _cmsTRANSFORM* info,
2233
                                    CMSREGISTER cmsUInt16Number wOut[],
2234
                                    CMSREGISTER cmsUInt8Number* output,
2235
                                    CMSREGISTER cmsUInt32Number Stride)
2236
0
{
2237
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
2238
0
    output+= 2;
2239
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]);
2240
0
    output+= 2;
2241
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]);
2242
0
    output+= 2;
2243
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[3]);
2244
0
    output+= 2;
2245
2246
0
    return output;
2247
2248
0
    cmsUNUSED_PARAMETER(info);
2249
0
    cmsUNUSED_PARAMETER(Stride);
2250
0
}
2251
2252
2253
static
2254
cmsUInt8Number* PackLabV2_8(cmsContext ContextID,
2255
                            CMSREGISTER _cmsTRANSFORM* info,
2256
                            CMSREGISTER cmsUInt16Number wOut[],
2257
                            CMSREGISTER cmsUInt8Number* output,
2258
                            CMSREGISTER cmsUInt32Number Stride)
2259
0
{
2260
0
    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0]));
2261
0
    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1]));
2262
0
    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2]));
2263
2264
0
    return output;
2265
2266
0
    cmsUNUSED_PARAMETER(info);
2267
0
    cmsUNUSED_PARAMETER(Stride);
2268
0
}
2269
2270
static
2271
cmsUInt8Number* PackALabV2_8(cmsContext ContextID,
2272
                             CMSREGISTER _cmsTRANSFORM* info,
2273
                             CMSREGISTER cmsUInt16Number wOut[],
2274
                             CMSREGISTER cmsUInt8Number* output,
2275
                             CMSREGISTER cmsUInt32Number Stride)
2276
0
{
2277
0
    output++;
2278
0
    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0]));
2279
0
    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1]));
2280
0
    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2]));
2281
2282
0
    return output;
2283
2284
0
    cmsUNUSED_PARAMETER(info);
2285
0
    cmsUNUSED_PARAMETER(Stride);
2286
0
}
2287
2288
static
2289
cmsUInt8Number* PackLabV2_16(cmsContext ContextID,
2290
                             CMSREGISTER _cmsTRANSFORM* info,
2291
                             CMSREGISTER cmsUInt16Number wOut[],
2292
                             CMSREGISTER cmsUInt8Number* output,
2293
                             CMSREGISTER cmsUInt32Number Stride)
2294
0
{
2295
0
    *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[0]);
2296
0
    output += 2;
2297
0
    *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[1]);
2298
0
    output += 2;
2299
0
    *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[2]);
2300
0
    output += 2;
2301
2302
0
    return output;
2303
2304
0
    cmsUNUSED_PARAMETER(info);
2305
0
    cmsUNUSED_PARAMETER(Stride);
2306
0
}
2307
2308
static
2309
cmsUInt8Number* Pack3Bytes(cmsContext ContextID,
2310
                           CMSREGISTER _cmsTRANSFORM* info,
2311
                           CMSREGISTER cmsUInt16Number wOut[],
2312
                           CMSREGISTER cmsUInt8Number* output,
2313
                           CMSREGISTER cmsUInt32Number Stride)
2314
0
{
2315
0
    *output++ = FROM_16_TO_8(wOut[0]);
2316
0
    *output++ = FROM_16_TO_8(wOut[1]);
2317
0
    *output++ = FROM_16_TO_8(wOut[2]);
2318
2319
0
    return output;
2320
2321
0
    cmsUNUSED_PARAMETER(info);
2322
0
    cmsUNUSED_PARAMETER(Stride);
2323
0
}
2324
2325
static
2326
cmsUInt8Number* Pack3BytesOptimized(cmsContext ContextID,
2327
                                    CMSREGISTER _cmsTRANSFORM* info,
2328
                                    CMSREGISTER cmsUInt16Number wOut[],
2329
                                    CMSREGISTER cmsUInt8Number* output,
2330
                                    CMSREGISTER cmsUInt32Number Stride)
2331
0
{
2332
0
    *output++ = (wOut[0] & 0xFFU);
2333
0
    *output++ = (wOut[1] & 0xFFU);
2334
0
    *output++ = (wOut[2] & 0xFFU);
2335
2336
0
    return output;
2337
2338
0
    cmsUNUSED_PARAMETER(info);
2339
0
    cmsUNUSED_PARAMETER(Stride);
2340
0
}
2341
2342
static
2343
cmsUInt8Number* Pack3BytesSwap(cmsContext ContextID,
2344
                               CMSREGISTER _cmsTRANSFORM* info,
2345
                               CMSREGISTER cmsUInt16Number wOut[],
2346
                               CMSREGISTER cmsUInt8Number* output,
2347
                               CMSREGISTER cmsUInt32Number Stride)
2348
0
{
2349
0
    *output++ = FROM_16_TO_8(wOut[2]);
2350
0
    *output++ = FROM_16_TO_8(wOut[1]);
2351
0
    *output++ = FROM_16_TO_8(wOut[0]);
2352
2353
0
    return output;
2354
2355
0
    cmsUNUSED_PARAMETER(info);
2356
0
    cmsUNUSED_PARAMETER(Stride);
2357
0
}
2358
2359
static
2360
cmsUInt8Number* Pack3BytesSwapOptimized(cmsContext ContextID,
2361
                                        CMSREGISTER _cmsTRANSFORM* info,
2362
                                        CMSREGISTER cmsUInt16Number wOut[],
2363
                                        CMSREGISTER cmsUInt8Number* output,
2364
                                        CMSREGISTER cmsUInt32Number Stride)
2365
0
{
2366
0
    *output++ = (wOut[2] & 0xFFU);
2367
0
    *output++ = (wOut[1] & 0xFFU);
2368
0
    *output++ = (wOut[0] & 0xFFU);
2369
2370
0
    return output;
2371
2372
0
    cmsUNUSED_PARAMETER(info);
2373
0
    cmsUNUSED_PARAMETER(Stride);
2374
0
}
2375
2376
2377
static
2378
cmsUInt8Number* Pack3Words(cmsContext ContextID,
2379
                           CMSREGISTER _cmsTRANSFORM* info,
2380
                           CMSREGISTER cmsUInt16Number wOut[],
2381
                           CMSREGISTER cmsUInt8Number* output,
2382
                           CMSREGISTER cmsUInt32Number Stride)
2383
0
{
2384
0
    *(cmsUInt16Number*) output = wOut[0];
2385
0
    output+= 2;
2386
0
    *(cmsUInt16Number*) output = wOut[1];
2387
0
    output+= 2;
2388
0
    *(cmsUInt16Number*) output = wOut[2];
2389
0
    output+= 2;
2390
2391
0
    return output;
2392
2393
0
    cmsUNUSED_PARAMETER(info);
2394
0
    cmsUNUSED_PARAMETER(Stride);
2395
0
}
2396
2397
static
2398
cmsUInt8Number* Pack3WordsSwap(cmsContext ContextID,
2399
                               CMSREGISTER _cmsTRANSFORM* info,
2400
                               CMSREGISTER cmsUInt16Number wOut[],
2401
                               CMSREGISTER cmsUInt8Number* output,
2402
                               CMSREGISTER cmsUInt32Number Stride)
2403
0
{
2404
0
    *(cmsUInt16Number*) output = wOut[2];
2405
0
    output+= 2;
2406
0
    *(cmsUInt16Number*) output = wOut[1];
2407
0
    output+= 2;
2408
0
    *(cmsUInt16Number*) output = wOut[0];
2409
0
    output+= 2;
2410
2411
0
    return output;
2412
2413
0
    cmsUNUSED_PARAMETER(info);
2414
0
    cmsUNUSED_PARAMETER(Stride);
2415
0
}
2416
2417
static
2418
cmsUInt8Number* Pack3WordsBigEndian(cmsContext ContextID,
2419
                                    CMSREGISTER _cmsTRANSFORM* info,
2420
                                    CMSREGISTER cmsUInt16Number wOut[],
2421
                                    CMSREGISTER cmsUInt8Number* output,
2422
                                    CMSREGISTER cmsUInt32Number Stride)
2423
0
{
2424
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
2425
0
    output+= 2;
2426
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]);
2427
0
    output+= 2;
2428
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]);
2429
0
    output+= 2;
2430
2431
0
    return output;
2432
2433
0
    cmsUNUSED_PARAMETER(info);
2434
0
    cmsUNUSED_PARAMETER(Stride);
2435
0
}
2436
2437
static
2438
cmsUInt8Number* Pack3BytesAndSkip1(cmsContext ContextID,
2439
                                   CMSREGISTER _cmsTRANSFORM* info,
2440
                                   CMSREGISTER cmsUInt16Number wOut[],
2441
                                   CMSREGISTER cmsUInt8Number* output,
2442
                                   CMSREGISTER cmsUInt32Number Stride)
2443
0
{
2444
0
    *output++ = FROM_16_TO_8(wOut[0]);
2445
0
    *output++ = FROM_16_TO_8(wOut[1]);
2446
0
    *output++ = FROM_16_TO_8(wOut[2]);
2447
0
    output++;
2448
2449
0
    return output;
2450
2451
0
    cmsUNUSED_PARAMETER(info);
2452
0
    cmsUNUSED_PARAMETER(Stride);
2453
0
}
2454
2455
static
2456
cmsUInt8Number* Pack3BytesAndSkip1Optimized(cmsContext ContextID,
2457
                                            CMSREGISTER _cmsTRANSFORM* info,
2458
                                            CMSREGISTER cmsUInt16Number wOut[],
2459
                                            CMSREGISTER cmsUInt8Number* output,
2460
                                            CMSREGISTER cmsUInt32Number Stride)
2461
0
{
2462
0
    *output++ = (wOut[0] & 0xFFU);
2463
0
    *output++ = (wOut[1] & 0xFFU);
2464
0
    *output++ = (wOut[2] & 0xFFU);
2465
0
    output++;
2466
2467
0
    return output;
2468
2469
0
    cmsUNUSED_PARAMETER(info);
2470
0
    cmsUNUSED_PARAMETER(Stride);
2471
0
}
2472
2473
2474
static
2475
cmsUInt8Number* Pack3BytesAndSkip1SwapFirst(cmsContext ContextID,
2476
                                            CMSREGISTER _cmsTRANSFORM* info,
2477
                                            CMSREGISTER cmsUInt16Number wOut[],
2478
                                            CMSREGISTER cmsUInt8Number* output,
2479
                                            CMSREGISTER cmsUInt32Number Stride)
2480
0
{
2481
0
    output++;
2482
0
    *output++ = FROM_16_TO_8(wOut[0]);
2483
0
    *output++ = FROM_16_TO_8(wOut[1]);
2484
0
    *output++ = FROM_16_TO_8(wOut[2]);
2485
2486
0
    return output;
2487
2488
0
    cmsUNUSED_PARAMETER(info);
2489
0
    cmsUNUSED_PARAMETER(Stride);
2490
0
}
2491
2492
static
2493
cmsUInt8Number* Pack3BytesAndSkip1SwapFirstOptimized(cmsContext ContextID,
2494
                                                     CMSREGISTER _cmsTRANSFORM* info,
2495
                                                     CMSREGISTER cmsUInt16Number wOut[],
2496
                                                     CMSREGISTER cmsUInt8Number* output,
2497
                                                     CMSREGISTER cmsUInt32Number Stride)
2498
0
{
2499
0
    output++;
2500
0
    *output++ = (wOut[0] & 0xFFU);
2501
0
    *output++ = (wOut[1] & 0xFFU);
2502
0
    *output++ = (wOut[2] & 0xFFU);
2503
2504
0
    return output;
2505
2506
0
    cmsUNUSED_PARAMETER(info);
2507
0
    cmsUNUSED_PARAMETER(Stride);
2508
0
}
2509
2510
static
2511
cmsUInt8Number* Pack3BytesAndSkip1Swap(cmsContext ContextID,
2512
                                       CMSREGISTER _cmsTRANSFORM* info,
2513
                                       CMSREGISTER cmsUInt16Number wOut[],
2514
                                       CMSREGISTER cmsUInt8Number* output,
2515
                                       CMSREGISTER cmsUInt32Number Stride)
2516
0
{
2517
0
    output++;
2518
0
    *output++ = FROM_16_TO_8(wOut[2]);
2519
0
    *output++ = FROM_16_TO_8(wOut[1]);
2520
0
    *output++ = FROM_16_TO_8(wOut[0]);
2521
2522
0
    return output;
2523
2524
0
    cmsUNUSED_PARAMETER(info);
2525
0
    cmsUNUSED_PARAMETER(Stride);
2526
0
}
2527
2528
static
2529
cmsUInt8Number* Pack3BytesAndSkip1SwapOptimized(cmsContext ContextID,
2530
                                                CMSREGISTER _cmsTRANSFORM* info,
2531
                                                CMSREGISTER cmsUInt16Number wOut[],
2532
                                                CMSREGISTER cmsUInt8Number* output,
2533
                                                CMSREGISTER cmsUInt32Number Stride)
2534
0
{
2535
0
    output++;
2536
0
    *output++ = (wOut[2] & 0xFFU);
2537
0
    *output++ = (wOut[1] & 0xFFU);
2538
0
    *output++ = (wOut[0] & 0xFFU);
2539
2540
0
    return output;
2541
2542
0
    cmsUNUSED_PARAMETER(info);
2543
0
    cmsUNUSED_PARAMETER(Stride);
2544
0
}
2545
2546
2547
static
2548
cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirst(cmsContext ContextID,
2549
                                                CMSREGISTER _cmsTRANSFORM* info,
2550
                                                CMSREGISTER cmsUInt16Number wOut[],
2551
                                                CMSREGISTER cmsUInt8Number* output,
2552
                                                CMSREGISTER cmsUInt32Number Stride)
2553
0
{
2554
0
    *output++ = FROM_16_TO_8(wOut[2]);
2555
0
    *output++ = FROM_16_TO_8(wOut[1]);
2556
0
    *output++ = FROM_16_TO_8(wOut[0]);
2557
0
    output++;
2558
2559
0
    return output;
2560
2561
0
    cmsUNUSED_PARAMETER(info);
2562
0
    cmsUNUSED_PARAMETER(Stride);
2563
0
}
2564
2565
static
2566
cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirstOptimized(cmsContext ContextID,
2567
                                                         CMSREGISTER _cmsTRANSFORM* info,
2568
                                                         CMSREGISTER cmsUInt16Number wOut[],
2569
                                                         CMSREGISTER cmsUInt8Number* output,
2570
                                                         CMSREGISTER cmsUInt32Number Stride)
2571
0
{
2572
0
    *output++ = (wOut[2] & 0xFFU);
2573
0
    *output++ = (wOut[1] & 0xFFU);
2574
0
    *output++ = (wOut[0] & 0xFFU);
2575
0
    output++;
2576
2577
0
    return output;
2578
2579
0
    cmsUNUSED_PARAMETER(info);
2580
0
    cmsUNUSED_PARAMETER(Stride);
2581
0
}
2582
2583
static
2584
cmsUInt8Number* Pack3WordsAndSkip1(cmsContext ContextID,
2585
                                   CMSREGISTER _cmsTRANSFORM* info,
2586
                                   CMSREGISTER cmsUInt16Number wOut[],
2587
                                   CMSREGISTER cmsUInt8Number* output,
2588
                                   CMSREGISTER cmsUInt32Number Stride)
2589
0
{
2590
0
    *(cmsUInt16Number*) output = wOut[0];
2591
0
    output+= 2;
2592
0
    *(cmsUInt16Number*) output = wOut[1];
2593
0
    output+= 2;
2594
0
    *(cmsUInt16Number*) output = wOut[2];
2595
0
    output+= 2;
2596
0
    output+= 2;
2597
2598
0
    return output;
2599
2600
0
    cmsUNUSED_PARAMETER(info);
2601
0
    cmsUNUSED_PARAMETER(Stride);
2602
0
}
2603
2604
static
2605
cmsUInt8Number* Pack3WordsAndSkip1Swap(cmsContext ContextID,
2606
                                       CMSREGISTER _cmsTRANSFORM* info,
2607
                                       CMSREGISTER cmsUInt16Number wOut[],
2608
                                       CMSREGISTER cmsUInt8Number* output,
2609
                                       CMSREGISTER cmsUInt32Number Stride)
2610
0
{
2611
0
    output+= 2;
2612
0
    *(cmsUInt16Number*) output = wOut[2];
2613
0
    output+= 2;
2614
0
    *(cmsUInt16Number*) output = wOut[1];
2615
0
    output+= 2;
2616
0
    *(cmsUInt16Number*) output = wOut[0];
2617
0
    output+= 2;
2618
2619
0
    return output;
2620
2621
0
    cmsUNUSED_PARAMETER(info);
2622
0
    cmsUNUSED_PARAMETER(Stride);
2623
0
}
2624
2625
2626
static
2627
cmsUInt8Number* Pack3WordsAndSkip1SwapFirst(cmsContext ContextID,
2628
                                            CMSREGISTER _cmsTRANSFORM* info,
2629
                                            CMSREGISTER cmsUInt16Number wOut[],
2630
                                            CMSREGISTER cmsUInt8Number* output,
2631
                                            CMSREGISTER cmsUInt32Number Stride)
2632
0
{
2633
0
    output+= 2;
2634
0
    *(cmsUInt16Number*) output = wOut[0];
2635
0
    output+= 2;
2636
0
    *(cmsUInt16Number*) output = wOut[1];
2637
0
    output+= 2;
2638
0
    *(cmsUInt16Number*) output = wOut[2];
2639
0
    output+= 2;
2640
2641
0
    return output;
2642
2643
0
    cmsUNUSED_PARAMETER(info);
2644
0
    cmsUNUSED_PARAMETER(Stride);
2645
0
}
2646
2647
2648
static
2649
cmsUInt8Number* Pack3WordsAndSkip1SwapSwapFirst(cmsContext ContextID,
2650
                                                CMSREGISTER _cmsTRANSFORM* info,
2651
                                                CMSREGISTER cmsUInt16Number wOut[],
2652
                                                CMSREGISTER cmsUInt8Number* output,
2653
                                                CMSREGISTER cmsUInt32Number Stride)
2654
0
{
2655
0
    *(cmsUInt16Number*) output = wOut[2];
2656
0
    output+= 2;
2657
0
    *(cmsUInt16Number*) output = wOut[1];
2658
0
    output+= 2;
2659
0
    *(cmsUInt16Number*) output = wOut[0];
2660
0
    output+= 2;
2661
0
    output+= 2;
2662
2663
0
    return output;
2664
2665
0
    cmsUNUSED_PARAMETER(info);
2666
0
    cmsUNUSED_PARAMETER(Stride);
2667
0
}
2668
2669
2670
2671
static
2672
cmsUInt8Number* Pack1Byte(cmsContext ContextID,
2673
                          CMSREGISTER _cmsTRANSFORM* info,
2674
                          CMSREGISTER cmsUInt16Number wOut[],
2675
                          CMSREGISTER cmsUInt8Number* output,
2676
                          CMSREGISTER cmsUInt32Number Stride)
2677
0
{
2678
0
    *output++ = FROM_16_TO_8(wOut[0]);
2679
2680
0
    return output;
2681
2682
0
    cmsUNUSED_PARAMETER(info);
2683
0
    cmsUNUSED_PARAMETER(Stride);
2684
0
}
2685
2686
2687
static
2688
cmsUInt8Number* Pack1ByteReversed(cmsContext ContextID,
2689
                                  CMSREGISTER _cmsTRANSFORM* info,
2690
                                  CMSREGISTER cmsUInt16Number wOut[],
2691
                                  CMSREGISTER cmsUInt8Number* output,
2692
                                  CMSREGISTER cmsUInt32Number Stride)
2693
0
{
2694
0
    *output++ = FROM_16_TO_8(REVERSE_FLAVOR_16(wOut[0]));
2695
2696
0
    return output;
2697
2698
0
    cmsUNUSED_PARAMETER(info);
2699
0
    cmsUNUSED_PARAMETER(Stride);
2700
0
}
2701
2702
2703
static
2704
cmsUInt8Number* Pack1ByteSkip1(cmsContext ContextID,
2705
                               CMSREGISTER _cmsTRANSFORM* info,
2706
                               CMSREGISTER cmsUInt16Number wOut[],
2707
                               CMSREGISTER cmsUInt8Number* output,
2708
                               CMSREGISTER cmsUInt32Number Stride)
2709
0
{
2710
0
    *output++ = FROM_16_TO_8(wOut[0]);
2711
0
    output++;
2712
2713
0
    return output;
2714
2715
0
    cmsUNUSED_PARAMETER(info);
2716
0
    cmsUNUSED_PARAMETER(Stride);
2717
0
}
2718
2719
2720
static
2721
cmsUInt8Number* Pack1ByteSkip1SwapFirst(cmsContext ContextID,
2722
                                        CMSREGISTER _cmsTRANSFORM* info,
2723
                                        CMSREGISTER cmsUInt16Number wOut[],
2724
                                        CMSREGISTER cmsUInt8Number* output,
2725
                                        CMSREGISTER cmsUInt32Number Stride)
2726
0
{
2727
0
    output++;
2728
0
    *output++ = FROM_16_TO_8(wOut[0]);
2729
2730
0
    return output;
2731
2732
0
    cmsUNUSED_PARAMETER(info);
2733
0
    cmsUNUSED_PARAMETER(Stride);
2734
0
}
2735
2736
static
2737
cmsUInt8Number* Pack1Word(cmsContext ContextID,
2738
                          CMSREGISTER _cmsTRANSFORM* info,
2739
                          CMSREGISTER cmsUInt16Number wOut[],
2740
                          CMSREGISTER cmsUInt8Number* output,
2741
                          CMSREGISTER cmsUInt32Number Stride)
2742
0
{
2743
0
    *(cmsUInt16Number*) output = wOut[0];
2744
0
    output+= 2;
2745
2746
0
    return output;
2747
2748
0
    cmsUNUSED_PARAMETER(info);
2749
0
    cmsUNUSED_PARAMETER(Stride);
2750
0
}
2751
2752
2753
static
2754
cmsUInt8Number* Pack1WordReversed(cmsContext ContextID,
2755
                                  CMSREGISTER _cmsTRANSFORM* info,
2756
                                  CMSREGISTER cmsUInt16Number wOut[],
2757
                                  CMSREGISTER cmsUInt8Number* output,
2758
                                  CMSREGISTER cmsUInt32Number Stride)
2759
0
{
2760
0
    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]);
2761
0
    output+= 2;
2762
2763
0
    return output;
2764
2765
0
    cmsUNUSED_PARAMETER(info);
2766
0
    cmsUNUSED_PARAMETER(Stride);
2767
0
}
2768
2769
static
2770
cmsUInt8Number* Pack1WordBigEndian(cmsContext ContextID,
2771
                                   CMSREGISTER _cmsTRANSFORM* info,
2772
                                   CMSREGISTER cmsUInt16Number wOut[],
2773
                                   CMSREGISTER cmsUInt8Number* output,
2774
                                   CMSREGISTER cmsUInt32Number Stride)
2775
0
{
2776
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
2777
0
    output+= 2;
2778
2779
0
    return output;
2780
2781
0
    cmsUNUSED_PARAMETER(info);
2782
0
    cmsUNUSED_PARAMETER(Stride);
2783
0
}
2784
2785
2786
static
2787
cmsUInt8Number* Pack1WordSkip1(cmsContext ContextID,
2788
                               CMSREGISTER _cmsTRANSFORM* info,
2789
                               CMSREGISTER cmsUInt16Number wOut[],
2790
                               CMSREGISTER cmsUInt8Number* output,
2791
                               CMSREGISTER cmsUInt32Number Stride)
2792
0
{
2793
0
    *(cmsUInt16Number*) output = wOut[0];
2794
0
    output+= 4;
2795
2796
0
    return output;
2797
2798
0
    cmsUNUSED_PARAMETER(info);
2799
0
    cmsUNUSED_PARAMETER(Stride);
2800
0
}
2801
2802
static
2803
cmsUInt8Number* Pack1WordSkip1SwapFirst(cmsContext ContextID,
2804
                                        CMSREGISTER _cmsTRANSFORM* info,
2805
                                        CMSREGISTER cmsUInt16Number wOut[],
2806
                                        CMSREGISTER cmsUInt8Number* output,
2807
                                        CMSREGISTER cmsUInt32Number Stride)
2808
0
{
2809
0
    output += 2;
2810
0
    *(cmsUInt16Number*) output = wOut[0];
2811
0
    output+= 2;
2812
2813
0
    return output;
2814
2815
0
    cmsUNUSED_PARAMETER(info);
2816
0
    cmsUNUSED_PARAMETER(Stride);
2817
0
}
2818
2819
2820
// Unencoded Float values -- don't try optimize speed
2821
static
2822
cmsUInt8Number* PackLabDoubleFrom16(cmsContext ContextID,
2823
                                    CMSREGISTER _cmsTRANSFORM* info,
2824
                                    CMSREGISTER cmsUInt16Number wOut[],
2825
                                    CMSREGISTER cmsUInt8Number* output,
2826
                                    CMSREGISTER cmsUInt32Number Stride)
2827
0
{
2828
2829
0
    if (T_PLANAR(info -> OutputFormat)) {
2830
2831
0
        cmsCIELab  Lab;
2832
0
        cmsFloat64Number* Out = (cmsFloat64Number*) output;
2833
0
        cmsLabEncoded2Float(ContextID, &Lab, wOut);
2834
2835
0
        Out[0]        = Lab.L;
2836
0
        Out[Stride]   = Lab.a;
2837
0
        Out[Stride*2] = Lab.b;
2838
2839
0
        return output + sizeof(cmsFloat64Number);
2840
0
    }
2841
0
    else {
2842
2843
0
        cmsLabEncoded2Float(ContextID, (cmsCIELab*) output, wOut);
2844
0
        return output + (sizeof(cmsCIELab) + T_EXTRA(info ->OutputFormat) * sizeof(cmsFloat64Number));
2845
0
    }
2846
0
}
2847
2848
2849
static
2850
cmsUInt8Number* PackLabFloatFrom16(cmsContext ContextID,
2851
                                   CMSREGISTER _cmsTRANSFORM* info,
2852
                                   CMSREGISTER cmsUInt16Number wOut[],
2853
                                   CMSREGISTER cmsUInt8Number* output,
2854
                                   CMSREGISTER cmsUInt32Number Stride)
2855
0
{
2856
0
    cmsCIELab  Lab;
2857
0
    cmsLabEncoded2Float(ContextID, &Lab, wOut);
2858
2859
0
    if (T_PLANAR(info -> OutputFormat)) {
2860
2861
0
        cmsFloat32Number* Out = (cmsFloat32Number*) output;
2862
2863
0
        Stride /= PixelSize(info->OutputFormat);
2864
2865
0
        Out[0]        = (cmsFloat32Number)Lab.L;
2866
0
        Out[Stride]   = (cmsFloat32Number)Lab.a;
2867
0
        Out[Stride*2] = (cmsFloat32Number)Lab.b;
2868
2869
0
        return output + sizeof(cmsFloat32Number);
2870
0
    }
2871
0
    else {
2872
2873
0
       ((cmsFloat32Number*) output)[0] = (cmsFloat32Number) Lab.L;
2874
0
       ((cmsFloat32Number*) output)[1] = (cmsFloat32Number) Lab.a;
2875
0
       ((cmsFloat32Number*) output)[2] = (cmsFloat32Number) Lab.b;
2876
2877
0
        return output + (3 + T_EXTRA(info ->OutputFormat)) * sizeof(cmsFloat32Number);
2878
0
    }
2879
0
}
2880
2881
static
2882
cmsUInt8Number* PackXYZDoubleFrom16(cmsContext ContextID,
2883
                                    CMSREGISTER _cmsTRANSFORM* Info,
2884
                                    CMSREGISTER cmsUInt16Number wOut[],
2885
                                    CMSREGISTER cmsUInt8Number* output,
2886
                                    CMSREGISTER cmsUInt32Number Stride)
2887
0
{
2888
0
    if (T_PLANAR(Info -> OutputFormat)) {
2889
2890
0
        cmsCIEXYZ XYZ;
2891
0
        cmsFloat64Number* Out = (cmsFloat64Number*) output;
2892
0
        cmsXYZEncoded2Float(ContextID, &XYZ, wOut);
2893
2894
0
        Stride /= PixelSize(Info->OutputFormat);
2895
2896
0
        Out[0]        = XYZ.X;
2897
0
        Out[Stride]   = XYZ.Y;
2898
0
        Out[Stride*2] = XYZ.Z;
2899
2900
0
        return output + sizeof(cmsFloat64Number);
2901
2902
0
    }
2903
0
    else {
2904
2905
0
        cmsXYZEncoded2Float(ContextID, (cmsCIEXYZ*) output, wOut);
2906
2907
0
        return output + (sizeof(cmsCIEXYZ) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
2908
0
    }
2909
0
}
2910
2911
static
2912
cmsUInt8Number* PackXYZFloatFrom16(cmsContext ContextID,
2913
                                   CMSREGISTER _cmsTRANSFORM* Info,
2914
                                   CMSREGISTER cmsUInt16Number wOut[],
2915
                                   CMSREGISTER cmsUInt8Number* output,
2916
                                   CMSREGISTER cmsUInt32Number Stride)
2917
0
{
2918
0
    if (T_PLANAR(Info -> OutputFormat)) {
2919
2920
0
        cmsCIEXYZ XYZ;
2921
0
        cmsFloat32Number* Out = (cmsFloat32Number*) output;
2922
0
        cmsXYZEncoded2Float(ContextID, &XYZ, wOut);
2923
2924
0
        Stride /= PixelSize(Info->OutputFormat);
2925
2926
0
        Out[0]        = (cmsFloat32Number) XYZ.X;
2927
0
        Out[Stride]   = (cmsFloat32Number) XYZ.Y;
2928
0
        Out[Stride*2] = (cmsFloat32Number) XYZ.Z;
2929
2930
0
        return output + sizeof(cmsFloat32Number);
2931
2932
0
    }
2933
0
    else {
2934
2935
0
        cmsCIEXYZ XYZ;
2936
0
        cmsFloat32Number* Out = (cmsFloat32Number*) output;
2937
0
        cmsXYZEncoded2Float(ContextID, &XYZ, wOut);
2938
2939
0
        Out[0] = (cmsFloat32Number) XYZ.X;
2940
0
        Out[1] = (cmsFloat32Number) XYZ.Y;
2941
0
        Out[2] = (cmsFloat32Number) XYZ.Z;
2942
2943
0
        return output + (3 * sizeof(cmsFloat32Number) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
2944
0
    }
2945
0
}
2946
2947
static
2948
cmsUInt8Number* PackDoubleFrom16(cmsContext ContextID,
2949
                                 CMSREGISTER _cmsTRANSFORM* info,
2950
                                 CMSREGISTER cmsUInt16Number wOut[],
2951
                                 CMSREGISTER cmsUInt8Number* output,
2952
                                 CMSREGISTER cmsUInt32Number Stride)
2953
0
{
2954
0
    cmsUInt32Number nChan      = T_CHANNELS(info -> OutputFormat);
2955
0
    cmsUInt32Number DoSwap     = T_DOSWAP(info ->OutputFormat);
2956
0
    cmsUInt32Number Reverse    = T_FLAVOR(info ->OutputFormat);
2957
0
    cmsUInt32Number Extra      = T_EXTRA(info -> OutputFormat);
2958
0
    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> OutputFormat);
2959
0
    cmsUInt32Number Planar     = T_PLANAR(info -> OutputFormat);
2960
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
2961
0
    cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0;
2962
0
    cmsFloat64Number v = 0;
2963
0
    cmsFloat64Number* swap1 = (cmsFloat64Number*) output;
2964
0
    cmsUInt32Number i, start = 0;
2965
2966
0
    Stride /= PixelSize(info->OutputFormat);
2967
2968
0
    if (ExtraFirst)
2969
0
        start = Extra;
2970
2971
0
    for (i=0; i < nChan; i++) {
2972
2973
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
2974
2975
0
        v = (cmsFloat64Number) wOut[index] / maximum;
2976
2977
0
        if (Reverse)
2978
0
            v = maximum - v;
2979
2980
0
        if (Planar)
2981
0
            ((cmsFloat64Number*) output)[(i + start)  * Stride]= v;
2982
0
        else
2983
0
            ((cmsFloat64Number*) output)[i + start] = v;
2984
0
    }
2985
2986
2987
0
    if (Extra == 0 && SwapFirst) {
2988
2989
0
         memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number));
2990
0
        *swap1 = v;
2991
0
    }
2992
2993
0
    if (T_PLANAR(info -> OutputFormat))
2994
0
        return output + sizeof(cmsFloat64Number);
2995
0
    else
2996
0
        return output + (nChan + Extra) * sizeof(cmsFloat64Number);
2997
2998
0
}
2999
3000
3001
static
3002
cmsUInt8Number* PackFloatFrom16(cmsContext ContextID,
3003
                                CMSREGISTER _cmsTRANSFORM* info,
3004
                                CMSREGISTER cmsUInt16Number wOut[],
3005
                                CMSREGISTER cmsUInt8Number* output,
3006
                                CMSREGISTER cmsUInt32Number Stride)
3007
0
{
3008
0
       cmsUInt32Number nChan      = T_CHANNELS(info->OutputFormat);
3009
0
       cmsUInt32Number DoSwap     = T_DOSWAP(info->OutputFormat);
3010
0
       cmsUInt32Number Reverse    = T_FLAVOR(info->OutputFormat);
3011
0
       cmsUInt32Number Extra      = T_EXTRA(info->OutputFormat);
3012
0
       cmsUInt32Number SwapFirst  = T_SWAPFIRST(info->OutputFormat);
3013
0
       cmsUInt32Number Planar     = T_PLANAR(info->OutputFormat);
3014
0
       cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3015
0
       cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 655.35 : 65535.0;
3016
0
       cmsFloat64Number v = 0;
3017
0
       cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
3018
0
       cmsUInt32Number i, start = 0;
3019
3020
0
       Stride /= PixelSize(info->OutputFormat);
3021
3022
0
       if (ExtraFirst)
3023
0
              start = Extra;
3024
3025
0
       for (i = 0; i < nChan; i++) {
3026
3027
0
              cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3028
3029
0
              v = (cmsFloat64Number)wOut[index] / maximum;
3030
3031
0
              if (Reverse)
3032
0
                     v = maximum - v;
3033
3034
0
              if (Planar)
3035
0
                     ((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v;
3036
0
              else
3037
0
                     ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;
3038
0
       }
3039
3040
3041
0
       if (Extra == 0 && SwapFirst) {
3042
3043
0
              memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));
3044
0
              *swap1 = (cmsFloat32Number)v;
3045
0
       }
3046
3047
0
       if (T_PLANAR(info->OutputFormat))
3048
0
              return output + sizeof(cmsFloat32Number);
3049
0
       else
3050
0
              return output + (nChan + Extra) * sizeof(cmsFloat32Number);
3051
0
}
3052
3053
3054
3055
// --------------------------------------------------------------------------------------------------------
3056
3057
static
3058
cmsUInt8Number* PackBytesFromFloat(cmsContext ContextID,
3059
           _cmsTRANSFORM* info,
3060
                                    cmsFloat32Number wOut[],
3061
                                    cmsUInt8Number* output,
3062
                                    cmsUInt32Number Stride)
3063
0
{
3064
0
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
3065
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
3066
0
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
3067
0
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
3068
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
3069
0
    cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
3070
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;    
3071
0
    cmsUInt8Number* swap1 = (cmsUInt8Number*)output;
3072
0
    cmsFloat64Number v = 0;
3073
0
    cmsUInt8Number vv = 0;
3074
0
    cmsUInt32Number i, start = 0;
3075
    
3076
0
    if (ExtraFirst)
3077
0
        start = Extra;
3078
3079
0
    for (i = 0; i < nChan; i++) {
3080
3081
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3082
3083
0
        v = wOut[index] * 65535.0;
3084
3085
0
        if (Reverse)
3086
0
            v = 65535.0 - v;
3087
        
3088
0
        vv =  FROM_16_TO_8(_cmsQuickSaturateWord(v));
3089
3090
0
        if (Planar)
3091
0
            ((cmsUInt8Number*)output)[(i + start) * Stride] = vv;
3092
0
        else
3093
0
            ((cmsUInt8Number*)output)[i + start] = vv;
3094
0
    }
3095
3096
3097
0
    if (Extra == 0 && SwapFirst) {
3098
3099
0
        memmove(swap1 + 1, swap1, (nChan - 1) * sizeof(cmsUInt8Number));
3100
0
        *swap1 = vv;
3101
0
    }
3102
3103
0
    if (T_PLANAR(info->OutputFormat))
3104
0
        return output + sizeof(cmsUInt8Number);
3105
0
    else
3106
0
        return output + (nChan + Extra) * sizeof(cmsUInt8Number);
3107
0
}
3108
3109
static
3110
cmsUInt8Number* PackWordsFromFloat(cmsContext ContextID,
3111
            _cmsTRANSFORM* info,
3112
                                    cmsFloat32Number wOut[],
3113
                                    cmsUInt8Number* output,
3114
                                    cmsUInt32Number Stride)
3115
0
{
3116
0
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
3117
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
3118
0
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
3119
0
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
3120
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
3121
0
    cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
3122
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;    
3123
0
    cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
3124
0
    cmsFloat64Number v = 0;
3125
0
    cmsUInt16Number vv = 0;
3126
0
    cmsUInt32Number i, start = 0;
3127
    
3128
0
    if (ExtraFirst)
3129
0
        start = Extra;
3130
3131
0
    for (i = 0; i < nChan; i++) {
3132
3133
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3134
3135
0
        v = wOut[index] * 65535.0;
3136
3137
0
        if (Reverse)
3138
0
            v = 65535.0 - v;
3139
3140
0
        vv = _cmsQuickSaturateWord(v);
3141
3142
0
        if (Planar)
3143
0
            ((cmsUInt16Number*)output)[(i + start) * Stride] = vv;
3144
0
        else
3145
0
            ((cmsUInt16Number*)output)[i + start] = vv;
3146
0
    }
3147
3148
0
    if (Extra == 0 && SwapFirst) {
3149
3150
0
        memmove(swap1 + 1, swap1, (nChan - 1) * sizeof(cmsUInt16Number));
3151
0
        *swap1 = vv;
3152
0
    }
3153
3154
0
    if (T_PLANAR(info->OutputFormat))
3155
0
        return output + sizeof(cmsUInt16Number);
3156
0
    else
3157
0
        return output + (nChan + Extra) * sizeof(cmsUInt16Number);
3158
0
}
3159
3160
3161
static
3162
cmsUInt8Number* PackFloatsFromFloat(cmsContext ContextID,
3163
           _cmsTRANSFORM* info,
3164
                                    cmsFloat32Number wOut[],
3165
                                    cmsUInt8Number* output,
3166
                                    cmsUInt32Number Stride)
3167
0
{
3168
0
       cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
3169
0
       cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
3170
0
       cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
3171
0
       cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
3172
0
       cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
3173
0
       cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
3174
0
       cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3175
0
       cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;
3176
0
       cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
3177
0
       cmsFloat64Number v = 0;
3178
0
       cmsUInt32Number i, start = 0;
3179
3180
0
       Stride /= PixelSize(info->OutputFormat);
3181
3182
0
       if (ExtraFirst)
3183
0
              start = Extra;
3184
3185
0
       for (i = 0; i < nChan; i++) {
3186
3187
0
              cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3188
3189
0
              v = wOut[index] * maximum;
3190
3191
0
              if (Reverse)
3192
0
                     v = maximum - v;
3193
3194
0
              if (Planar)
3195
0
                     ((cmsFloat32Number*)output)[(i + start)* Stride] = (cmsFloat32Number)v;
3196
0
              else
3197
0
                     ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;
3198
0
       }
3199
3200
3201
0
       if (Extra == 0 && SwapFirst) {
3202
3203
0
              memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));
3204
0
              *swap1 = (cmsFloat32Number)v;
3205
0
       }
3206
3207
0
       if (T_PLANAR(info->OutputFormat))
3208
0
              return output + sizeof(cmsFloat32Number);
3209
0
       else
3210
0
              return output + (nChan + Extra) * sizeof(cmsFloat32Number);
3211
0
}
3212
3213
static
3214
cmsUInt8Number* PackDoublesFromFloat(cmsContext ContextID, _cmsTRANSFORM* info,
3215
                                    cmsFloat32Number wOut[],
3216
                                    cmsUInt8Number* output,
3217
                                    cmsUInt32Number Stride)
3218
0
{
3219
0
       cmsUInt32Number nChan      = T_CHANNELS(info->OutputFormat);
3220
0
       cmsUInt32Number DoSwap     = T_DOSWAP(info->OutputFormat);
3221
0
       cmsUInt32Number Reverse    = T_FLAVOR(info->OutputFormat);
3222
0
       cmsUInt32Number Extra      = T_EXTRA(info->OutputFormat);
3223
0
       cmsUInt32Number SwapFirst  = T_SWAPFIRST(info->OutputFormat);
3224
0
       cmsUInt32Number Planar     = T_PLANAR(info->OutputFormat);
3225
0
       cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3226
0
       cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;
3227
0
       cmsFloat64Number v = 0;
3228
0
       cmsFloat64Number* swap1 = (cmsFloat64Number*)output;
3229
0
       cmsUInt32Number i, start = 0;
3230
3231
0
       Stride /= PixelSize(info->OutputFormat);
3232
3233
0
       if (ExtraFirst)
3234
0
              start = Extra;
3235
3236
0
       for (i = 0; i < nChan; i++) {
3237
3238
0
              cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3239
3240
0
              v = wOut[index] * maximum;
3241
3242
0
              if (Reverse)
3243
0
                     v = maximum - v;
3244
3245
0
              if (Planar)
3246
0
                     ((cmsFloat64Number*)output)[(i + start) * Stride] = v;
3247
0
              else
3248
0
                     ((cmsFloat64Number*)output)[i + start] = v;
3249
0
       }
3250
3251
0
       if (Extra == 0 && SwapFirst) {
3252
3253
0
              memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat64Number));
3254
0
              *swap1 = v;
3255
0
       }
3256
3257
3258
0
       if (T_PLANAR(info->OutputFormat))
3259
0
              return output + sizeof(cmsFloat64Number);
3260
0
       else
3261
0
              return output + (nChan + Extra) * sizeof(cmsFloat64Number);
3262
3263
0
}
3264
3265
static
3266
cmsUInt8Number* PackLabFloatFromFloat(cmsContext ContextID, _cmsTRANSFORM* Info,
3267
                                      cmsFloat32Number wOut[],
3268
                                      cmsUInt8Number* output,
3269
                                      cmsUInt32Number Stride)
3270
0
{
3271
0
    cmsFloat32Number* Out = (cmsFloat32Number*) output;
3272
3273
0
    if (T_PLANAR(Info -> OutputFormat)) {
3274
3275
0
        Stride /= PixelSize(Info->OutputFormat);
3276
3277
0
        Out[0]        = (cmsFloat32Number) (wOut[0] * 100.0);
3278
0
        Out[Stride]   = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0);
3279
0
        Out[Stride*2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0);
3280
3281
0
        return output + sizeof(cmsFloat32Number);
3282
0
    }
3283
0
    else {
3284
3285
0
        Out[0] = (cmsFloat32Number) (wOut[0] * 100.0);
3286
0
        Out[1] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0);
3287
0
        Out[2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0);
3288
3289
0
        return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
3290
0
    }
3291
3292
0
}
3293
3294
3295
static
3296
cmsUInt8Number* PackLabDoubleFromFloat(cmsContext ContextID, _cmsTRANSFORM* Info,
3297
                                       cmsFloat32Number wOut[],
3298
                                       cmsUInt8Number* output,
3299
                                       cmsUInt32Number Stride)
3300
6
{
3301
6
    cmsFloat64Number* Out = (cmsFloat64Number*) output;
3302
3303
6
    if (T_PLANAR(Info -> OutputFormat)) {
3304
3305
0
        Stride /= PixelSize(Info->OutputFormat);
3306
3307
0
        Out[0]        = (cmsFloat64Number) (wOut[0] * 100.0);
3308
0
        Out[Stride]   = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0);
3309
0
        Out[Stride*2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0);
3310
3311
0
        return output + sizeof(cmsFloat64Number);
3312
0
    }
3313
6
    else {
3314
3315
6
        Out[0] = (cmsFloat64Number) (wOut[0] * 100.0);
3316
6
        Out[1] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0);
3317
6
        Out[2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0);
3318
3319
6
        return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
3320
6
    }
3321
3322
6
}
3323
3324
3325
static
3326
cmsUInt8Number* PackEncodedBytesLabV2FromFloat(cmsContext ContextID, _cmsTRANSFORM* Info,
3327
                                           cmsFloat32Number wOut[],
3328
                                           cmsUInt8Number* output,
3329
                                           cmsUInt32Number Stride)
3330
0
{    
3331
0
    cmsCIELab Lab;
3332
0
    cmsUInt16Number wlab[3];
3333
3334
0
    Lab.L = (cmsFloat64Number)(wOut[0] * 100.0);
3335
0
    Lab.a = (cmsFloat64Number)(wOut[1] * 255.0 - 128.0);
3336
0
    Lab.b = (cmsFloat64Number)(wOut[2] * 255.0 - 128.0);
3337
3338
0
    cmsFloat2LabEncoded(ContextID, wlab, &Lab);
3339
    
3340
0
    if (T_PLANAR(Info -> OutputFormat)) {
3341
3342
0
        Stride /= PixelSize(Info->OutputFormat);       
3343
    
3344
0
        output[0]        = wlab[0] >> 8;
3345
0
        output[Stride]   = wlab[1] >> 8;
3346
0
        output[Stride*2] = wlab[2] >> 8;
3347
3348
0
        return output + 1;
3349
0
    }
3350
0
    else {
3351
3352
0
        output[0] = wlab[0] >> 8;
3353
0
        output[1] = wlab[1] >> 8;
3354
0
        output[2] = wlab[2] >> 8;
3355
3356
0
        return output + (3 + T_EXTRA(Info ->OutputFormat));
3357
0
    }
3358
0
}
3359
3360
static
3361
cmsUInt8Number* PackEncodedWordsLabV2FromFloat(cmsContext ContextID, _cmsTRANSFORM* Info,
3362
                                           cmsFloat32Number wOut[],
3363
                                           cmsUInt8Number* output,
3364
                                           cmsUInt32Number Stride)
3365
0
{    
3366
0
    cmsCIELab Lab;
3367
0
    cmsUInt16Number wlab[3];
3368
3369
0
    Lab.L = (cmsFloat64Number)(wOut[0] * 100.0);
3370
0
    Lab.a = (cmsFloat64Number)(wOut[1] * 255.0 - 128.0);
3371
0
    Lab.b = (cmsFloat64Number)(wOut[2] * 255.0 - 128.0);
3372
3373
0
    cmsFloat2LabEncodedV2(ContextID, wlab, &Lab);
3374
    
3375
0
    if (T_PLANAR(Info -> OutputFormat)) {
3376
3377
0
        Stride /= PixelSize(Info->OutputFormat);       
3378
    
3379
0
        ((cmsUInt16Number*) output)[0]        = wlab[0];
3380
0
        ((cmsUInt16Number*) output)[Stride]   = wlab[1];
3381
0
        ((cmsUInt16Number*) output)[Stride*2] = wlab[2];
3382
3383
0
        return output + sizeof(cmsUInt16Number);
3384
0
    }
3385
0
    else {
3386
3387
0
         ((cmsUInt16Number*) output)[0] = wlab[0];
3388
0
         ((cmsUInt16Number*) output)[1] = wlab[1];
3389
0
         ((cmsUInt16Number*) output)[2] = wlab[2];
3390
3391
0
        return output + (3 + T_EXTRA(Info ->OutputFormat)) * sizeof(cmsUInt16Number);
3392
0
    }
3393
0
}
3394
3395
3396
// From 0..1 range to 0..MAX_ENCODEABLE_XYZ
3397
static
3398
cmsUInt8Number* PackXYZFloatFromFloat(cmsContext ContextID, _cmsTRANSFORM* Info,
3399
                                      cmsFloat32Number wOut[],
3400
                                      cmsUInt8Number* output,
3401
                                      cmsUInt32Number Stride)
3402
0
{
3403
0
    cmsFloat32Number* Out = (cmsFloat32Number*) output;
3404
3405
0
    if (T_PLANAR(Info -> OutputFormat)) {
3406
3407
0
        Stride /= PixelSize(Info->OutputFormat);
3408
3409
0
        Out[0]        = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
3410
0
        Out[Stride]   = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
3411
0
        Out[Stride*2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
3412
3413
0
        return output + sizeof(cmsFloat32Number);
3414
0
    }
3415
0
    else {
3416
3417
0
        Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
3418
0
        Out[1] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
3419
0
        Out[2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
3420
3421
0
        return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
3422
0
    }
3423
3424
0
}
3425
3426
// Same, but convert to double
3427
static
3428
cmsUInt8Number* PackXYZDoubleFromFloat(cmsContext ContextID, _cmsTRANSFORM* Info,
3429
                                       cmsFloat32Number wOut[],
3430
                                       cmsUInt8Number* output,
3431
                                       cmsUInt32Number Stride)
3432
0
{
3433
0
    cmsFloat64Number* Out = (cmsFloat64Number*) output;
3434
3435
0
    if (T_PLANAR(Info -> OutputFormat)) {
3436
3437
0
        Stride /= PixelSize(Info->OutputFormat);
3438
3439
0
        Out[0]        = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
3440
0
        Out[Stride]   = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
3441
0
        Out[Stride*2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
3442
3443
0
        return output + sizeof(cmsFloat64Number);
3444
0
    }
3445
0
    else {
3446
3447
0
        Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
3448
0
        Out[1] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
3449
0
        Out[2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
3450
3451
0
        return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
3452
0
    }
3453
3454
0
}
3455
3456
3457
// ----------------------------------------------------------------------------------------------------------------
3458
3459
#ifndef CMS_NO_HALF_SUPPORT
3460
3461
// Decodes an stream of half floats to wIn[] described by input format
3462
3463
static
3464
cmsUInt8Number* UnrollHalfTo16(cmsContext ContextID,
3465
                               CMSREGISTER _cmsTRANSFORM* info,
3466
                               CMSREGISTER cmsUInt16Number wIn[],
3467
                               CMSREGISTER cmsUInt8Number* accum,
3468
                               CMSREGISTER cmsUInt32Number Stride)
3469
0
{
3470
3471
0
    cmsUInt32Number nChan      = T_CHANNELS(info -> InputFormat);
3472
0
    cmsUInt32Number DoSwap     = T_DOSWAP(info ->InputFormat);
3473
0
    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
3474
0
    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
3475
0
    cmsUInt32Number Extra      = T_EXTRA(info -> InputFormat);
3476
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3477
0
    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
3478
0
    cmsFloat32Number v;
3479
0
    cmsUInt32Number i, start = 0;
3480
0
    cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 655.35F : 65535.0F;
3481
3482
3483
0
    Stride /= PixelSize(info->OutputFormat);
3484
3485
0
    if (ExtraFirst)
3486
0
            start = Extra;
3487
3488
0
    for (i=0; i < nChan; i++) {
3489
3490
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3491
3492
0
        if (Planar)
3493
0
            v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] );
3494
0
        else
3495
0
            v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[i + start] ) ;
3496
3497
0
        if (Reverse) v = maximum - v;
3498
3499
0
        wIn[index] = _cmsQuickSaturateWord((cmsFloat64Number) v * maximum);
3500
0
    }
3501
3502
3503
0
    if (Extra == 0 && SwapFirst) {
3504
0
        cmsUInt16Number tmp = wIn[0];
3505
3506
0
        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
3507
0
        wIn[nChan-1] = tmp;
3508
0
    }
3509
3510
0
    if (T_PLANAR(info -> InputFormat))
3511
0
        return accum + sizeof(cmsUInt16Number);
3512
0
    else
3513
0
        return accum + (nChan + Extra) * sizeof(cmsUInt16Number);
3514
0
}
3515
3516
// Decodes an stream of half floats to wIn[] described by input format
3517
3518
static
3519
cmsUInt8Number* UnrollHalfToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
3520
                                    cmsFloat32Number wIn[],
3521
                                    cmsUInt8Number* accum,
3522
                                    cmsUInt32Number Stride)
3523
0
{
3524
3525
0
    cmsUInt32Number nChan      = T_CHANNELS(info -> InputFormat);
3526
0
    cmsUInt32Number DoSwap     = T_DOSWAP(info ->InputFormat);
3527
0
    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
3528
0
    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
3529
0
    cmsUInt32Number Extra      = T_EXTRA(info -> InputFormat);
3530
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3531
0
    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
3532
0
    cmsFloat32Number v;
3533
0
    cmsUInt32Number i, start = 0;
3534
0
    cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F;
3535
3536
0
    Stride /= PixelSize(info->OutputFormat);
3537
3538
0
    if (ExtraFirst)
3539
0
            start = Extra;
3540
3541
0
    for (i=0; i < nChan; i++) {
3542
3543
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3544
3545
0
        if (Planar)
3546
0
            v =  _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] );
3547
0
        else
3548
0
            v =  _cmsHalf2Float ( ((cmsUInt16Number*) accum)[i + start] ) ;
3549
3550
0
        v /= maximum;
3551
3552
0
        wIn[index] = Reverse ? 1 - v : v;
3553
0
    }
3554
3555
3556
0
    if (Extra == 0 && SwapFirst) {
3557
0
        cmsFloat32Number tmp = wIn[0];
3558
3559
0
        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));
3560
0
        wIn[nChan-1] = tmp;
3561
0
    }
3562
3563
0
    if (T_PLANAR(info -> InputFormat))
3564
0
        return accum + sizeof(cmsUInt16Number);
3565
0
    else
3566
0
        return accum + (nChan + Extra) * sizeof(cmsUInt16Number);
3567
0
}
3568
3569
3570
static
3571
cmsUInt8Number* PackHalfFrom16(cmsContext ContextID,
3572
                               CMSREGISTER _cmsTRANSFORM* info,
3573
                               CMSREGISTER cmsUInt16Number wOut[],
3574
                               CMSREGISTER cmsUInt8Number* output,
3575
                               CMSREGISTER cmsUInt32Number Stride)
3576
0
{
3577
0
       cmsUInt32Number nChan      = T_CHANNELS(info->OutputFormat);
3578
0
       cmsUInt32Number DoSwap     = T_DOSWAP(info->OutputFormat);
3579
0
       cmsUInt32Number Reverse    = T_FLAVOR(info->OutputFormat);
3580
0
       cmsUInt32Number Extra      = T_EXTRA(info->OutputFormat);
3581
0
       cmsUInt32Number SwapFirst  = T_SWAPFIRST(info->OutputFormat);
3582
0
       cmsUInt32Number Planar     = T_PLANAR(info->OutputFormat);
3583
0
       cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3584
0
       cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 655.35F : 65535.0F;
3585
0
       cmsFloat32Number v = 0;
3586
0
       cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
3587
0
       cmsUInt32Number i, start = 0;
3588
3589
0
       Stride /= PixelSize(info->OutputFormat);
3590
3591
0
       if (ExtraFirst)
3592
0
              start = Extra;
3593
3594
0
       for (i = 0; i < nChan; i++) {
3595
3596
0
              cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3597
3598
0
              v = (cmsFloat32Number)wOut[index] / maximum;
3599
3600
0
              if (Reverse)
3601
0
                     v = maximum - v;
3602
3603
0
              if (Planar)
3604
0
                     ((cmsUInt16Number*)output)[(i + start) * Stride] = _cmsFloat2Half(v);
3605
0
              else
3606
0
                     ((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v);
3607
0
       }
3608
3609
3610
0
       if (Extra == 0 && SwapFirst) {
3611
3612
0
              memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number));
3613
0
              *swap1 = _cmsFloat2Half(v);
3614
0
       }
3615
3616
0
       if (T_PLANAR(info->OutputFormat))
3617
0
              return output + sizeof(cmsUInt16Number);
3618
0
       else
3619
0
              return output + (nChan + Extra) * sizeof(cmsUInt16Number);
3620
0
}
3621
3622
3623
3624
static
3625
cmsUInt8Number* PackHalfFromFloat(cmsContext ContextID, _cmsTRANSFORM* info,
3626
                                    cmsFloat32Number wOut[],
3627
                                    cmsUInt8Number* output,
3628
                                    cmsUInt32Number Stride)
3629
0
{
3630
0
       cmsUInt32Number nChan      = T_CHANNELS(info->OutputFormat);
3631
0
       cmsUInt32Number DoSwap     = T_DOSWAP(info->OutputFormat);
3632
0
       cmsUInt32Number Reverse    = T_FLAVOR(info->OutputFormat);
3633
0
       cmsUInt32Number Extra      = T_EXTRA(info->OutputFormat);
3634
0
       cmsUInt32Number SwapFirst  = T_SWAPFIRST(info->OutputFormat);
3635
0
       cmsUInt32Number Planar     = T_PLANAR(info->OutputFormat);
3636
0
       cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3637
0
       cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 100.0F : 1.0F;
3638
0
       cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
3639
0
       cmsFloat32Number v = 0;
3640
0
       cmsUInt32Number i, start = 0;
3641
3642
0
       Stride /= PixelSize(info->OutputFormat);
3643
3644
0
       if (ExtraFirst)
3645
0
              start = Extra;
3646
3647
0
       for (i = 0; i < nChan; i++) {
3648
3649
0
           cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3650
3651
0
              v = wOut[index] * maximum;
3652
3653
0
              if (Reverse)
3654
0
                     v = maximum - v;
3655
3656
0
              if (Planar)
3657
0
                     ((cmsUInt16Number*)output)[(i + start)* Stride] = _cmsFloat2Half(v);
3658
0
              else
3659
0
                     ((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v);
3660
0
       }
3661
3662
3663
0
       if (Extra == 0 && SwapFirst) {
3664
3665
0
              memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number));
3666
0
              *swap1 = (cmsUInt16Number)_cmsFloat2Half(v);
3667
0
       }
3668
3669
0
       if (T_PLANAR(info->OutputFormat))
3670
0
              return output + sizeof(cmsUInt16Number);
3671
0
       else
3672
0
              return output + (nChan + Extra)* sizeof(cmsUInt16Number);
3673
0
}
3674
3675
#endif
3676
3677
// ----------------------------------------------------------------------------------------------------------------
3678
3679
3680
static const cmsFormatters16 InputFormatters16[] = {
3681
3682
    //    Type                                          Mask                  Function
3683
    //  ----------------------------   ------------------------------------  ----------------------------
3684
    { TYPE_Lab_DBL,                                 ANYPLANAR|ANYEXTRA,   UnrollLabDoubleTo16},
3685
    { TYPE_XYZ_DBL,                                 ANYPLANAR|ANYEXTRA,   UnrollXYZDoubleTo16},
3686
    { TYPE_Lab_FLT,                                 ANYPLANAR|ANYEXTRA,   UnrollLabFloatTo16},
3687
    { TYPE_XYZ_FLT,                                 ANYPLANAR|ANYEXTRA,   UnrollXYZFloatTo16},
3688
    { TYPE_GRAY_DBL,                                                 0,   UnrollDouble1Chan},
3689
    { FLOAT_SH(1)|BYTES_SH(0), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR|
3690
                                             ANYSWAP|ANYEXTRA|ANYSPACE,   UnrollDoubleTo16},
3691
    { FLOAT_SH(1)|BYTES_SH(4), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR|
3692
                                             ANYSWAP|ANYEXTRA|ANYSPACE,   UnrollFloatTo16},
3693
#ifndef CMS_NO_HALF_SUPPORT
3694
    { FLOAT_SH(1)|BYTES_SH(2), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR|
3695
                                            ANYEXTRA|ANYSWAP|ANYSPACE,   UnrollHalfTo16},
3696
#endif
3697
3698
    { CHANNELS_SH(1)|BYTES_SH(1),                              ANYSPACE,  Unroll1Byte},
3699
    { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1),                  ANYSPACE,  Unroll1ByteSkip1},
3700
    { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(2),                  ANYSPACE,  Unroll1ByteSkip2},
3701
    { CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1),                 ANYSPACE,  Unroll1ByteReversed},
3702
    { COLORSPACE_SH(PT_MCH2)|CHANNELS_SH(2)|BYTES_SH(1),              0,  Unroll2Bytes},
3703
3704
    { TYPE_LabV2_8,                                                   0,  UnrollLabV2_8 },
3705
    { TYPE_ALabV2_8,                                                  0,  UnrollALabV2_8 },
3706
    { TYPE_LabV2_16,                                                  0,  UnrollLabV2_16 },
3707
3708
    { CHANNELS_SH(3)|BYTES_SH(1),                              ANYSPACE,  Unroll3Bytes},
3709
    { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1),                 ANYSPACE,  Unroll3BytesSwap},
3710
    { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1),     ANYSPACE,  Unroll3BytesSkip1Swap},
3711
    { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|SWAPFIRST_SH(1),  ANYSPACE,  Unroll3BytesSkip1SwapFirst},
3712
3713
    { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
3714
                                                               ANYSPACE,  Unroll3BytesSkip1SwapSwapFirst},
3715
3716
    { CHANNELS_SH(4)|BYTES_SH(1),                              ANYSPACE,  Unroll4Bytes},
3717
    { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1),                 ANYSPACE,  Unroll4BytesReverse},
3718
    { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1),              ANYSPACE,  Unroll4BytesSwapFirst},
3719
    { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1),                 ANYSPACE,  Unroll4BytesSwap},
3720
    { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE,  Unroll4BytesSwapSwapFirst},
3721
3722
    { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYPREMUL|
3723
                                   ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarBytes},
3724
3725
    { BYTES_SH(1),    ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYPREMUL|
3726
                                           ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollChunkyBytes},
3727
3728
    { CHANNELS_SH(1)|BYTES_SH(2),                              ANYSPACE,  Unroll1Word},
3729
    { CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1),                 ANYSPACE,  Unroll1WordReversed},
3730
    { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(3),                  ANYSPACE,  Unroll1WordSkip3},
3731
3732
    { CHANNELS_SH(2)|BYTES_SH(2),                              ANYSPACE,  Unroll2Words},
3733
    { CHANNELS_SH(3)|BYTES_SH(2),                              ANYSPACE,  Unroll3Words},
3734
    { CHANNELS_SH(4)|BYTES_SH(2),                              ANYSPACE,  Unroll4Words},
3735
3736
    { CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1),                 ANYSPACE,  Unroll3WordsSwap},
3737
    { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1),  ANYSPACE,  Unroll3WordsSkip1SwapFirst},
3738
    { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1),     ANYSPACE,  Unroll3WordsSkip1Swap},
3739
    { CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1),                 ANYSPACE,  Unroll4WordsReverse},
3740
    { CHANNELS_SH(4)|BYTES_SH(2)|SWAPFIRST_SH(1),              ANYSPACE,  Unroll4WordsSwapFirst},
3741
    { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1),                 ANYSPACE,  Unroll4WordsSwap},
3742
    { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE,  Unroll4WordsSwapSwapFirst},
3743
3744
3745
    { BYTES_SH(2)|PLANAR_SH(1),  ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE,  UnrollPlanarWords},
3746
    { BYTES_SH(2),  ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE,  UnrollAnyWords},
3747
3748
    { BYTES_SH(2)|PLANAR_SH(1),  ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE|PREMUL_SH(1),  UnrollPlanarWordsPremul},
3749
    { BYTES_SH(2),  ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE|PREMUL_SH(1),  UnrollAnyWordsPremul}
3750
3751
};
3752
3753
3754
3755
static const cmsFormattersFloat InputFormattersFloat[] = {
3756
3757
    //    Type                                          Mask                  Function
3758
    //  ----------------------------   ------------------------------------  ----------------------------
3759
    {     TYPE_Lab_DBL,                                ANYPLANAR|ANYEXTRA,   UnrollLabDoubleToFloat},
3760
    {     TYPE_Lab_FLT,                                ANYPLANAR|ANYEXTRA,   UnrollLabFloatToFloat},
3761
3762
    {     TYPE_XYZ_DBL,                                ANYPLANAR|ANYEXTRA,   UnrollXYZDoubleToFloat},
3763
    {     TYPE_XYZ_FLT,                                ANYPLANAR|ANYEXTRA,   UnrollXYZFloatToFloat},
3764
3765
    {     FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
3766
                                            ANYPREMUL|ANYCHANNELS|ANYSPACE,  UnrollFloatsToFloat},
3767
3768
    {     FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
3769
                                              ANYCHANNELS|ANYSPACE|ANYPREMUL, UnrollDoublesToFloat},
3770
3771
    {     TYPE_LabV2_8,                                                   0,  UnrollLabV2_8ToFloat },
3772
    {     TYPE_ALabV2_8,                                                  0,  UnrollALabV2_8ToFloat },
3773
    {     TYPE_LabV2_16,                                                  0,  UnrollLabV2_16ToFloat },
3774
3775
    {     BYTES_SH(1),              ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
3776
                                                        ANYCHANNELS|ANYSPACE, Unroll8ToFloat},
3777
3778
    {     BYTES_SH(2),              ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
3779
                                                        ANYCHANNELS|ANYSPACE, Unroll16ToFloat},
3780
#ifndef CMS_NO_HALF_SUPPORT
3781
    {     FLOAT_SH(1)|BYTES_SH(2), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
3782
                                                        ANYCHANNELS|ANYSPACE, UnrollHalfToFloat},
3783
#endif
3784
};
3785
3786
3787
// Bit fields set to one in the mask are not compared
3788
static
3789
cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags)
3790
9
{
3791
9
    cmsUInt32Number i;
3792
9
    cmsFormatter fr;
3793
3794
9
    switch (dwFlags) {
3795
3796
3
    case CMS_PACK_FLAGS_16BITS: {
3797
87
        for (i=0; i < sizeof(InputFormatters16) / sizeof(cmsFormatters16); i++) {
3798
87
            const cmsFormatters16* f = InputFormatters16 + i;
3799
3800
87
            if ((dwInput & ~f ->Mask) == f ->Type) {
3801
3
                fr.Fmt16 = f ->Frm;
3802
3
                return fr;
3803
3
            }
3804
87
        }
3805
3
    }
3806
0
    break;
3807
3808
6
    case CMS_PACK_FLAGS_FLOAT: {
3809
66
        for (i=0; i < sizeof(InputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {
3810
66
            const cmsFormattersFloat* f = InputFormattersFloat + i;
3811
3812
66
            if ((dwInput & ~f ->Mask) == f ->Type) {
3813
6
                fr.FmtFloat = f ->Frm;
3814
6
                return fr;
3815
6
            }
3816
66
        }
3817
6
    }
3818
0
    break;
3819
3820
0
    default:;
3821
3822
9
    }
3823
3824
0
    fr.Fmt16 = NULL;
3825
0
    return fr;
3826
9
}
3827
3828
static const cmsFormatters16 OutputFormatters16[] = {
3829
    //    Type                                          Mask                  Function
3830
    //  ----------------------------   ------------------------------------  ----------------------------
3831
3832
    { TYPE_Lab_DBL,                                      ANYPLANAR|ANYEXTRA,  PackLabDoubleFrom16},
3833
    { TYPE_XYZ_DBL,                                      ANYPLANAR|ANYEXTRA,  PackXYZDoubleFrom16},
3834
3835
    { TYPE_Lab_FLT,                                      ANYPLANAR|ANYEXTRA,  PackLabFloatFrom16},
3836
    { TYPE_XYZ_FLT,                                      ANYPLANAR|ANYEXTRA,  PackXYZFloatFrom16},
3837
3838
    { FLOAT_SH(1)|BYTES_SH(0),      ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|
3839
                                    ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE,  PackDoubleFrom16},
3840
    { FLOAT_SH(1)|BYTES_SH(4),      ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|
3841
                                    ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE,  PackFloatFrom16},
3842
#ifndef CMS_NO_HALF_SUPPORT
3843
    { FLOAT_SH(1)|BYTES_SH(2),      ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|
3844
                                    ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE,  PackHalfFrom16},
3845
#endif
3846
3847
    { CHANNELS_SH(1)|BYTES_SH(1),                                  ANYSPACE,  Pack1Byte},
3848
    { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1),                      ANYSPACE,  Pack1ByteSkip1},
3849
    { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1),      ANYSPACE,  Pack1ByteSkip1SwapFirst},
3850
3851
    { CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1),                     ANYSPACE,  Pack1ByteReversed},
3852
3853
    { TYPE_LabV2_8,                                                       0,  PackLabV2_8 },
3854
    { TYPE_ALabV2_8,                                                      0,  PackALabV2_8 },
3855
    { TYPE_LabV2_16,                                                      0,  PackLabV2_16 },
3856
3857
    { CHANNELS_SH(3)|BYTES_SH(1)|OPTIMIZED_SH(1),                  ANYSPACE,  Pack3BytesOptimized},
3858
    { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1),      ANYSPACE,  Pack3BytesAndSkip1Optimized},
3859
    { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1),
3860
                                                                   ANYSPACE,  Pack3BytesAndSkip1SwapFirstOptimized},
3861
    { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1),
3862
                                                                   ANYSPACE,  Pack3BytesAndSkip1SwapSwapFirstOptimized},
3863
    { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1),
3864
                                                                   ANYSPACE,  Pack3BytesAndSkip1SwapOptimized},
3865
    { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|OPTIMIZED_SH(1),     ANYSPACE,  Pack3BytesSwapOptimized},
3866
3867
3868
3869
    { CHANNELS_SH(3)|BYTES_SH(1),                                  ANYSPACE,  Pack3Bytes},
3870
    { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1),                      ANYSPACE,  Pack3BytesAndSkip1},
3871
    { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1),      ANYSPACE,  Pack3BytesAndSkip1SwapFirst},
3872
    { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
3873
                                                                   ANYSPACE,  Pack3BytesAndSkip1SwapSwapFirst},
3874
    { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1),         ANYSPACE,  Pack3BytesAndSkip1Swap},
3875
    { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1),                     ANYSPACE,  Pack3BytesSwap},
3876
    { CHANNELS_SH(4)|BYTES_SH(1),                                  ANYSPACE,  Pack4Bytes},
3877
    { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1),                     ANYSPACE,  Pack4BytesReverse},
3878
    { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1),                  ANYSPACE,  Pack4BytesSwapFirst},
3879
    { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1),                     ANYSPACE,  Pack4BytesSwap},
3880
    { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),     ANYSPACE,  Pack4BytesSwapSwapFirst},
3881
    { CHANNELS_SH(6)|BYTES_SH(1),                                  ANYSPACE,  Pack6Bytes},
3882
    { CHANNELS_SH(6)|BYTES_SH(1)|DOSWAP_SH(1),                     ANYSPACE,  Pack6BytesSwap},
3883
3884
    { BYTES_SH(1),    ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|
3885
                                                          ANYSPACE|ANYPREMUL, PackChunkyBytes},
3886
3887
    { BYTES_SH(1)|PLANAR_SH(1),    ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
3888
                                              ANYCHANNELS|ANYSPACE|ANYPREMUL, PackPlanarBytes},
3889
3890
3891
    { CHANNELS_SH(1)|BYTES_SH(2),                                  ANYSPACE,  Pack1Word},
3892
    { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1),                      ANYSPACE,  Pack1WordSkip1},
3893
    { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1),      ANYSPACE,  Pack1WordSkip1SwapFirst},
3894
    { CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1),                     ANYSPACE,  Pack1WordReversed},
3895
    { CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1),                   ANYSPACE,  Pack1WordBigEndian},
3896
    { CHANNELS_SH(3)|BYTES_SH(2),                                  ANYSPACE,  Pack3Words},
3897
    { CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1),                     ANYSPACE,  Pack3WordsSwap},
3898
    { CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1),                   ANYSPACE,  Pack3WordsBigEndian},
3899
    { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1),                      ANYSPACE,  Pack3WordsAndSkip1},
3900
    { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1),         ANYSPACE,  Pack3WordsAndSkip1Swap},
3901
    { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1),      ANYSPACE,  Pack3WordsAndSkip1SwapFirst},
3902
3903
    { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
3904
                                                                   ANYSPACE,  Pack3WordsAndSkip1SwapSwapFirst},
3905
3906
    { CHANNELS_SH(4)|BYTES_SH(2),                                  ANYSPACE,  Pack4Words},
3907
    { CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1),                     ANYSPACE,  Pack4WordsReverse},
3908
    { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1),                     ANYSPACE,  Pack4WordsSwap},
3909
    { CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1),                   ANYSPACE,  Pack4WordsBigEndian},
3910
3911
    { CHANNELS_SH(6)|BYTES_SH(2),                                  ANYSPACE,  Pack6Words},
3912
    { CHANNELS_SH(6)|BYTES_SH(2)|DOSWAP_SH(1),                     ANYSPACE,  Pack6WordsSwap},
3913
3914
    { BYTES_SH(2),                  ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|
3915
                                     ANYEXTRA|ANYCHANNELS|ANYSPACE|ANYPREMUL, PackChunkyWords},
3916
    { BYTES_SH(2)|PLANAR_SH(1),     ANYFLAVOR|ANYENDIAN|ANYSWAP|ANYEXTRA|
3917
                                     ANYCHANNELS|ANYSPACE|ANYPREMUL,          PackPlanarWords}
3918
3919
};
3920
3921
3922
static const cmsFormattersFloat OutputFormattersFloat[] = {
3923
    //    Type                                          Mask                                 Function
3924
    //  ----------------------------   ---------------------------------------------------  ----------------------------
3925
    {     TYPE_Lab_FLT,                                                ANYPLANAR|ANYEXTRA,   PackLabFloatFromFloat},
3926
    {     TYPE_XYZ_FLT,                                                ANYPLANAR|ANYEXTRA,   PackXYZFloatFromFloat},
3927
3928
    {     TYPE_Lab_DBL,                                                ANYPLANAR|ANYEXTRA,   PackLabDoubleFromFloat},
3929
    {     TYPE_XYZ_DBL,                                                ANYPLANAR|ANYEXTRA,   PackXYZDoubleFromFloat},
3930
3931
    {     TYPE_LabV2_8,                                                ANYPLANAR|ANYEXTRA,   PackEncodedBytesLabV2FromFloat},
3932
    {     TYPE_LabV2_16,                                               ANYPLANAR|ANYEXTRA,   PackEncodedWordsLabV2FromFloat},
3933
3934
    {     FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR|
3935
                             ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE,   PackFloatsFromFloat },
3936
    {     FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR|
3937
                             ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE,   PackDoublesFromFloat },
3938
3939
    {     BYTES_SH(2), ANYPLANAR|
3940
                             ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE,   PackWordsFromFloat },
3941
3942
    {     BYTES_SH(1), ANYPLANAR|
3943
                             ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE,   PackBytesFromFloat },
3944
3945
#ifndef CMS_NO_HALF_SUPPORT
3946
    {     FLOAT_SH(1)|BYTES_SH(2),
3947
                             ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE,   PackHalfFromFloat },
3948
#endif
3949
3950
};
3951
3952
3953
// Bit fields set to one in the mask are not compared
3954
static
3955
cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags)
3956
9
{
3957
9
    cmsUInt32Number i;
3958
9
    cmsFormatter fr;
3959
3960
    // Optimization is only a hint
3961
9
    dwInput &= ~OPTIMIZED_SH(1);
3962
3963
9
    switch (dwFlags)
3964
9
    {
3965
3966
3
     case CMS_PACK_FLAGS_16BITS: {
3967
3968
123
        for (i=0; i < sizeof(OutputFormatters16) / sizeof(cmsFormatters16); i++) {
3969
123
            const cmsFormatters16* f = OutputFormatters16 + i;
3970
3971
123
            if ((dwInput & ~f ->Mask) == f ->Type) {
3972
3
                fr.Fmt16 = f ->Frm;
3973
3
                return fr;
3974
3
            }
3975
123
        }
3976
3
        }
3977
0
        break;
3978
3979
6
    case CMS_PACK_FLAGS_FLOAT: {
3980
3981
18
        for (i=0; i < sizeof(OutputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {
3982
18
            const cmsFormattersFloat* f = OutputFormattersFloat + i;
3983
3984
18
            if ((dwInput & ~f ->Mask) == f ->Type) {
3985
6
                fr.FmtFloat = f ->Frm;
3986
6
                return fr;
3987
6
            }
3988
18
        }
3989
6
        }
3990
0
        break;
3991
3992
0
    default:;
3993
3994
9
    }
3995
3996
0
    fr.Fmt16 = NULL;
3997
0
    return fr;
3998
9
}
3999
4000
4001
typedef struct _cms_formatters_factory_list {
4002
4003
    cmsFormatterFactory Factory;
4004
    struct _cms_formatters_factory_list *Next;
4005
4006
} cmsFormattersFactoryList;
4007
4008
_cmsFormattersPluginChunkType _cmsFormattersPluginChunk = { NULL };
4009
4010
4011
// Duplicates the zone of memory used by the plug-in in the new context
4012
static
4013
void DupFormatterFactoryList(struct _cmsContext_struct* ctx,
4014
                                               const struct _cmsContext_struct* src)
4015
0
{
4016
0
   _cmsFormattersPluginChunkType newHead = { NULL };
4017
0
   cmsFormattersFactoryList*  entry;
4018
0
   cmsFormattersFactoryList*  Anterior = NULL;
4019
0
   _cmsFormattersPluginChunkType* head = (_cmsFormattersPluginChunkType*) src->chunks[FormattersPlugin];
4020
4021
0
     _cmsAssert(head != NULL);
4022
4023
   // Walk the list copying all nodes
4024
0
   for (entry = head->FactoryList;
4025
0
       entry != NULL;
4026
0
       entry = entry ->Next) {
4027
4028
0
           cmsFormattersFactoryList *newEntry = ( cmsFormattersFactoryList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(cmsFormattersFactoryList));
4029
4030
0
           if (newEntry == NULL)
4031
0
               return;
4032
4033
           // We want to keep the linked list order, so this is a little bit tricky
4034
0
           newEntry -> Next = NULL;
4035
0
           if (Anterior)
4036
0
               Anterior -> Next = newEntry;
4037
4038
0
           Anterior = newEntry;
4039
4040
0
           if (newHead.FactoryList == NULL)
4041
0
               newHead.FactoryList = newEntry;
4042
0
   }
4043
4044
0
   ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsFormattersPluginChunkType));
4045
0
}
4046
4047
// The interpolation plug-in memory chunk allocator/dup
4048
void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx,
4049
                                    const struct _cmsContext_struct* src)
4050
29
{
4051
29
      _cmsAssert(ctx != NULL);
4052
4053
29
     if (src != NULL) {
4054
4055
         // Duplicate the LIST
4056
0
         DupFormatterFactoryList(ctx, src);
4057
0
     }
4058
29
     else {
4059
29
          static _cmsFormattersPluginChunkType FormattersPluginChunk = { NULL };
4060
29
          ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx ->MemPool, &FormattersPluginChunk, sizeof(_cmsFormattersPluginChunkType));
4061
29
     }
4062
29
}
4063
4064
4065
4066
// Formatters management
4067
cmsBool  _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Data)
4068
29
{
4069
29
    _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);
4070
29
    cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data;
4071
29
    cmsFormattersFactoryList* fl ;
4072
4073
    // Reset to built-in defaults
4074
29
    if (Data == NULL) {
4075
4076
29
          ctx ->FactoryList = NULL;
4077
29
          return TRUE;
4078
29
    }
4079
4080
0
    fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(ContextID, sizeof(cmsFormattersFactoryList));
4081
0
    if (fl == NULL) return FALSE;
4082
4083
0
    fl ->Factory    = Plugin ->FormattersFactory;
4084
4085
0
    fl ->Next = ctx -> FactoryList;
4086
0
    ctx ->FactoryList = fl;
4087
4088
0
    return TRUE;
4089
0
}
4090
4091
cmsFormatter CMSEXPORT _cmsGetFormatter(cmsContext ContextID,
4092
                                        cmsUInt32Number Type,         // Specific type, i.e. TYPE_RGB_8
4093
                                        cmsFormatterDirection Dir,
4094
                                        cmsUInt32Number dwFlags)
4095
18
{
4096
18
    _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);
4097
18
    cmsFormattersFactoryList* f;
4098
4099
18
    if (T_CHANNELS(Type) == 0) {
4100
0
        static const cmsFormatter nullFormatter = { 0 };
4101
0
        return nullFormatter;
4102
0
    }
4103
4104
18
    for (f =ctx->FactoryList; f != NULL; f = f ->Next) {
4105
4106
0
        cmsFormatter fn = f ->Factory(ContextID, Type, Dir, dwFlags);
4107
0
        if (fn.Fmt16 != NULL) return fn;
4108
0
    }
4109
4110
    // Revert to default
4111
18
    if (Dir == cmsFormatterInput)
4112
9
        return _cmsGetStockInputFormatter(Type, dwFlags);
4113
9
    else
4114
9
        return _cmsGetStockOutputFormatter(Type, dwFlags);
4115
18
}
4116
4117
4118
// Return whatever given formatter refers to float values
4119
cmsBool  _cmsFormatterIsFloat(cmsUInt32Number Type)
4120
54
{
4121
54
    return T_FLOAT(Type) ? TRUE : FALSE;
4122
54
}
4123
4124
// Return whatever given formatter refers to 8 bits
4125
cmsBool  _cmsFormatterIs8bit(cmsUInt32Number Type)
4126
0
{
4127
0
    cmsUInt32Number Bytes = T_BYTES(Type);
4128
4129
0
    return (Bytes == 1);
4130
0
}
4131
4132
// Build a suitable formatter for the colorspace of this profile
4133
cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsContext ContextID, cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat)
4134
6
{
4135
4136
6
    cmsColorSpaceSignature ColorSpace      = cmsGetColorSpace(ContextID, hProfile);
4137
6
    cmsUInt32Number        ColorSpaceBits  = (cmsUInt32Number) _cmsLCMScolorSpace(ContextID, ColorSpace);
4138
6
    cmsInt32Number         nOutputChans    = cmsChannelsOfColorSpace(ContextID, ColorSpace);
4139
6
    cmsUInt32Number        Float           = lIsFloat ? 1U : 0;
4140
4141
    // Unsupported color space?
4142
6
    if (nOutputChans < 0) return 0;
4143
4144
    // Create a fake formatter for result
4145
6
    return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
4146
6
}
4147
4148
// Build a suitable formatter for the colorspace of this profile
4149
cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsContext ContextID, cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat)
4150
0
{
4151
4152
0
    cmsColorSpaceSignature ColorSpace = cmsGetPCS(ContextID, hProfile);
4153
4154
0
    cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ContextID, ColorSpace);
4155
0
    cmsUInt32Number nOutputChans = cmsChannelsOfColorSpace(ContextID, ColorSpace);
4156
0
    cmsUInt32Number Float = lIsFloat ? 1U : 0;
4157
4158
    // Unsupported color space?
4159
0
    if (nOutputChans < 0) return 0;
4160
4161
    // Create a fake formatter for result
4162
0
    return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
4163
0
}