Coverage Report

Created: 2025-06-10 07:27

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