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