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