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