Coverage Report

Created: 2026-07-24 07:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/lcms2mt/src/cmspack.c
Line
Count
Source
1
//---------------------------------------------------------------------------------
2
//
3
//  Little Color Management System
4
//  Copyright (c) 1998-2026 Marti Maria Saguer
5
//
6
// Permission is hereby granted, free of charge, to any person obtaining
7
// a copy of this software and associated documentation files (the "Software"),
8
// to deal in the Software without restriction, including without limitation
9
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
// and/or sell copies of the Software, and to permit persons to whom the Software
11
// is furnished to do so, subject to the following conditions:
12
//
13
// The above copyright notice and this permission notice shall be included in
14
// all copies or substantial portions of the Software.
15
//
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
//
24
//---------------------------------------------------------------------------------
25
//
26
27
#include "lcms2_internal.h"
28
29
// 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
107M
{
171
107M
    cmsUInt32Number nChan     = T_CHANNELS(info -> InputFormat);
172
107M
    cmsUInt32Number DoSwap    = T_DOSWAP(info ->InputFormat);
173
107M
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->InputFormat);
174
107M
    cmsUInt32Number Reverse   = T_FLAVOR(info ->InputFormat);
175
107M
    cmsUInt32Number i;
176
107M
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
177
107M
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
178
107M
    cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
179
107M
    cmsUInt8Number* Init = accum;
180
107M
    cmsUInt32Number alpha_factor = 1;
181
182
107M
    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
107M
    else
191
107M
    {
192
107M
        if (Premul && Extra)
193
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[nChan * Stride]));
194
107M
    }
195
196
444M
    for (i=0; i < nChan; i++) {
197
198
336M
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
199
336M
        cmsUInt32Number v = FROM_8_TO_16(*accum);
200
201
336M
        v = Reverse ? REVERSE_FLAVOR_16(v) : v;
202
203
336M
        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
336M
        wIn[index] = (cmsUInt16Number) v;
210
336M
        accum += Stride;
211
336M
    }
212
213
107M
    return (Init + 1);
214
107M
}
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
35.3M
{
316
35.3M
    wIn[0] = FROM_8_TO_16(*accum); accum++;     // R
317
35.3M
    wIn[1] = FROM_8_TO_16(*accum); accum++;     // G
318
35.3M
    wIn[2] = FROM_8_TO_16(*accum); accum++;     // B
319
320
35.3M
    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 ? ((cmsUInt16Number*)accum)[0] : ((cmsUInt16Number*)accum)[nChan]);
603
0
   cmsUInt32Number alpha_factor = _cmsToFixedDomain(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 ? ((cmsUInt16Number*)accum)[0] : ((cmsUInt16Number*)accum)[nChan * Stride / 2]);
690
0
    cmsUInt32Number alpha_factor = _cmsToFixedDomain(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
1.83M
{
816
1.83M
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2;  // C R
817
1.83M
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2;  // M G
818
1.83M
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2;  // Y B
819
820
1.83M
    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
cmsINLINE cmsUInt32Number PixelSize(cmsUInt32Number Format)
1123
15.9M
{
1124
15.9M
    cmsUInt32Number fmt_bytes = T_BYTES(Format);
1125
1126
    // For double, the T_BYTES field is zero
1127
15.9M
    if (fmt_bytes == 0)
1128
0
        return sizeof(cmsUInt64Number);
1129
1130
    // Otherwise, it is already correct for all formats
1131
15.9M
    return fmt_bytes;
1132
15.9M
}
1133
1134
// Inks does come in percentage, remaining cases are between 0..1.0, again to 16 bits
1135
static
1136
cmsUInt8Number* UnrollDoubleTo16(cmsContext ContextID,
1137
                                 CMSREGISTER _cmsTRANSFORM* info,
1138
                                 CMSREGISTER cmsUInt16Number wIn[],
1139
                                 CMSREGISTER cmsUInt8Number* accum,
1140
                                 CMSREGISTER cmsUInt32Number Stride)
1141
0
{
1142
1143
0
    cmsUInt32Number nChan      = T_CHANNELS(info -> InputFormat);
1144
0
    cmsUInt32Number DoSwap     = T_DOSWAP(info ->InputFormat);
1145
0
    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
1146
0
    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
1147
0
    cmsUInt32Number Extra      = T_EXTRA(info -> InputFormat);
1148
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1149
0
    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
1150
0
    cmsFloat64Number v;
1151
0
    cmsUInt16Number  vi;
1152
0
    cmsUInt32Number i, start = 0;
1153
0
    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
1154
1155
1156
0
    Stride /= PixelSize(info->InputFormat);
1157
1158
0
    if (ExtraFirst)
1159
0
            start = Extra;
1160
1161
0
    for (i=0; i < nChan; i++) {
1162
1163
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1164
1165
0
        if (Planar)
1166
0
            v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[(i + start) * Stride];
1167
0
        else
1168
0
            v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[i + start];
1169
1170
0
        vi = _cmsQuickSaturateWord(v * maximum);
1171
1172
0
        if (Reverse)
1173
0
            vi = REVERSE_FLAVOR_16(vi);
1174
1175
0
        wIn[index] = vi;
1176
0
    }
1177
1178
1179
0
    if (Extra == 0 && SwapFirst) {
1180
0
        cmsUInt16Number tmp = wIn[0];
1181
1182
0
        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
1183
0
        wIn[nChan-1] = tmp;
1184
0
    }
1185
1186
0
    if (T_PLANAR(info -> InputFormat))
1187
0
        return accum + sizeof(cmsFloat64Number);
1188
0
    else
1189
0
        return accum + (nChan + Extra) * sizeof(cmsFloat64Number);
1190
0
}
1191
1192
1193
1194
static
1195
cmsUInt8Number* UnrollFloatTo16(cmsContext ContextID,
1196
                                CMSREGISTER _cmsTRANSFORM* info,
1197
                                CMSREGISTER cmsUInt16Number wIn[],
1198
                                CMSREGISTER cmsUInt8Number* accum,
1199
                                CMSREGISTER cmsUInt32Number Stride)
1200
0
{
1201
1202
0
    cmsUInt32Number nChan  = T_CHANNELS(info -> InputFormat);
1203
0
    cmsUInt32Number DoSwap   = T_DOSWAP(info ->InputFormat);
1204
0
    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
1205
0
    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
1206
0
    cmsUInt32Number Extra   = T_EXTRA(info -> InputFormat);
1207
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1208
0
    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
1209
0
    cmsFloat32Number v;
1210
0
    cmsUInt16Number  vi;
1211
0
    cmsUInt32Number i, start = 0;
1212
0
    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
1213
1214
0
    Stride /= PixelSize(info->InputFormat);
1215
1216
0
    if (ExtraFirst)
1217
0
            start = Extra;
1218
1219
0
    for (i=0; i < nChan; i++) {
1220
1221
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1222
1223
0
        if (Planar)
1224
0
            v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride];
1225
0
        else
1226
0
            v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[i + start];
1227
1228
0
        vi = _cmsQuickSaturateWord(v * maximum);
1229
1230
0
        if (Reverse)
1231
0
            vi = REVERSE_FLAVOR_16(vi);
1232
1233
0
        wIn[index] = vi;
1234
0
    }
1235
1236
1237
0
    if (Extra == 0 && SwapFirst) {
1238
0
        cmsUInt16Number tmp = wIn[0];
1239
1240
0
        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
1241
0
        wIn[nChan-1] = tmp;
1242
0
    }
1243
1244
0
    if (T_PLANAR(info -> InputFormat))
1245
0
        return accum + sizeof(cmsFloat32Number);
1246
0
    else
1247
0
        return accum + (nChan + Extra) * sizeof(cmsFloat32Number);
1248
0
}
1249
1250
1251
1252
1253
// For 1 channel, we need to duplicate data (it comes in 0..1.0 range)
1254
static
1255
cmsUInt8Number* UnrollDouble1Chan(cmsContext ContextID,
1256
                                  CMSREGISTER _cmsTRANSFORM* info,
1257
                                  CMSREGISTER cmsUInt16Number wIn[],
1258
                                  CMSREGISTER cmsUInt8Number* accum,
1259
                                  CMSREGISTER cmsUInt32Number Stride)
1260
0
{
1261
0
    cmsFloat64Number* Inks = (cmsFloat64Number*) accum;
1262
1263
0
    wIn[0] = wIn[1] = wIn[2] = _cmsQuickSaturateWord(Inks[0] * 65535.0);
1264
1265
0
    return accum + sizeof(cmsFloat64Number);
1266
1267
0
    cmsUNUSED_PARAMETER(info);
1268
0
    cmsUNUSED_PARAMETER(Stride);
1269
0
}
1270
1271
//-------------------------------------------------------------------------------------------------------------------
1272
1273
// For anything going from cmsUInt8Number
1274
static
1275
cmsUInt8Number* Unroll8ToFloat(cmsContext ContextID,
1276
                               _cmsTRANSFORM* info,
1277
                               cmsFloat32Number wIn[],
1278
                               cmsUInt8Number* accum,
1279
                               cmsUInt32Number Stride)
1280
0
{
1281
1282
0
    cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
1283
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
1284
0
    cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
1285
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
1286
0
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
1287
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1288
0
    cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
1289
0
    cmsFloat32Number v;
1290
0
    cmsUInt32Number i, start = 0;
1291
1292
0
    Stride /= PixelSize(info->InputFormat);
1293
1294
0
    if (ExtraFirst)
1295
0
        start = Extra;
1296
1297
0
    for (i = 0; i < nChan; i++) {
1298
1299
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1300
1301
0
        if (Planar)
1302
0
            v = (cmsFloat32Number) ((cmsUInt8Number *)accum)[(i + start) * Stride];
1303
0
        else
1304
0
            v = (cmsFloat32Number) ((cmsUInt8Number *)accum)[i + start];
1305
1306
0
        v /= 255.0F;
1307
1308
0
        wIn[index] = Reverse ? 1 - v : v;
1309
0
    }
1310
1311
1312
0
    if (Extra == 0 && SwapFirst) {
1313
0
        cmsFloat32Number tmp = wIn[0];
1314
1315
0
        memmove(&wIn[0], &wIn[1], (nChan - 1) * sizeof(cmsFloat32Number));
1316
0
        wIn[nChan - 1] = tmp;
1317
0
    }
1318
1319
0
    if (T_PLANAR(info->InputFormat))
1320
0
        return accum + sizeof(cmsUInt8Number);
1321
0
    else
1322
0
        return accum + (nChan + Extra) * sizeof(cmsUInt8Number);
1323
0
}
1324
1325
1326
// For anything going from cmsUInt16Number
1327
static
1328
cmsUInt8Number* Unroll16ToFloat(cmsContext ContextID,
1329
                                _cmsTRANSFORM* info,
1330
                                cmsFloat32Number wIn[],
1331
                                cmsUInt8Number* accum,
1332
                                cmsUInt32Number Stride)
1333
15.9M
{
1334
1335
15.9M
    cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
1336
15.9M
    cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
1337
15.9M
    cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
1338
15.9M
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
1339
15.9M
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
1340
15.9M
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1341
15.9M
    cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
1342
15.9M
    cmsFloat32Number v;
1343
15.9M
    cmsUInt32Number i, start = 0;
1344
1345
15.9M
    Stride /= PixelSize(info->InputFormat);
1346
1347
15.9M
    if (ExtraFirst)
1348
0
        start = Extra;
1349
1350
62.1M
    for (i = 0; i < nChan; i++) {
1351
1352
46.2M
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1353
1354
46.2M
        if (Planar)
1355
0
            v = (cmsFloat32Number)((cmsUInt16Number*)accum)[(i + start) * Stride];
1356
46.2M
        else
1357
46.2M
            v = (cmsFloat32Number)((cmsUInt16Number*)accum)[i + start];
1358
1359
46.2M
        v /= 65535.0F;
1360
1361
46.2M
        wIn[index] = Reverse ? 1 - v : v;
1362
46.2M
    }
1363
1364
1365
15.9M
    if (Extra == 0 && SwapFirst) {
1366
0
        cmsFloat32Number tmp = wIn[0];
1367
1368
0
        memmove(&wIn[0], &wIn[1], (nChan - 1) * sizeof(cmsFloat32Number));
1369
0
        wIn[nChan - 1] = tmp;
1370
0
    }
1371
1372
15.9M
    if (T_PLANAR(info->InputFormat))
1373
0
        return accum + sizeof(cmsUInt16Number);
1374
15.9M
    else
1375
15.9M
        return accum + (nChan + Extra) * sizeof(cmsUInt16Number);
1376
15.9M
}
1377
1378
1379
// For anything going from cmsFloat32Number
1380
static
1381
cmsUInt8Number* UnrollFloatsToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
1382
                                    cmsFloat32Number wIn[],
1383
                                    cmsUInt8Number* accum,
1384
                                    cmsUInt32Number Stride)
1385
0
{
1386
1387
0
    cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
1388
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
1389
0
    cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
1390
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
1391
0
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
1392
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1393
0
    cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
1394
0
    cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
1395
0
    cmsFloat32Number v;
1396
0
    cmsUInt32Number i, start = 0;
1397
0
    cmsFloat32Number maximum = IsInkSpace(info->InputFormat) ? 100.0F : 1.0F;
1398
0
    cmsFloat32Number alpha_factor = 1.0f;
1399
0
    cmsFloat32Number* ptr = (cmsFloat32Number*)accum;
1400
1401
0
    Stride /= PixelSize(info->InputFormat);
1402
1403
0
    if (Premul && Extra)
1404
0
    {
1405
0
        if (Planar)
1406
0
            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan * Stride]) / maximum;
1407
0
        else
1408
0
            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
1409
0
    }
1410
1411
0
    if (ExtraFirst)
1412
0
            start = Extra;
1413
1414
0
    for (i=0; i < nChan; i++) {
1415
1416
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1417
1418
0
        if (Planar)
1419
0
            v = ptr[(i + start) * Stride];
1420
0
        else
1421
0
            v = ptr[i + start];
1422
1423
0
        if (Premul && alpha_factor > 0)
1424
0
            v /= alpha_factor;
1425
1426
0
        v /= maximum;
1427
1428
0
        wIn[index] = Reverse ? 1 - v : v;
1429
0
    }
1430
1431
1432
0
    if (Extra == 0 && SwapFirst) {
1433
0
        cmsFloat32Number tmp = wIn[0];
1434
1435
0
        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));
1436
0
        wIn[nChan-1] = tmp;
1437
0
    }
1438
1439
0
    if (T_PLANAR(info -> InputFormat))
1440
0
        return accum + sizeof(cmsFloat32Number);
1441
0
    else
1442
0
        return accum + (nChan + Extra) * sizeof(cmsFloat32Number);
1443
0
}
1444
1445
// For anything going from double
1446
1447
static
1448
cmsUInt8Number* UnrollDoublesToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
1449
                                    cmsFloat32Number wIn[],
1450
                                    cmsUInt8Number* accum,
1451
                                    cmsUInt32Number Stride)
1452
0
{
1453
1454
0
    cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
1455
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
1456
0
    cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
1457
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
1458
0
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
1459
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1460
0
    cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
1461
0
    cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
1462
0
    cmsFloat64Number v;
1463
0
    cmsUInt32Number i, start = 0;
1464
0
    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0;
1465
0
    cmsFloat64Number alpha_factor = 1.0;
1466
0
    cmsFloat64Number* ptr = (cmsFloat64Number*)accum;
1467
1468
0
    Stride /= PixelSize(info->InputFormat);
1469
1470
0
    if (Premul && Extra)
1471
0
    {
1472
0
        if (Planar)
1473
0
            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan * Stride]) / maximum;
1474
0
        else
1475
0
            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
1476
0
    }
1477
1478
0
    if (ExtraFirst)
1479
0
            start = Extra;
1480
1481
0
    for (i=0; i < nChan; i++) {
1482
1483
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1484
1485
0
        if (Planar)
1486
0
            v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[(i + start)  * Stride];
1487
0
        else
1488
0
            v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[i + start];
1489
1490
1491
0
        if (Premul && alpha_factor > 0)
1492
0
            v /= alpha_factor;
1493
1494
0
        v /= maximum;
1495
1496
0
        wIn[index] = (cmsFloat32Number) (Reverse ? 1.0 - v : v);
1497
0
    }
1498
1499
1500
0
    if (Extra == 0 && SwapFirst) {
1501
0
        cmsFloat32Number tmp = wIn[0];
1502
1503
0
        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));
1504
0
        wIn[nChan-1] = tmp;
1505
0
    }
1506
1507
0
    if (T_PLANAR(info -> InputFormat))
1508
0
        return accum + sizeof(cmsFloat64Number);
1509
0
    else
1510
0
        return accum + (nChan + Extra) * sizeof(cmsFloat64Number);
1511
0
}
1512
1513
1514
1515
// From Lab double to cmsFloat32Number
1516
static
1517
cmsUInt8Number* UnrollLabDoubleToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
1518
                                       cmsFloat32Number wIn[],
1519
                                       cmsUInt8Number* accum,
1520
                                       cmsUInt32Number Stride)
1521
1.55M
{
1522
1.55M
    cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
1523
1524
1.55M
    if (T_PLANAR(info -> InputFormat)) {
1525
1526
0
        Stride /= PixelSize(info->InputFormat);
1527
1528
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);                 // from 0..100 to 0..1
1529
0
        wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0);    // form -128..+127 to 0..1
1530
0
        wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);
1531
1532
0
        return accum + sizeof(cmsFloat64Number);
1533
0
    }
1534
1.55M
    else {
1535
1536
1.55M
        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);            // from 0..100 to 0..1
1537
1.55M
        wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0);    // form -128..+127 to 0..1
1538
1.55M
        wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);
1539
1540
1.55M
        accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat));
1541
1.55M
        return accum;
1542
1.55M
    }
1543
1.55M
}
1544
1545
// From Lab double to cmsFloat32Number
1546
static
1547
cmsUInt8Number* UnrollLabFloatToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
1548
                                      cmsFloat32Number wIn[],
1549
                                      cmsUInt8Number* accum,
1550
                                      cmsUInt32Number Stride)
1551
0
{
1552
0
    cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
1553
1554
0
    if (T_PLANAR(info -> InputFormat)) {
1555
1556
0
        Stride /= PixelSize(info->InputFormat);
1557
1558
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);                 // from 0..100 to 0..1
1559
0
        wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0);    // form -128..+127 to 0..1
1560
0
        wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);
1561
1562
0
        return accum + sizeof(cmsFloat32Number);
1563
0
    }
1564
0
    else {
1565
1566
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);            // from 0..100 to 0..1
1567
0
        wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0);    // form -128..+127 to 0..1
1568
0
        wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);
1569
1570
0
        accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat));
1571
0
        return accum;
1572
0
    }
1573
0
}
1574
1575
// 1.15 fixed point, that means maximum value is MAX_ENCODEABLE_XYZ (0xFFFF)
1576
static
1577
cmsUInt8Number* UnrollXYZDoubleToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
1578
                                       cmsFloat32Number wIn[],
1579
                                       cmsUInt8Number* accum,
1580
                                       cmsUInt32Number Stride)
1581
0
{
1582
0
    cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
1583
1584
0
    if (T_PLANAR(info -> InputFormat)) {
1585
1586
0
        Stride /= PixelSize(info->InputFormat);
1587
1588
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
1589
0
        wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);
1590
0
        wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);
1591
1592
0
        return accum + sizeof(cmsFloat64Number);
1593
0
    }
1594
0
    else {
1595
1596
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
1597
0
        wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);
1598
0
        wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);
1599
1600
0
        accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat));
1601
0
        return accum;
1602
0
    }
1603
0
}
1604
1605
static
1606
cmsUInt8Number* UnrollXYZFloatToFloat(cmsContext ContextID, _cmsTRANSFORM* info,
1607
                                      cmsFloat32Number wIn[],
1608
                                      cmsUInt8Number* accum,
1609
                                      cmsUInt32Number Stride)
1610
0
{
1611
0
    cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
1612
1613
0
    if (T_PLANAR(info -> InputFormat)) {
1614
1615
0
        Stride /= PixelSize(info->InputFormat);
1616
1617
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
1618
0
        wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);
1619
0
        wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);
1620
1621
0
        return accum + sizeof(cmsFloat32Number);
1622
0
    }
1623
0
    else {
1624
1625
0
        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
1626
0
        wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);
1627
0
        wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);
1628
1629
0
        accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat));
1630
0
        return accum;
1631
0
    }
1632
0
}
1633
1634
1635
cmsINLINE void lab4toFloat(cmsFloat32Number wIn[], cmsUInt16Number lab4[3])
1636
0
{
1637
0
    cmsFloat32Number L = (cmsFloat32Number) lab4[0] / 655.35F;
1638
0
    cmsFloat32Number a = ((cmsFloat32Number) lab4[1] / 257.0F) - 128.0F;
1639
0
    cmsFloat32Number b = ((cmsFloat32Number) lab4[2] / 257.0F) - 128.0F;
1640
1641
0
    wIn[0] = (L / 100.0F);                    // from 0..100 to 0..1
1642
0
    wIn[1] = ((a + 128.0F) / 255.0F);         // form -128..+127 to 0..1
1643
0
    wIn[2] = ((b + 128.0F) / 255.0F);
1644
1645
0
}
1646
1647
static
1648
cmsUInt8Number* UnrollLabV2_8ToFloat(cmsContext ContextID,
1649
                                      _cmsTRANSFORM* info,
1650
                                      cmsFloat32Number wIn[],
1651
                                      cmsUInt8Number* accum,
1652
                                      cmsUInt32Number Stride)
1653
0
{
1654
0
    cmsUInt16Number lab4[3];
1655
1656
0
    lab4[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // L
1657
0
    lab4[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // a
1658
0
    lab4[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // b
1659
1660
0
    lab4toFloat(wIn, lab4);
1661
1662
0
    return accum;
1663
1664
0
    cmsUNUSED_PARAMETER(info);
1665
0
    cmsUNUSED_PARAMETER(Stride);
1666
0
}
1667
1668
static
1669
cmsUInt8Number* UnrollALabV2_8ToFloat(cmsContext ContextID,
1670
                                      _cmsTRANSFORM* info,
1671
                                      cmsFloat32Number wIn[],
1672
                                      cmsUInt8Number* accum,
1673
                                      cmsUInt32Number Stride)
1674
0
{
1675
0
    cmsUInt16Number lab4[3];
1676
1677
0
    accum++;  // A
1678
0
    lab4[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // L
1679
0
    lab4[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // a
1680
0
    lab4[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // b
1681
1682
0
    lab4toFloat(wIn, lab4);
1683
1684
0
    return accum;
1685
1686
0
    cmsUNUSED_PARAMETER(info);
1687
0
    cmsUNUSED_PARAMETER(Stride);
1688
0
}
1689
1690
static
1691
cmsUInt8Number* UnrollLabV2_16ToFloat(cmsContext ContextID,
1692
                                      _cmsTRANSFORM* info,
1693
                                      cmsFloat32Number wIn[],
1694
                                      cmsUInt8Number* accum,
1695
                                      cmsUInt32Number Stride)
1696
0
{
1697
0
    cmsUInt16Number lab4[3];
1698
1699
0
    lab4[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // L
1700
0
    lab4[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // a
1701
0
    lab4[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // b
1702
1703
0
    lab4toFloat(wIn, lab4);
1704
1705
0
    return accum;
1706
1707
0
    cmsUNUSED_PARAMETER(info);
1708
0
    cmsUNUSED_PARAMETER(Stride);
1709
0
}
1710
1711
1712
// Packing routines -----------------------------------------------------------------------------------------------------------
1713
1714
1715
// Generic chunky for byte
1716
static
1717
cmsUInt8Number* PackChunkyBytes(cmsContext ContextID,
1718
                                CMSREGISTER _cmsTRANSFORM* info,
1719
                                CMSREGISTER cmsUInt16Number wOut[],
1720
                                CMSREGISTER cmsUInt8Number* output,
1721
                                CMSREGISTER cmsUInt32Number Stride)
1722
0
{
1723
0
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
1724
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
1725
0
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
1726
0
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
1727
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
1728
0
    cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
1729
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1730
0
    cmsUInt8Number* swap1;
1731
0
    cmsUInt16Number v = 0;
1732
0
    cmsUInt32Number i;
1733
0
    cmsUInt32Number alpha_factor = 0;
1734
1735
0
    swap1 = output;
1736
1737
0
    if (ExtraFirst) {
1738
1739
0
        if (Premul && Extra)
1740
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[0]));
1741
1742
0
        output += Extra;
1743
0
    }
1744
0
    else
1745
0
    {
1746
0
        if (Premul && Extra)
1747
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[nChan]));
1748
0
    }
1749
1750
0
    for (i=0; i < nChan; i++) {
1751
1752
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1753
1754
0
        v = wOut[index];
1755
1756
0
        if (Reverse)
1757
0
            v = REVERSE_FLAVOR_16(v);
1758
1759
0
        if (Premul)
1760
0
        {
1761
0
            v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
1762
0
        }
1763
1764
0
        *output++ = FROM_16_TO_8(v);
1765
0
    }
1766
1767
0
    if (!ExtraFirst) {
1768
0
        output += Extra;
1769
0
    }
1770
1771
0
    if (Extra == 0 && SwapFirst) {
1772
1773
0
        memmove(swap1 + 1, swap1, nChan-1);
1774
0
        *swap1 = FROM_16_TO_8(v);
1775
0
    }
1776
1777
0
    return output;
1778
1779
0
    cmsUNUSED_PARAMETER(Stride);
1780
0
}
1781
1782
static
1783
cmsUInt8Number* PackChunkyWords(cmsContext ContextID,
1784
                                CMSREGISTER _cmsTRANSFORM* info,
1785
                                CMSREGISTER cmsUInt16Number wOut[],
1786
                                CMSREGISTER cmsUInt8Number* output,
1787
                                CMSREGISTER cmsUInt32Number Stride)
1788
0
{
1789
0
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
1790
0
    cmsUInt32Number SwapEndian = T_ENDIAN16(info->OutputFormat);
1791
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
1792
0
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
1793
0
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
1794
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
1795
0
    cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
1796
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1797
0
    cmsUInt16Number* swap1;
1798
0
    cmsUInt16Number v = 0;
1799
0
    cmsUInt32Number i;
1800
0
    cmsUInt32Number alpha_factor = 0;
1801
1802
0
    swap1 = (cmsUInt16Number*) output;
1803
1804
0
    if (ExtraFirst) {
1805
1806
0
        if (Premul && Extra)
1807
0
            alpha_factor = _cmsToFixedDomain(*(cmsUInt16Number*) output);
1808
1809
0
        output += Extra * sizeof(cmsUInt16Number);
1810
0
    }
1811
0
    else
1812
0
    {
1813
0
        if (Premul && Extra)
1814
0
            alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*) output)[nChan]);
1815
0
    }
1816
1817
0
    for (i=0; i < nChan; i++) {
1818
1819
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1820
1821
0
        v = wOut[index];
1822
1823
0
        if (SwapEndian)
1824
0
            v = CHANGE_ENDIAN(v);
1825
1826
0
        if (Reverse)
1827
0
            v = REVERSE_FLAVOR_16(v);
1828
1829
0
        if (Premul)
1830
0
        {
1831
0
            v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
1832
0
        }
1833
1834
0
        *(cmsUInt16Number*) output = v;
1835
1836
0
        output += sizeof(cmsUInt16Number);
1837
0
    }
1838
1839
0
    if (!ExtraFirst) {
1840
0
        output += Extra * sizeof(cmsUInt16Number);
1841
0
    }
1842
1843
0
    if (Extra == 0 && SwapFirst) {
1844
1845
0
        memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number));
1846
0
        *swap1 = v;
1847
0
    }
1848
1849
0
    return output;
1850
1851
0
    cmsUNUSED_PARAMETER(Stride);
1852
0
}
1853
1854
1855
1856
static
1857
cmsUInt8Number* PackPlanarBytes(cmsContext ContextID,
1858
                                CMSREGISTER _cmsTRANSFORM* info,
1859
                                CMSREGISTER cmsUInt16Number wOut[],
1860
                                CMSREGISTER cmsUInt8Number* output,
1861
                                CMSREGISTER cmsUInt32Number Stride)
1862
107M
{
1863
107M
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
1864
107M
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
1865
107M
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
1866
107M
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
1867
107M
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
1868
107M
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1869
107M
    cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
1870
107M
    cmsUInt32Number i;
1871
107M
    cmsUInt8Number* Init = output;
1872
107M
    cmsUInt32Number alpha_factor = 0;
1873
1874
1875
107M
    if (ExtraFirst) {
1876
1877
0
        if (Premul && Extra)
1878
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[0]));
1879
1880
0
        output += Extra * Stride;
1881
0
    }
1882
107M
    else
1883
107M
    {
1884
107M
        if (Premul && Extra)
1885
0
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[nChan * Stride]));
1886
107M
    }
1887
1888
1889
445M
    for (i=0; i < nChan; i++) {
1890
1891
337M
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1892
337M
        cmsUInt16Number v = wOut[index];
1893
1894
337M
        if (Reverse)
1895
0
            v = REVERSE_FLAVOR_16(v);
1896
1897
337M
        if (Premul)
1898
0
        {
1899
0
            v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
1900
0
        }
1901
1902
337M
        *(cmsUInt8Number*)output = FROM_16_TO_8(v);
1903
1904
337M
        output += Stride;
1905
337M
    }
1906
1907
107M
    return (Init + 1);
1908
1909
0
    cmsUNUSED_PARAMETER(Stride);
1910
0
}
1911
1912
1913
static
1914
cmsUInt8Number* PackPlanarWords(cmsContext ContextID,
1915
                                CMSREGISTER _cmsTRANSFORM* info,
1916
                                CMSREGISTER cmsUInt16Number wOut[],
1917
                                CMSREGISTER cmsUInt8Number* output,
1918
                                CMSREGISTER cmsUInt32Number Stride)
1919
0
{
1920
0
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
1921
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
1922
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
1923
0
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
1924
0
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
1925
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1926
0
    cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
1927
0
    cmsUInt32Number SwapEndian = T_ENDIAN16(info->OutputFormat);
1928
0
    cmsUInt32Number i;
1929
0
    cmsUInt8Number* Init = output;
1930
0
    cmsUInt16Number v;
1931
0
    cmsUInt32Number alpha_factor = 0;
1932
1933
0
    if (ExtraFirst) {
1934
1935
0
        if (Premul && Extra)
1936
0
            alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*) output)[0]);
1937
1938
0
        output += Extra * Stride;
1939
0
    }
1940
0
    else
1941
0
    {
1942
0
        if (Premul && Extra)
1943
0
            alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*)output)[nChan * Stride]);
1944
0
    }
1945
1946
0
    for (i=0; i < nChan; i++) {
1947
1948
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1949
1950
0
        v = wOut[index];
1951
1952
0
        if (SwapEndian)
1953
0
            v = CHANGE_ENDIAN(v);
1954
1955
0
        if (Reverse)
1956
0
            v =  REVERSE_FLAVOR_16(v);
1957
1958
0
        if (Premul)
1959
0
        {
1960
0
            v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
1961
0
        }
1962
1963
0
        *(cmsUInt16Number*) output = v;
1964
0
        output += Stride;
1965
0
    }
1966
1967
0
    return (Init + sizeof(cmsUInt16Number));
1968
0
}
1969
1970
// CMYKcm (unrolled for speed)
1971
1972
static
1973
cmsUInt8Number* Pack6Bytes(cmsContext ContextID,
1974
                           CMSREGISTER _cmsTRANSFORM* info,
1975
                           CMSREGISTER cmsUInt16Number wOut[],
1976
                           CMSREGISTER cmsUInt8Number* output,
1977
                           CMSREGISTER cmsUInt32Number Stride)
1978
0
{
1979
0
    *output++ = FROM_16_TO_8(wOut[0]);
1980
0
    *output++ = FROM_16_TO_8(wOut[1]);
1981
0
    *output++ = FROM_16_TO_8(wOut[2]);
1982
0
    *output++ = FROM_16_TO_8(wOut[3]);
1983
0
    *output++ = FROM_16_TO_8(wOut[4]);
1984
0
    *output++ = FROM_16_TO_8(wOut[5]);
1985
1986
0
    return output;
1987
1988
0
    cmsUNUSED_PARAMETER(info);
1989
0
    cmsUNUSED_PARAMETER(Stride);
1990
0
}
1991
1992
// KCMYcm
1993
1994
static
1995
cmsUInt8Number* Pack6BytesSwap(cmsContext ContextID,
1996
                               CMSREGISTER _cmsTRANSFORM* info,
1997
                               CMSREGISTER cmsUInt16Number wOut[],
1998
                               CMSREGISTER cmsUInt8Number* output,
1999
                               CMSREGISTER cmsUInt32Number Stride)
2000
0
{
2001
0
    *output++ = FROM_16_TO_8(wOut[5]);
2002
0
    *output++ = FROM_16_TO_8(wOut[4]);
2003
0
    *output++ = FROM_16_TO_8(wOut[3]);
2004
0
    *output++ = FROM_16_TO_8(wOut[2]);
2005
0
    *output++ = FROM_16_TO_8(wOut[1]);
2006
0
    *output++ = FROM_16_TO_8(wOut[0]);
2007
2008
0
    return output;
2009
2010
0
    cmsUNUSED_PARAMETER(info);
2011
0
    cmsUNUSED_PARAMETER(Stride);
2012
0
}
2013
2014
// CMYKcm
2015
static
2016
cmsUInt8Number* Pack6Words(cmsContext ContextID,
2017
                           CMSREGISTER _cmsTRANSFORM* info,
2018
                           CMSREGISTER cmsUInt16Number wOut[],
2019
                           CMSREGISTER cmsUInt8Number* output,
2020
                           CMSREGISTER cmsUInt32Number Stride)
2021
0
{
2022
0
    *(cmsUInt16Number*) output = wOut[0];
2023
0
    output+= 2;
2024
0
    *(cmsUInt16Number*) output = wOut[1];
2025
0
    output+= 2;
2026
0
    *(cmsUInt16Number*) output = wOut[2];
2027
0
    output+= 2;
2028
0
    *(cmsUInt16Number*) output = wOut[3];
2029
0
    output+= 2;
2030
0
    *(cmsUInt16Number*) output = wOut[4];
2031
0
    output+= 2;
2032
0
    *(cmsUInt16Number*) output = wOut[5];
2033
0
    output+= 2;
2034
2035
0
    return output;
2036
2037
0
    cmsUNUSED_PARAMETER(info);
2038
0
    cmsUNUSED_PARAMETER(Stride);
2039
0
}
2040
2041
// KCMYcm
2042
static
2043
cmsUInt8Number* Pack6WordsSwap(cmsContext ContextID,
2044
                               CMSREGISTER _cmsTRANSFORM* info,
2045
                               CMSREGISTER cmsUInt16Number wOut[],
2046
                               CMSREGISTER cmsUInt8Number* output,
2047
                               CMSREGISTER cmsUInt32Number Stride)
2048
0
{
2049
0
    *(cmsUInt16Number*) output = wOut[5];
2050
0
    output+= 2;
2051
0
    *(cmsUInt16Number*) output = wOut[4];
2052
0
    output+= 2;
2053
0
    *(cmsUInt16Number*) output = wOut[3];
2054
0
    output+= 2;
2055
0
    *(cmsUInt16Number*) output = wOut[2];
2056
0
    output+= 2;
2057
0
    *(cmsUInt16Number*) output = wOut[1];
2058
0
    output+= 2;
2059
0
    *(cmsUInt16Number*) output = wOut[0];
2060
0
    output+= 2;
2061
2062
0
    return output;
2063
2064
0
    cmsUNUSED_PARAMETER(info);
2065
0
    cmsUNUSED_PARAMETER(Stride);
2066
0
}
2067
2068
2069
static
2070
cmsUInt8Number* Pack4Bytes(cmsContext ContextID,
2071
                           CMSREGISTER _cmsTRANSFORM* info,
2072
                           CMSREGISTER cmsUInt16Number wOut[],
2073
                           CMSREGISTER cmsUInt8Number* output,
2074
                           CMSREGISTER cmsUInt32Number Stride)
2075
0
{
2076
0
    *output++ = FROM_16_TO_8(wOut[0]);
2077
0
    *output++ = FROM_16_TO_8(wOut[1]);
2078
0
    *output++ = FROM_16_TO_8(wOut[2]);
2079
0
    *output++ = FROM_16_TO_8(wOut[3]);
2080
2081
0
    return output;
2082
2083
0
    cmsUNUSED_PARAMETER(info);
2084
0
    cmsUNUSED_PARAMETER(Stride);
2085
0
}
2086
2087
static
2088
cmsUInt8Number* Pack4BytesReverse(cmsContext ContextID,
2089
                                  CMSREGISTER _cmsTRANSFORM* info,
2090
                                  CMSREGISTER cmsUInt16Number wOut[],
2091
                                  CMSREGISTER cmsUInt8Number* output,
2092
                                  CMSREGISTER cmsUInt32Number Stride)
2093
0
{
2094
0
    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[0]));
2095
0
    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[1]));
2096
0
    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[2]));
2097
0
    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[3]));
2098
2099
0
    return output;
2100
2101
0
    cmsUNUSED_PARAMETER(info);
2102
0
    cmsUNUSED_PARAMETER(Stride);
2103
0
}
2104
2105
2106
static
2107
cmsUInt8Number* Pack4BytesSwapFirst(cmsContext ContextID,
2108
                                    CMSREGISTER _cmsTRANSFORM* info,
2109
                                    CMSREGISTER cmsUInt16Number wOut[],
2110
                                    CMSREGISTER cmsUInt8Number* output,
2111
                                    CMSREGISTER cmsUInt32Number Stride)
2112
0
{
2113
0
    *output++ = FROM_16_TO_8(wOut[3]);
2114
0
    *output++ = FROM_16_TO_8(wOut[0]);
2115
0
    *output++ = FROM_16_TO_8(wOut[1]);
2116
0
    *output++ = FROM_16_TO_8(wOut[2]);
2117
2118
0
    return output;
2119
2120
0
    cmsUNUSED_PARAMETER(info);
2121
0
    cmsUNUSED_PARAMETER(Stride);
2122
0
}
2123
2124
// ABGR
2125
static
2126
cmsUInt8Number* Pack4BytesSwap(cmsContext ContextID,
2127
                               CMSREGISTER _cmsTRANSFORM* info,
2128
                               CMSREGISTER cmsUInt16Number wOut[],
2129
                               CMSREGISTER cmsUInt8Number* output,
2130
                               CMSREGISTER cmsUInt32Number Stride)
2131
0
{
2132
0
    *output++ = FROM_16_TO_8(wOut[3]);
2133
0
    *output++ = FROM_16_TO_8(wOut[2]);
2134
0
    *output++ = FROM_16_TO_8(wOut[1]);
2135
0
    *output++ = FROM_16_TO_8(wOut[0]);
2136
2137
0
    return output;
2138
2139
0
    cmsUNUSED_PARAMETER(info);
2140
0
    cmsUNUSED_PARAMETER(Stride);
2141
0
}
2142
2143
static
2144
cmsUInt8Number* Pack4BytesSwapSwapFirst(cmsContext ContextID,
2145
                                        CMSREGISTER _cmsTRANSFORM* info,
2146
                                        CMSREGISTER cmsUInt16Number wOut[],
2147
                                        CMSREGISTER cmsUInt8Number* output,
2148
                                        CMSREGISTER cmsUInt32Number Stride)
2149
0
{
2150
0
    *output++ = FROM_16_TO_8(wOut[2]);
2151
0
    *output++ = FROM_16_TO_8(wOut[1]);
2152
0
    *output++ = FROM_16_TO_8(wOut[0]);
2153
0
    *output++ = FROM_16_TO_8(wOut[3]);
2154
2155
0
    return output;
2156
2157
0
    cmsUNUSED_PARAMETER(info);
2158
0
    cmsUNUSED_PARAMETER(Stride);
2159
0
}
2160
2161
static
2162
cmsUInt8Number* Pack4Words(cmsContext ContextID,
2163
                           CMSREGISTER _cmsTRANSFORM* info,
2164
                           CMSREGISTER cmsUInt16Number wOut[],
2165
                           CMSREGISTER cmsUInt8Number* output,
2166
                           CMSREGISTER cmsUInt32Number Stride)
2167
0
{
2168
0
    *(cmsUInt16Number*) output = wOut[0];
2169
0
    output+= 2;
2170
0
    *(cmsUInt16Number*) output = wOut[1];
2171
0
    output+= 2;
2172
0
    *(cmsUInt16Number*) output = wOut[2];
2173
0
    output+= 2;
2174
0
    *(cmsUInt16Number*) output = wOut[3];
2175
0
    output+= 2;
2176
2177
0
    return output;
2178
2179
0
    cmsUNUSED_PARAMETER(info);
2180
0
    cmsUNUSED_PARAMETER(Stride);
2181
0
}
2182
2183
static
2184
cmsUInt8Number* Pack4WordsReverse(cmsContext ContextID,
2185
                                  CMSREGISTER _cmsTRANSFORM* info,
2186
                                  CMSREGISTER cmsUInt16Number wOut[],
2187
                                  CMSREGISTER cmsUInt8Number* output,
2188
                                  CMSREGISTER cmsUInt32Number Stride)
2189
0
{
2190
0
    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]);
2191
0
    output+= 2;
2192
0
    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[1]);
2193
0
    output+= 2;
2194
0
    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[2]);
2195
0
    output+= 2;
2196
0
    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[3]);
2197
0
    output+= 2;
2198
2199
0
    return output;
2200
2201
0
    cmsUNUSED_PARAMETER(info);
2202
0
    cmsUNUSED_PARAMETER(Stride);
2203
0
}
2204
2205
// ABGR
2206
static
2207
cmsUInt8Number* Pack4WordsSwap(cmsContext ContextID,
2208
                               CMSREGISTER _cmsTRANSFORM* info,
2209
                               CMSREGISTER cmsUInt16Number wOut[],
2210
                               CMSREGISTER cmsUInt8Number* output,
2211
                               CMSREGISTER cmsUInt32Number Stride)
2212
0
{
2213
0
    *(cmsUInt16Number*) output = wOut[3];
2214
0
    output+= 2;
2215
0
    *(cmsUInt16Number*) output = wOut[2];
2216
0
    output+= 2;
2217
0
    *(cmsUInt16Number*) output = wOut[1];
2218
0
    output+= 2;
2219
0
    *(cmsUInt16Number*) output = wOut[0];
2220
0
    output+= 2;
2221
2222
0
    return output;
2223
2224
0
    cmsUNUSED_PARAMETER(info);
2225
0
    cmsUNUSED_PARAMETER(Stride);
2226
0
}
2227
2228
// CMYK
2229
static
2230
cmsUInt8Number* Pack4WordsBigEndian(cmsContext ContextID,
2231
                                    CMSREGISTER _cmsTRANSFORM* info,
2232
                                    CMSREGISTER cmsUInt16Number wOut[],
2233
                                    CMSREGISTER cmsUInt8Number* output,
2234
                                    CMSREGISTER cmsUInt32Number Stride)
2235
0
{
2236
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
2237
0
    output+= 2;
2238
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]);
2239
0
    output+= 2;
2240
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]);
2241
0
    output+= 2;
2242
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[3]);
2243
0
    output+= 2;
2244
2245
0
    return output;
2246
2247
0
    cmsUNUSED_PARAMETER(info);
2248
0
    cmsUNUSED_PARAMETER(Stride);
2249
0
}
2250
2251
2252
static
2253
cmsUInt8Number* PackLabV2_8(cmsContext ContextID,
2254
                            CMSREGISTER _cmsTRANSFORM* info,
2255
                            CMSREGISTER cmsUInt16Number wOut[],
2256
                            CMSREGISTER cmsUInt8Number* output,
2257
                            CMSREGISTER cmsUInt32Number Stride)
2258
0
{
2259
0
    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0]));
2260
0
    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1]));
2261
0
    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2]));
2262
2263
0
    return output;
2264
2265
0
    cmsUNUSED_PARAMETER(info);
2266
0
    cmsUNUSED_PARAMETER(Stride);
2267
0
}
2268
2269
static
2270
cmsUInt8Number* PackALabV2_8(cmsContext ContextID,
2271
                             CMSREGISTER _cmsTRANSFORM* info,
2272
                             CMSREGISTER cmsUInt16Number wOut[],
2273
                             CMSREGISTER cmsUInt8Number* output,
2274
                             CMSREGISTER cmsUInt32Number Stride)
2275
0
{
2276
0
    output++;
2277
0
    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0]));
2278
0
    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1]));
2279
0
    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2]));
2280
2281
0
    return output;
2282
2283
0
    cmsUNUSED_PARAMETER(info);
2284
0
    cmsUNUSED_PARAMETER(Stride);
2285
0
}
2286
2287
static
2288
cmsUInt8Number* PackLabV2_16(cmsContext ContextID,
2289
                             CMSREGISTER _cmsTRANSFORM* info,
2290
                             CMSREGISTER cmsUInt16Number wOut[],
2291
                             CMSREGISTER cmsUInt8Number* output,
2292
                             CMSREGISTER cmsUInt32Number Stride)
2293
0
{
2294
0
    *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[0]);
2295
0
    output += 2;
2296
0
    *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[1]);
2297
0
    output += 2;
2298
0
    *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[2]);
2299
0
    output += 2;
2300
2301
0
    return output;
2302
2303
0
    cmsUNUSED_PARAMETER(info);
2304
0
    cmsUNUSED_PARAMETER(Stride);
2305
0
}
2306
2307
static
2308
cmsUInt8Number* Pack3Bytes(cmsContext ContextID,
2309
                           CMSREGISTER _cmsTRANSFORM* info,
2310
                           CMSREGISTER cmsUInt16Number wOut[],
2311
                           CMSREGISTER cmsUInt8Number* output,
2312
                           CMSREGISTER cmsUInt32Number Stride)
2313
35.3M
{
2314
35.3M
    *output++ = FROM_16_TO_8(wOut[0]);
2315
35.3M
    *output++ = FROM_16_TO_8(wOut[1]);
2316
35.3M
    *output++ = FROM_16_TO_8(wOut[2]);
2317
2318
35.3M
    return output;
2319
2320
0
    cmsUNUSED_PARAMETER(info);
2321
0
    cmsUNUSED_PARAMETER(Stride);
2322
0
}
2323
2324
static
2325
cmsUInt8Number* Pack3BytesOptimized(cmsContext ContextID,
2326
                                    CMSREGISTER _cmsTRANSFORM* info,
2327
                                    CMSREGISTER cmsUInt16Number wOut[],
2328
                                    CMSREGISTER cmsUInt8Number* output,
2329
                                    CMSREGISTER cmsUInt32Number Stride)
2330
0
{
2331
0
    *output++ = (wOut[0] & 0xFFU);
2332
0
    *output++ = (wOut[1] & 0xFFU);
2333
0
    *output++ = (wOut[2] & 0xFFU);
2334
2335
0
    return output;
2336
2337
0
    cmsUNUSED_PARAMETER(info);
2338
0
    cmsUNUSED_PARAMETER(Stride);
2339
0
}
2340
2341
static
2342
cmsUInt8Number* Pack3BytesSwap(cmsContext ContextID,
2343
                               CMSREGISTER _cmsTRANSFORM* info,
2344
                               CMSREGISTER cmsUInt16Number wOut[],
2345
                               CMSREGISTER cmsUInt8Number* output,
2346
                               CMSREGISTER cmsUInt32Number Stride)
2347
0
{
2348
0
    *output++ = FROM_16_TO_8(wOut[2]);
2349
0
    *output++ = FROM_16_TO_8(wOut[1]);
2350
0
    *output++ = FROM_16_TO_8(wOut[0]);
2351
2352
0
    return output;
2353
2354
0
    cmsUNUSED_PARAMETER(info);
2355
0
    cmsUNUSED_PARAMETER(Stride);
2356
0
}
2357
2358
static
2359
cmsUInt8Number* Pack3BytesSwapOptimized(cmsContext ContextID,
2360
                                        CMSREGISTER _cmsTRANSFORM* info,
2361
                                        CMSREGISTER cmsUInt16Number wOut[],
2362
                                        CMSREGISTER cmsUInt8Number* output,
2363
                                        CMSREGISTER cmsUInt32Number Stride)
2364
0
{
2365
0
    *output++ = (wOut[2] & 0xFFU);
2366
0
    *output++ = (wOut[1] & 0xFFU);
2367
0
    *output++ = (wOut[0] & 0xFFU);
2368
2369
0
    return output;
2370
2371
0
    cmsUNUSED_PARAMETER(info);
2372
0
    cmsUNUSED_PARAMETER(Stride);
2373
0
}
2374
2375
2376
static
2377
cmsUInt8Number* Pack3Words(cmsContext ContextID,
2378
                           CMSREGISTER _cmsTRANSFORM* info,
2379
                           CMSREGISTER cmsUInt16Number wOut[],
2380
                           CMSREGISTER cmsUInt8Number* output,
2381
                           CMSREGISTER cmsUInt32Number Stride)
2382
1.83M
{
2383
1.83M
    *(cmsUInt16Number*) output = wOut[0];
2384
1.83M
    output+= 2;
2385
1.83M
    *(cmsUInt16Number*) output = wOut[1];
2386
1.83M
    output+= 2;
2387
1.83M
    *(cmsUInt16Number*) output = wOut[2];
2388
1.83M
    output+= 2;
2389
2390
1.83M
    return output;
2391
2392
0
    cmsUNUSED_PARAMETER(info);
2393
0
    cmsUNUSED_PARAMETER(Stride);
2394
0
}
2395
2396
static
2397
cmsUInt8Number* Pack3WordsSwap(cmsContext ContextID,
2398
                               CMSREGISTER _cmsTRANSFORM* info,
2399
                               CMSREGISTER cmsUInt16Number wOut[],
2400
                               CMSREGISTER cmsUInt8Number* output,
2401
                               CMSREGISTER cmsUInt32Number Stride)
2402
0
{
2403
0
    *(cmsUInt16Number*) output = wOut[2];
2404
0
    output+= 2;
2405
0
    *(cmsUInt16Number*) output = wOut[1];
2406
0
    output+= 2;
2407
0
    *(cmsUInt16Number*) output = wOut[0];
2408
0
    output+= 2;
2409
2410
0
    return output;
2411
2412
0
    cmsUNUSED_PARAMETER(info);
2413
0
    cmsUNUSED_PARAMETER(Stride);
2414
0
}
2415
2416
static
2417
cmsUInt8Number* Pack3WordsBigEndian(cmsContext ContextID,
2418
                                    CMSREGISTER _cmsTRANSFORM* info,
2419
                                    CMSREGISTER cmsUInt16Number wOut[],
2420
                                    CMSREGISTER cmsUInt8Number* output,
2421
                                    CMSREGISTER cmsUInt32Number Stride)
2422
0
{
2423
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
2424
0
    output+= 2;
2425
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]);
2426
0
    output+= 2;
2427
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]);
2428
0
    output+= 2;
2429
2430
0
    return output;
2431
2432
0
    cmsUNUSED_PARAMETER(info);
2433
0
    cmsUNUSED_PARAMETER(Stride);
2434
0
}
2435
2436
static
2437
cmsUInt8Number* Pack3BytesAndSkip1(cmsContext ContextID,
2438
                                   CMSREGISTER _cmsTRANSFORM* info,
2439
                                   CMSREGISTER cmsUInt16Number wOut[],
2440
                                   CMSREGISTER cmsUInt8Number* output,
2441
                                   CMSREGISTER cmsUInt32Number Stride)
2442
0
{
2443
0
    *output++ = FROM_16_TO_8(wOut[0]);
2444
0
    *output++ = FROM_16_TO_8(wOut[1]);
2445
0
    *output++ = FROM_16_TO_8(wOut[2]);
2446
0
    output++;
2447
2448
0
    return output;
2449
2450
0
    cmsUNUSED_PARAMETER(info);
2451
0
    cmsUNUSED_PARAMETER(Stride);
2452
0
}
2453
2454
static
2455
cmsUInt8Number* Pack3BytesAndSkip1Optimized(cmsContext ContextID,
2456
                                            CMSREGISTER _cmsTRANSFORM* info,
2457
                                            CMSREGISTER cmsUInt16Number wOut[],
2458
                                            CMSREGISTER cmsUInt8Number* output,
2459
                                            CMSREGISTER cmsUInt32Number Stride)
2460
0
{
2461
0
    *output++ = (wOut[0] & 0xFFU);
2462
0
    *output++ = (wOut[1] & 0xFFU);
2463
0
    *output++ = (wOut[2] & 0xFFU);
2464
0
    output++;
2465
2466
0
    return output;
2467
2468
0
    cmsUNUSED_PARAMETER(info);
2469
0
    cmsUNUSED_PARAMETER(Stride);
2470
0
}
2471
2472
2473
static
2474
cmsUInt8Number* Pack3BytesAndSkip1SwapFirst(cmsContext ContextID,
2475
                                            CMSREGISTER _cmsTRANSFORM* info,
2476
                                            CMSREGISTER cmsUInt16Number wOut[],
2477
                                            CMSREGISTER cmsUInt8Number* output,
2478
                                            CMSREGISTER cmsUInt32Number Stride)
2479
0
{
2480
0
    output++;
2481
0
    *output++ = FROM_16_TO_8(wOut[0]);
2482
0
    *output++ = FROM_16_TO_8(wOut[1]);
2483
0
    *output++ = FROM_16_TO_8(wOut[2]);
2484
2485
0
    return output;
2486
2487
0
    cmsUNUSED_PARAMETER(info);
2488
0
    cmsUNUSED_PARAMETER(Stride);
2489
0
}
2490
2491
static
2492
cmsUInt8Number* Pack3BytesAndSkip1SwapFirstOptimized(cmsContext ContextID,
2493
                                                     CMSREGISTER _cmsTRANSFORM* info,
2494
                                                     CMSREGISTER cmsUInt16Number wOut[],
2495
                                                     CMSREGISTER cmsUInt8Number* output,
2496
                                                     CMSREGISTER cmsUInt32Number Stride)
2497
0
{
2498
0
    output++;
2499
0
    *output++ = (wOut[0] & 0xFFU);
2500
0
    *output++ = (wOut[1] & 0xFFU);
2501
0
    *output++ = (wOut[2] & 0xFFU);
2502
2503
0
    return output;
2504
2505
0
    cmsUNUSED_PARAMETER(info);
2506
0
    cmsUNUSED_PARAMETER(Stride);
2507
0
}
2508
2509
static
2510
cmsUInt8Number* Pack3BytesAndSkip1Swap(cmsContext ContextID,
2511
                                       CMSREGISTER _cmsTRANSFORM* info,
2512
                                       CMSREGISTER cmsUInt16Number wOut[],
2513
                                       CMSREGISTER cmsUInt8Number* output,
2514
                                       CMSREGISTER cmsUInt32Number Stride)
2515
0
{
2516
0
    output++;
2517
0
    *output++ = FROM_16_TO_8(wOut[2]);
2518
0
    *output++ = FROM_16_TO_8(wOut[1]);
2519
0
    *output++ = FROM_16_TO_8(wOut[0]);
2520
2521
0
    return output;
2522
2523
0
    cmsUNUSED_PARAMETER(info);
2524
0
    cmsUNUSED_PARAMETER(Stride);
2525
0
}
2526
2527
static
2528
cmsUInt8Number* Pack3BytesAndSkip1SwapOptimized(cmsContext ContextID,
2529
                                                CMSREGISTER _cmsTRANSFORM* info,
2530
                                                CMSREGISTER cmsUInt16Number wOut[],
2531
                                                CMSREGISTER cmsUInt8Number* output,
2532
                                                CMSREGISTER cmsUInt32Number Stride)
2533
0
{
2534
0
    output++;
2535
0
    *output++ = (wOut[2] & 0xFFU);
2536
0
    *output++ = (wOut[1] & 0xFFU);
2537
0
    *output++ = (wOut[0] & 0xFFU);
2538
2539
0
    return output;
2540
2541
0
    cmsUNUSED_PARAMETER(info);
2542
0
    cmsUNUSED_PARAMETER(Stride);
2543
0
}
2544
2545
2546
static
2547
cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirst(cmsContext ContextID,
2548
                                                CMSREGISTER _cmsTRANSFORM* info,
2549
                                                CMSREGISTER cmsUInt16Number wOut[],
2550
                                                CMSREGISTER cmsUInt8Number* output,
2551
                                                CMSREGISTER cmsUInt32Number Stride)
2552
0
{
2553
0
    *output++ = FROM_16_TO_8(wOut[2]);
2554
0
    *output++ = FROM_16_TO_8(wOut[1]);
2555
0
    *output++ = FROM_16_TO_8(wOut[0]);
2556
0
    output++;
2557
2558
0
    return output;
2559
2560
0
    cmsUNUSED_PARAMETER(info);
2561
0
    cmsUNUSED_PARAMETER(Stride);
2562
0
}
2563
2564
static
2565
cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirstOptimized(cmsContext ContextID,
2566
                                                         CMSREGISTER _cmsTRANSFORM* info,
2567
                                                         CMSREGISTER cmsUInt16Number wOut[],
2568
                                                         CMSREGISTER cmsUInt8Number* output,
2569
                                                         CMSREGISTER cmsUInt32Number Stride)
2570
0
{
2571
0
    *output++ = (wOut[2] & 0xFFU);
2572
0
    *output++ = (wOut[1] & 0xFFU);
2573
0
    *output++ = (wOut[0] & 0xFFU);
2574
0
    output++;
2575
2576
0
    return output;
2577
2578
0
    cmsUNUSED_PARAMETER(info);
2579
0
    cmsUNUSED_PARAMETER(Stride);
2580
0
}
2581
2582
static
2583
cmsUInt8Number* Pack3WordsAndSkip1(cmsContext ContextID,
2584
                                   CMSREGISTER _cmsTRANSFORM* info,
2585
                                   CMSREGISTER cmsUInt16Number wOut[],
2586
                                   CMSREGISTER cmsUInt8Number* output,
2587
                                   CMSREGISTER cmsUInt32Number Stride)
2588
0
{
2589
0
    *(cmsUInt16Number*) output = wOut[0];
2590
0
    output+= 2;
2591
0
    *(cmsUInt16Number*) output = wOut[1];
2592
0
    output+= 2;
2593
0
    *(cmsUInt16Number*) output = wOut[2];
2594
0
    output+= 2;
2595
0
    output+= 2;
2596
2597
0
    return output;
2598
2599
0
    cmsUNUSED_PARAMETER(info);
2600
0
    cmsUNUSED_PARAMETER(Stride);
2601
0
}
2602
2603
static
2604
cmsUInt8Number* Pack3WordsAndSkip1Swap(cmsContext ContextID,
2605
                                       CMSREGISTER _cmsTRANSFORM* info,
2606
                                       CMSREGISTER cmsUInt16Number wOut[],
2607
                                       CMSREGISTER cmsUInt8Number* output,
2608
                                       CMSREGISTER cmsUInt32Number Stride)
2609
0
{
2610
0
    output+= 2;
2611
0
    *(cmsUInt16Number*) output = wOut[2];
2612
0
    output+= 2;
2613
0
    *(cmsUInt16Number*) output = wOut[1];
2614
0
    output+= 2;
2615
0
    *(cmsUInt16Number*) output = wOut[0];
2616
0
    output+= 2;
2617
2618
0
    return output;
2619
2620
0
    cmsUNUSED_PARAMETER(info);
2621
0
    cmsUNUSED_PARAMETER(Stride);
2622
0
}
2623
2624
2625
static
2626
cmsUInt8Number* Pack3WordsAndSkip1SwapFirst(cmsContext ContextID,
2627
                                            CMSREGISTER _cmsTRANSFORM* info,
2628
                                            CMSREGISTER cmsUInt16Number wOut[],
2629
                                            CMSREGISTER cmsUInt8Number* output,
2630
                                            CMSREGISTER cmsUInt32Number Stride)
2631
0
{
2632
0
    output+= 2;
2633
0
    *(cmsUInt16Number*) output = wOut[0];
2634
0
    output+= 2;
2635
0
    *(cmsUInt16Number*) output = wOut[1];
2636
0
    output+= 2;
2637
0
    *(cmsUInt16Number*) output = wOut[2];
2638
0
    output+= 2;
2639
2640
0
    return output;
2641
2642
0
    cmsUNUSED_PARAMETER(info);
2643
0
    cmsUNUSED_PARAMETER(Stride);
2644
0
}
2645
2646
2647
static
2648
cmsUInt8Number* Pack3WordsAndSkip1SwapSwapFirst(cmsContext ContextID,
2649
                                                CMSREGISTER _cmsTRANSFORM* info,
2650
                                                CMSREGISTER cmsUInt16Number wOut[],
2651
                                                CMSREGISTER cmsUInt8Number* output,
2652
                                                CMSREGISTER cmsUInt32Number Stride)
2653
0
{
2654
0
    *(cmsUInt16Number*) output = wOut[2];
2655
0
    output+= 2;
2656
0
    *(cmsUInt16Number*) output = wOut[1];
2657
0
    output+= 2;
2658
0
    *(cmsUInt16Number*) output = wOut[0];
2659
0
    output+= 2;
2660
0
    output+= 2;
2661
2662
0
    return output;
2663
2664
0
    cmsUNUSED_PARAMETER(info);
2665
0
    cmsUNUSED_PARAMETER(Stride);
2666
0
}
2667
2668
2669
2670
static
2671
cmsUInt8Number* Pack1Byte(cmsContext ContextID,
2672
                          CMSREGISTER _cmsTRANSFORM* info,
2673
                          CMSREGISTER cmsUInt16Number wOut[],
2674
                          CMSREGISTER cmsUInt8Number* output,
2675
                          CMSREGISTER cmsUInt32Number Stride)
2676
0
{
2677
0
    *output++ = FROM_16_TO_8(wOut[0]);
2678
2679
0
    return output;
2680
2681
0
    cmsUNUSED_PARAMETER(info);
2682
0
    cmsUNUSED_PARAMETER(Stride);
2683
0
}
2684
2685
2686
static
2687
cmsUInt8Number* Pack1ByteReversed(cmsContext ContextID,
2688
                                  CMSREGISTER _cmsTRANSFORM* info,
2689
                                  CMSREGISTER cmsUInt16Number wOut[],
2690
                                  CMSREGISTER cmsUInt8Number* output,
2691
                                  CMSREGISTER cmsUInt32Number Stride)
2692
0
{
2693
0
    *output++ = FROM_16_TO_8(REVERSE_FLAVOR_16(wOut[0]));
2694
2695
0
    return output;
2696
2697
0
    cmsUNUSED_PARAMETER(info);
2698
0
    cmsUNUSED_PARAMETER(Stride);
2699
0
}
2700
2701
2702
static
2703
cmsUInt8Number* Pack1ByteSkip1(cmsContext ContextID,
2704
                               CMSREGISTER _cmsTRANSFORM* info,
2705
                               CMSREGISTER cmsUInt16Number wOut[],
2706
                               CMSREGISTER cmsUInt8Number* output,
2707
                               CMSREGISTER cmsUInt32Number Stride)
2708
0
{
2709
0
    *output++ = FROM_16_TO_8(wOut[0]);
2710
0
    output++;
2711
2712
0
    return output;
2713
2714
0
    cmsUNUSED_PARAMETER(info);
2715
0
    cmsUNUSED_PARAMETER(Stride);
2716
0
}
2717
2718
2719
static
2720
cmsUInt8Number* Pack1ByteSkip1SwapFirst(cmsContext ContextID,
2721
                                        CMSREGISTER _cmsTRANSFORM* info,
2722
                                        CMSREGISTER cmsUInt16Number wOut[],
2723
                                        CMSREGISTER cmsUInt8Number* output,
2724
                                        CMSREGISTER cmsUInt32Number Stride)
2725
0
{
2726
0
    output++;
2727
0
    *output++ = FROM_16_TO_8(wOut[0]);
2728
2729
0
    return output;
2730
2731
0
    cmsUNUSED_PARAMETER(info);
2732
0
    cmsUNUSED_PARAMETER(Stride);
2733
0
}
2734
2735
static
2736
cmsUInt8Number* Pack1Word(cmsContext ContextID,
2737
                          CMSREGISTER _cmsTRANSFORM* info,
2738
                          CMSREGISTER cmsUInt16Number wOut[],
2739
                          CMSREGISTER cmsUInt8Number* output,
2740
                          CMSREGISTER cmsUInt32Number Stride)
2741
0
{
2742
0
    *(cmsUInt16Number*) output = wOut[0];
2743
0
    output+= 2;
2744
2745
0
    return output;
2746
2747
0
    cmsUNUSED_PARAMETER(info);
2748
0
    cmsUNUSED_PARAMETER(Stride);
2749
0
}
2750
2751
2752
static
2753
cmsUInt8Number* Pack1WordReversed(cmsContext ContextID,
2754
                                  CMSREGISTER _cmsTRANSFORM* info,
2755
                                  CMSREGISTER cmsUInt16Number wOut[],
2756
                                  CMSREGISTER cmsUInt8Number* output,
2757
                                  CMSREGISTER cmsUInt32Number Stride)
2758
0
{
2759
0
    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]);
2760
0
    output+= 2;
2761
2762
0
    return output;
2763
2764
0
    cmsUNUSED_PARAMETER(info);
2765
0
    cmsUNUSED_PARAMETER(Stride);
2766
0
}
2767
2768
static
2769
cmsUInt8Number* Pack1WordBigEndian(cmsContext ContextID,
2770
                                   CMSREGISTER _cmsTRANSFORM* info,
2771
                                   CMSREGISTER cmsUInt16Number wOut[],
2772
                                   CMSREGISTER cmsUInt8Number* output,
2773
                                   CMSREGISTER cmsUInt32Number Stride)
2774
0
{
2775
0
    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
2776
0
    output+= 2;
2777
2778
0
    return output;
2779
2780
0
    cmsUNUSED_PARAMETER(info);
2781
0
    cmsUNUSED_PARAMETER(Stride);
2782
0
}
2783
2784
2785
static
2786
cmsUInt8Number* Pack1WordSkip1(cmsContext ContextID,
2787
                               CMSREGISTER _cmsTRANSFORM* info,
2788
                               CMSREGISTER cmsUInt16Number wOut[],
2789
                               CMSREGISTER cmsUInt8Number* output,
2790
                               CMSREGISTER cmsUInt32Number Stride)
2791
0
{
2792
0
    *(cmsUInt16Number*) output = wOut[0];
2793
0
    output+= 4;
2794
2795
0
    return output;
2796
2797
0
    cmsUNUSED_PARAMETER(info);
2798
0
    cmsUNUSED_PARAMETER(Stride);
2799
0
}
2800
2801
static
2802
cmsUInt8Number* Pack1WordSkip1SwapFirst(cmsContext ContextID,
2803
                                        CMSREGISTER _cmsTRANSFORM* info,
2804
                                        CMSREGISTER cmsUInt16Number wOut[],
2805
                                        CMSREGISTER cmsUInt8Number* output,
2806
                                        CMSREGISTER cmsUInt32Number Stride)
2807
0
{
2808
0
    output += 2;
2809
0
    *(cmsUInt16Number*) output = wOut[0];
2810
0
    output+= 2;
2811
2812
0
    return output;
2813
2814
0
    cmsUNUSED_PARAMETER(info);
2815
0
    cmsUNUSED_PARAMETER(Stride);
2816
0
}
2817
2818
2819
// Unencoded Float values -- don't try optimize speed
2820
static
2821
cmsUInt8Number* PackLabDoubleFrom16(cmsContext ContextID,
2822
                                    CMSREGISTER _cmsTRANSFORM* info,
2823
                                    CMSREGISTER cmsUInt16Number wOut[],
2824
                                    CMSREGISTER cmsUInt8Number* output,
2825
                                    CMSREGISTER cmsUInt32Number Stride)
2826
0
{
2827
2828
0
    if (T_PLANAR(info -> OutputFormat)) {
2829
2830
0
        cmsCIELab  Lab;
2831
0
        cmsFloat64Number* Out = (cmsFloat64Number*) output;
2832
0
        cmsLabEncoded2Float(ContextID, &Lab, wOut);
2833
2834
0
        Out[0]        = Lab.L;
2835
0
        Out[Stride]   = Lab.a;
2836
0
        Out[Stride*2] = Lab.b;
2837
2838
0
        return output + sizeof(cmsFloat64Number);
2839
0
    }
2840
0
    else {
2841
2842
0
        cmsLabEncoded2Float(ContextID, (cmsCIELab*) output, wOut);
2843
0
        return output + (sizeof(cmsCIELab) + T_EXTRA(info ->OutputFormat) * sizeof(cmsFloat64Number));
2844
0
    }
2845
0
}
2846
2847
2848
static
2849
cmsUInt8Number* PackLabFloatFrom16(cmsContext ContextID,
2850
                                   CMSREGISTER _cmsTRANSFORM* info,
2851
                                   CMSREGISTER cmsUInt16Number wOut[],
2852
                                   CMSREGISTER cmsUInt8Number* output,
2853
                                   CMSREGISTER cmsUInt32Number Stride)
2854
0
{
2855
0
    cmsCIELab  Lab;
2856
0
    cmsLabEncoded2Float(ContextID, &Lab, wOut);
2857
2858
0
    if (T_PLANAR(info -> OutputFormat)) {
2859
2860
0
        cmsFloat32Number* Out = (cmsFloat32Number*) output;
2861
2862
0
        Stride /= PixelSize(info->OutputFormat);
2863
2864
0
        Out[0]        = (cmsFloat32Number)Lab.L;
2865
0
        Out[Stride]   = (cmsFloat32Number)Lab.a;
2866
0
        Out[Stride*2] = (cmsFloat32Number)Lab.b;
2867
2868
0
        return output + sizeof(cmsFloat32Number);
2869
0
    }
2870
0
    else {
2871
2872
0
       ((cmsFloat32Number*) output)[0] = (cmsFloat32Number) Lab.L;
2873
0
       ((cmsFloat32Number*) output)[1] = (cmsFloat32Number) Lab.a;
2874
0
       ((cmsFloat32Number*) output)[2] = (cmsFloat32Number) Lab.b;
2875
2876
0
        return output + (3 + T_EXTRA(info ->OutputFormat)) * sizeof(cmsFloat32Number);
2877
0
    }
2878
0
}
2879
2880
static
2881
cmsUInt8Number* PackXYZDoubleFrom16(cmsContext ContextID,
2882
                                    CMSREGISTER _cmsTRANSFORM* Info,
2883
                                    CMSREGISTER cmsUInt16Number wOut[],
2884
                                    CMSREGISTER cmsUInt8Number* output,
2885
                                    CMSREGISTER cmsUInt32Number Stride)
2886
0
{
2887
0
    if (T_PLANAR(Info -> OutputFormat)) {
2888
2889
0
        cmsCIEXYZ XYZ;
2890
0
        cmsFloat64Number* Out = (cmsFloat64Number*) output;
2891
0
        cmsXYZEncoded2Float(ContextID, &XYZ, wOut);
2892
2893
0
        Stride /= PixelSize(Info->OutputFormat);
2894
2895
0
        Out[0]        = XYZ.X;
2896
0
        Out[Stride]   = XYZ.Y;
2897
0
        Out[Stride*2] = XYZ.Z;
2898
2899
0
        return output + sizeof(cmsFloat64Number);
2900
2901
0
    }
2902
0
    else {
2903
2904
0
        cmsXYZEncoded2Float(ContextID, (cmsCIEXYZ*) output, wOut);
2905
2906
0
        return output + (sizeof(cmsCIEXYZ) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
2907
0
    }
2908
0
}
2909
2910
static
2911
cmsUInt8Number* PackXYZFloatFrom16(cmsContext ContextID,
2912
                                   CMSREGISTER _cmsTRANSFORM* Info,
2913
                                   CMSREGISTER cmsUInt16Number wOut[],
2914
                                   CMSREGISTER cmsUInt8Number* output,
2915
                                   CMSREGISTER cmsUInt32Number Stride)
2916
0
{
2917
0
    if (T_PLANAR(Info -> OutputFormat)) {
2918
2919
0
        cmsCIEXYZ XYZ;
2920
0
        cmsFloat32Number* Out = (cmsFloat32Number*) output;
2921
0
        cmsXYZEncoded2Float(ContextID, &XYZ, wOut);
2922
2923
0
        Stride /= PixelSize(Info->OutputFormat);
2924
2925
0
        Out[0]        = (cmsFloat32Number) XYZ.X;
2926
0
        Out[Stride]   = (cmsFloat32Number) XYZ.Y;
2927
0
        Out[Stride*2] = (cmsFloat32Number) XYZ.Z;
2928
2929
0
        return output + sizeof(cmsFloat32Number);
2930
2931
0
    }
2932
0
    else {
2933
2934
0
        cmsCIEXYZ XYZ;
2935
0
        cmsFloat32Number* Out = (cmsFloat32Number*) output;
2936
0
        cmsXYZEncoded2Float(ContextID, &XYZ, wOut);
2937
2938
0
        Out[0] = (cmsFloat32Number) XYZ.X;
2939
0
        Out[1] = (cmsFloat32Number) XYZ.Y;
2940
0
        Out[2] = (cmsFloat32Number) XYZ.Z;
2941
2942
0
        return output + (3 * sizeof(cmsFloat32Number) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
2943
0
    }
2944
0
}
2945
2946
static
2947
cmsUInt8Number* PackDoubleFrom16(cmsContext ContextID,
2948
                                 CMSREGISTER _cmsTRANSFORM* info,
2949
                                 CMSREGISTER cmsUInt16Number wOut[],
2950
                                 CMSREGISTER cmsUInt8Number* output,
2951
                                 CMSREGISTER cmsUInt32Number Stride)
2952
0
{
2953
0
    cmsUInt32Number nChan      = T_CHANNELS(info -> OutputFormat);
2954
0
    cmsUInt32Number DoSwap     = T_DOSWAP(info ->OutputFormat);
2955
0
    cmsUInt32Number Reverse    = T_FLAVOR(info ->OutputFormat);
2956
0
    cmsUInt32Number Extra      = T_EXTRA(info -> OutputFormat);
2957
0
    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> OutputFormat);
2958
0
    cmsUInt32Number Planar     = T_PLANAR(info -> OutputFormat);
2959
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
2960
0
    cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0;
2961
0
    cmsFloat64Number v = 0;
2962
0
    cmsFloat64Number* swap1 = (cmsFloat64Number*) output;
2963
0
    cmsUInt32Number i, start = 0;
2964
2965
0
    Stride /= PixelSize(info->OutputFormat);
2966
2967
0
    if (ExtraFirst)
2968
0
        start = Extra;
2969
2970
0
    for (i=0; i < nChan; i++) {
2971
2972
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
2973
2974
0
        v = (cmsFloat64Number) wOut[index] / maximum;
2975
2976
0
        if (Reverse)
2977
0
            v = maximum - v;
2978
2979
0
        if (Planar)
2980
0
            ((cmsFloat64Number*) output)[(i + start)  * Stride]= v;
2981
0
        else
2982
0
            ((cmsFloat64Number*) output)[i + start] = v;
2983
0
    }
2984
2985
2986
0
    if (Extra == 0 && SwapFirst) {
2987
2988
0
         memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number));
2989
0
        *swap1 = v;
2990
0
    }
2991
2992
0
    if (T_PLANAR(info -> OutputFormat))
2993
0
        return output + sizeof(cmsFloat64Number);
2994
0
    else
2995
0
        return output + (nChan + Extra) * sizeof(cmsFloat64Number);
2996
2997
0
}
2998
2999
3000
static
3001
cmsUInt8Number* PackFloatFrom16(cmsContext ContextID,
3002
                                CMSREGISTER _cmsTRANSFORM* info,
3003
                                CMSREGISTER cmsUInt16Number wOut[],
3004
                                CMSREGISTER cmsUInt8Number* output,
3005
                                CMSREGISTER cmsUInt32Number Stride)
3006
0
{
3007
0
       cmsUInt32Number nChan      = T_CHANNELS(info->OutputFormat);
3008
0
       cmsUInt32Number DoSwap     = T_DOSWAP(info->OutputFormat);
3009
0
       cmsUInt32Number Reverse    = T_FLAVOR(info->OutputFormat);
3010
0
       cmsUInt32Number Extra      = T_EXTRA(info->OutputFormat);
3011
0
       cmsUInt32Number SwapFirst  = T_SWAPFIRST(info->OutputFormat);
3012
0
       cmsUInt32Number Planar     = T_PLANAR(info->OutputFormat);
3013
0
       cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3014
0
       cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 655.35 : 65535.0;
3015
0
       cmsFloat64Number v = 0;
3016
0
       cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
3017
0
       cmsUInt32Number i, start = 0;
3018
3019
0
       Stride /= PixelSize(info->OutputFormat);
3020
3021
0
       if (ExtraFirst)
3022
0
              start = Extra;
3023
3024
0
       for (i = 0; i < nChan; i++) {
3025
3026
0
              cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3027
3028
0
              v = (cmsFloat64Number)wOut[index] / maximum;
3029
3030
0
              if (Reverse)
3031
0
                     v = maximum - v;
3032
3033
0
              if (Planar)
3034
0
                     ((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v;
3035
0
              else
3036
0
                     ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;
3037
0
       }
3038
3039
3040
0
       if (Extra == 0 && SwapFirst) {
3041
3042
0
              memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));
3043
0
              *swap1 = (cmsFloat32Number)v;
3044
0
       }
3045
3046
0
       if (T_PLANAR(info->OutputFormat))
3047
0
              return output + sizeof(cmsFloat32Number);
3048
0
       else
3049
0
              return output + (nChan + Extra) * sizeof(cmsFloat32Number);
3050
0
}
3051
3052
3053
3054
// --------------------------------------------------------------------------------------------------------
3055
3056
static
3057
cmsUInt8Number* PackBytesFromFloat(cmsContext ContextID,
3058
           _cmsTRANSFORM* info,
3059
                                    cmsFloat32Number wOut[],
3060
                                    cmsUInt8Number* output,
3061
                                    cmsUInt32Number Stride)
3062
0
{
3063
0
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
3064
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
3065
0
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
3066
0
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
3067
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
3068
0
    cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
3069
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3070
0
    cmsUInt8Number* swap1 = (cmsUInt8Number*)output;
3071
0
    cmsFloat64Number v = 0;
3072
0
    cmsUInt8Number vv = 0;
3073
0
    cmsUInt32Number i, start = 0;
3074
3075
0
    if (ExtraFirst)
3076
0
        start = Extra;
3077
3078
0
    for (i = 0; i < nChan; i++) {
3079
3080
0
        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3081
3082
0
        v = wOut[index] * 65535.0;
3083
3084
0
        if (Reverse)
3085
0
            v = 65535.0 - v;
3086
3087
0
        vv =  FROM_16_TO_8(_cmsQuickSaturateWord(v));
3088
3089
0
        if (Planar)
3090
0
            ((cmsUInt8Number*)output)[(i + start) * Stride] = vv;
3091
0
        else
3092
0
            ((cmsUInt8Number*)output)[i + start] = vv;
3093
0
    }
3094
3095
3096
0
    if (Extra == 0 && SwapFirst) {
3097
3098
0
        memmove(swap1 + 1, swap1, (nChan - 1) * sizeof(cmsUInt8Number));
3099
0
        *swap1 = vv;
3100
0
    }
3101
3102
0
    if (T_PLANAR(info->OutputFormat))
3103
0
        return output + sizeof(cmsUInt8Number);
3104
0
    else
3105
0
        return output + (nChan + Extra) * sizeof(cmsUInt8Number);
3106
0
}
3107
3108
static
3109
cmsUInt8Number* PackWordsFromFloat(cmsContext ContextID,
3110
            _cmsTRANSFORM* info,
3111
                                    cmsFloat32Number wOut[],
3112
                                    cmsUInt8Number* output,
3113
                                    cmsUInt32Number Stride)
3114
0
{
3115
0
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
3116
0
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
3117
0
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
3118
0
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
3119
0
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
3120
0
    cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
3121
0
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3122
0
    cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
3123
0
    cmsFloat64Number v = 0;
3124
0
    cmsUInt16Number vv = 0;
3125
0
    cmsUInt32Number i, start = 0;
3126
3127
0
    if (ExtraFirst)
3128
0
        start = Extra;
3129
3130
0
    Stride /= 2;
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
2.55M
{
3301
2.55M
    cmsFloat64Number* Out = (cmsFloat64Number*) output;
3302
3303
2.55M
    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
2.55M
    else {
3314
3315
2.55M
        Out[0] = (cmsFloat64Number) (wOut[0] * 100.0);
3316
2.55M
        Out[1] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0);
3317
2.55M
        Out[2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0);
3318
3319
2.55M
        return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
3320
2.55M
    }
3321
3322
2.55M
}
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
14.9M
{
3433
14.9M
    cmsFloat64Number* Out = (cmsFloat64Number*) output;
3434
3435
14.9M
    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
14.9M
    else {
3446
3447
14.9M
        Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
3448
14.9M
        Out[1] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
3449
14.9M
        Out[2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
3450
3451
14.9M
        return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
3452
14.9M
    }
3453
3454
14.9M
}
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->InputFormat);
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
1.62M
{
3791
1.62M
    cmsUInt32Number i;
3792
1.62M
    cmsFormatter fr;
3793
3794
1.62M
    switch (dwFlags) {
3795
3796
535k
    case CMS_PACK_FLAGS_16BITS: {
3797
15.7M
        for (i=0; i < sizeof(InputFormatters16) / sizeof(cmsFormatters16); i++) {
3798
15.7M
            const cmsFormatters16* f = InputFormatters16 + i;
3799
3800
15.7M
            if ((dwInput & ~f ->Mask) == f ->Type) {
3801
535k
                fr.Fmt16 = f ->Frm;
3802
535k
                return fr;
3803
535k
            }
3804
15.7M
        }
3805
535k
    }
3806
0
    break;
3807
3808
1.08M
    case CMS_PACK_FLAGS_FLOAT: {
3809
11.7M
        for (i=0; i < sizeof(InputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {
3810
11.7M
            const cmsFormattersFloat* f = InputFormattersFloat + i;
3811
3812
11.7M
            if ((dwInput & ~f ->Mask) == f ->Type) {
3813
1.08M
                fr.FmtFloat = f ->Frm;
3814
1.08M
                return fr;
3815
1.08M
            }
3816
11.7M
        }
3817
1.08M
    }
3818
0
    break;
3819
3820
0
    default:;
3821
3822
1.62M
    }
3823
3824
0
    fr.Fmt16 = NULL;
3825
0
    return fr;
3826
1.62M
}
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
1.62M
{
3957
1.62M
    cmsUInt32Number i;
3958
1.62M
    cmsFormatter fr;
3959
3960
    // Optimization is only a hint
3961
1.62M
    dwInput &= ~OPTIMIZED_SH(1);
3962
3963
1.62M
    switch (dwFlags)
3964
1.62M
    {
3965
3966
535k
     case CMS_PACK_FLAGS_16BITS: {
3967
3968
20.2M
        for (i=0; i < sizeof(OutputFormatters16) / sizeof(cmsFormatters16); i++) {
3969
20.2M
            const cmsFormatters16* f = OutputFormatters16 + i;
3970
3971
20.2M
            if ((dwInput & ~f ->Mask) == f ->Type) {
3972
535k
                fr.Fmt16 = f ->Frm;
3973
535k
                return fr;
3974
535k
            }
3975
20.2M
        }
3976
535k
        }
3977
0
        break;
3978
3979
1.08M
    case CMS_PACK_FLAGS_FLOAT: {
3980
3981
3.31M
        for (i=0; i < sizeof(OutputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {
3982
3.31M
            const cmsFormattersFloat* f = OutputFormattersFloat + i;
3983
3984
3.31M
            if ((dwInput & ~f ->Mask) == f ->Type) {
3985
1.08M
                fr.FmtFloat = f ->Frm;
3986
1.08M
                return fr;
3987
1.08M
            }
3988
3.31M
        }
3989
1.08M
        }
3990
0
        break;
3991
3992
0
    default:;
3993
3994
1.62M
    }
3995
3996
0
    fr.Fmt16 = NULL;
3997
0
    return fr;
3998
1.62M
}
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
174k
{
4051
174k
      _cmsAssert(ctx != NULL);
4052
4053
174k
     if (src != NULL) {
4054
4055
         // Duplicate the LIST
4056
0
         DupFormatterFactoryList(ctx, src);
4057
0
     }
4058
174k
     else {
4059
174k
          static _cmsFormattersPluginChunkType FormattersPluginChunk = { NULL };
4060
174k
          ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx ->MemPool, &FormattersPluginChunk, sizeof(_cmsFormattersPluginChunkType));
4061
174k
     }
4062
174k
}
4063
4064
4065
4066
// Formatters management
4067
cmsBool  _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Data)
4068
174k
{
4069
174k
    _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);
4070
174k
    cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data;
4071
174k
    cmsFormattersFactoryList* fl ;
4072
4073
    // Reset to built-in defaults
4074
174k
    if (Data == NULL) {
4075
4076
174k
          ctx ->FactoryList = NULL;
4077
174k
          return TRUE;
4078
174k
    }
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
3.24M
{
4096
3.24M
    _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);
4097
3.24M
    cmsFormattersFactoryList* f;
4098
4099
3.24M
    if (T_CHANNELS(Type) == 0) {
4100
0
        static const cmsFormatter nullFormatter = { 0 };
4101
0
        return nullFormatter;
4102
0
    }
4103
4104
3.24M
    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
3.24M
    if (Dir == cmsFormatterInput)
4112
1.62M
        return _cmsGetStockInputFormatter(Type, dwFlags);
4113
1.62M
    else
4114
1.62M
        return _cmsGetStockOutputFormatter(Type, dwFlags);
4115
3.24M
}
4116
4117
4118
// Return whatever given formatter refers to float values
4119
cmsBool  _cmsFormatterIsFloat(cmsUInt32Number Type)
4120
11.8M
{
4121
11.8M
    return T_FLOAT(Type) ? TRUE : FALSE;
4122
11.8M
}
4123
4124
// Return whatever given formatter refers to 8 bits
4125
cmsBool  _cmsFormatterIs8bit(cmsUInt32Number Type)
4126
11.1k
{
4127
11.1k
    cmsUInt32Number Bytes = T_BYTES(Type);
4128
4129
11.1k
    return (Bytes == 1);
4130
11.1k
}
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
1.00M
{
4135
4136
1.00M
    cmsColorSpaceSignature ColorSpace      = cmsGetColorSpace(ContextID, hProfile);
4137
1.00M
    cmsUInt32Number        ColorSpaceBits  = (cmsUInt32Number) _cmsLCMScolorSpace(ContextID, ColorSpace);
4138
1.00M
    cmsInt32Number         nOutputChans    = cmsChannelsOfColorSpace(ContextID, ColorSpace);
4139
1.00M
    cmsUInt32Number        Float           = lIsFloat ? 1U : 0;
4140
4141
    // Unsupported color space?
4142
1.00M
    if (nOutputChans < 0) return 0;
4143
4144
    // Fix float spaces
4145
1.00M
    nBytes &= 7;
4146
4147
    // Create a fake formatter for result
4148
1.00M
    return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
4149
1.00M
}
4150
4151
// Build a suitable formatter for the colorspace of this profile
4152
cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsContext ContextID, cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat)
4153
0
{
4154
4155
0
    cmsColorSpaceSignature ColorSpace = cmsGetPCS(ContextID, hProfile);
4156
4157
0
    cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ContextID, ColorSpace);
4158
0
    cmsUInt32Number nOutputChans = cmsChannelsOfColorSpace(ContextID, ColorSpace);
4159
0
    cmsUInt32Number Float = lIsFloat ? 1U : 0;
4160
4161
    // Unsupported color space?
4162
0
    if (nOutputChans < 0) return 0;
4163
4164
    // Fix float spaces
4165
0
    nBytes &= 7;
4166
4167
    // Create a fake formatter for result
4168
0
    return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
4169
0
}