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