1 //---------------------------------------------------------------------------------
3 // Little Color Management System
4 // Copyright (c) 1998-2010 Marti Maria Saguer
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:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
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.
24 //---------------------------------------------------------------------------------
27 #include "lcms2_internal.h"
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 as special
34 // ---------------------------------------------------------------------------
37 // This macro return words stored as big endian
38 #define CHANGE_ENDIAN(w) (cmsUInt16Number) ((cmsUInt16Number) ((w)<<8)|((w)>>8))
40 // These macros handles reversing (negative)
41 #define REVERSE_FLAVOR_8(x) ((cmsUInt8Number) (0xff-(x)))
42 #define REVERSE_FLAVOR_16(x) ((cmsUInt16Number)(0xffff-(x)))
44 // * 0xffff / 0xff00 = (255 * 257) / (255 * 256) = 257 / 256
45 cmsINLINE cmsUInt16Number FomLabV2ToLabV4(cmsUInt16Number x)
49 a = (x << 8 | x) >> 8; // * 257 / 256
50 if ( a > 0xffff) return 0xffff;
51 return (cmsUInt16Number) a;
54 // * 0xf00 / 0xffff = * 256 / 257
55 cmsINLINE cmsUInt16Number FomLabV4ToLabV2(cmsUInt16Number x)
57 return (cmsUInt16Number) (((x << 8) + 0x80) / 257);
71 cmsFormatterFloat Frm;
75 #define ANYSPACE COLORSPACE_SH(31)
76 #define ANYCHANNELS CHANNELS_SH(15)
77 #define ANYEXTRA EXTRA_SH(7)
78 #define ANYPLANAR PLANAR_SH(1)
79 #define ANYENDIAN ENDIAN16_SH(1)
80 #define ANYSWAP DOSWAP_SH(1)
81 #define ANYSWAPFIRST SWAPFIRST_SH(1)
82 #define ANYFLAVOR FLAVOR_SH(1)
85 // Supress waning about info never being used
88 #pragma warning(disable : 4100)
91 // Unpacking routines (16 bits) ----------------------------------------------------------------------------------------
93 // Does almost everything but is slow
95 cmsUInt8Number* UnrollChunkyBytes(register _cmsTRANSFORM* info,
96 register cmsUInt16Number wIn[],
97 register cmsUInt8Number* accum,
98 register cmsUInt32Number Stride)
100 int nChan = T_CHANNELS(info -> InputFormat);
101 int DoSwap = T_DOSWAP(info ->InputFormat);
102 int Reverse = T_FLAVOR(info ->InputFormat);
103 int SwapFirst = T_SWAPFIRST(info -> InputFormat);
104 int Extra = T_EXTRA(info -> InputFormat);
105 int ExtraFirst = DoSwap && !SwapFirst;
113 for (i=0; i < nChan; i++) {
114 int index = DoSwap ? (nChan - i - 1) : i;
116 v = FROM_8_TO_16(*accum);
117 v = Reverse ? REVERSE_FLAVOR_16(v) : v;
126 if (Extra == 0 && SwapFirst) {
127 cmsUInt16Number tmp = wIn[0];
129 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
136 // Extra channels are just ignored because come in the next planes
138 cmsUInt8Number* UnrollPlanarBytes(register _cmsTRANSFORM* info,
139 register cmsUInt16Number wIn[],
140 register cmsUInt8Number* accum,
141 register cmsUInt32Number Stride)
143 int nChan = T_CHANNELS(info -> InputFormat);
144 int DoSwap= T_DOSWAP(info ->InputFormat);
145 int Reverse= T_FLAVOR(info ->InputFormat);
147 cmsUInt8Number* Init = accum;
150 accum += T_EXTRA(info -> InputFormat) * Stride;
153 for (i=0; i < nChan; i++) {
155 int index = DoSwap ? (nChan - i - 1) : i;
156 cmsUInt16Number v = FROM_8_TO_16(*accum);
158 wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;
165 // Special cases, provided for performance
167 cmsUInt8Number* Unroll4Bytes(register _cmsTRANSFORM* info,
168 register cmsUInt16Number wIn[],
169 register cmsUInt8Number* accum,
170 register cmsUInt32Number Stride)
172 wIn[0] = FROM_8_TO_16(*accum); accum++; // C
173 wIn[1] = FROM_8_TO_16(*accum); accum++; // M
174 wIn[2] = FROM_8_TO_16(*accum); accum++; // Y
175 wIn[3] = FROM_8_TO_16(*accum); accum++; // K
181 cmsUInt8Number* Unroll4BytesReverse(register _cmsTRANSFORM* info,
182 register cmsUInt16Number wIn[],
183 register cmsUInt8Number* accum,
184 register cmsUInt32Number Stride)
186 wIn[0] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // C
187 wIn[1] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // M
188 wIn[2] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // Y
189 wIn[3] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // K
195 cmsUInt8Number* Unroll4BytesSwapFirst(register _cmsTRANSFORM* info,
196 register cmsUInt16Number wIn[],
197 register cmsUInt8Number* accum,
198 register cmsUInt32Number Stride)
200 wIn[3] = FROM_8_TO_16(*accum); accum++; // K
201 wIn[0] = FROM_8_TO_16(*accum); accum++; // C
202 wIn[1] = FROM_8_TO_16(*accum); accum++; // M
203 wIn[2] = FROM_8_TO_16(*accum); accum++; // Y
210 cmsUInt8Number* Unroll4BytesSwap(register _cmsTRANSFORM* info,
211 register cmsUInt16Number wIn[],
212 register cmsUInt8Number* accum,
213 register cmsUInt32Number Stride)
215 wIn[3] = FROM_8_TO_16(*accum); accum++; // K
216 wIn[2] = FROM_8_TO_16(*accum); accum++; // Y
217 wIn[1] = FROM_8_TO_16(*accum); accum++; // M
218 wIn[0] = FROM_8_TO_16(*accum); accum++; // C
224 cmsUInt8Number* Unroll4BytesSwapSwapFirst(register _cmsTRANSFORM* info,
225 register cmsUInt16Number wIn[],
226 register cmsUInt8Number* accum,
227 register cmsUInt32Number Stride)
229 wIn[2] = FROM_8_TO_16(*accum); accum++; // K
230 wIn[1] = FROM_8_TO_16(*accum); accum++; // Y
231 wIn[0] = FROM_8_TO_16(*accum); accum++; // M
232 wIn[3] = FROM_8_TO_16(*accum); accum++; // C
238 cmsUInt8Number* Unroll3Bytes(register _cmsTRANSFORM* info,
239 register cmsUInt16Number wIn[],
240 register cmsUInt8Number* accum,
241 register cmsUInt32Number Stride)
243 wIn[0] = FROM_8_TO_16(*accum); accum++; // R
244 wIn[1] = FROM_8_TO_16(*accum); accum++; // G
245 wIn[2] = FROM_8_TO_16(*accum); accum++; // B
251 cmsUInt8Number* Unroll3BytesSkip1Swap(register _cmsTRANSFORM* info,
252 register cmsUInt16Number wIn[],
253 register cmsUInt8Number* accum,
254 register cmsUInt32Number Stride)
257 wIn[2] = FROM_8_TO_16(*accum); accum++; // B
258 wIn[1] = FROM_8_TO_16(*accum); accum++; // G
259 wIn[0] = FROM_8_TO_16(*accum); accum++; // R
265 cmsUInt8Number* Unroll3BytesSkip1SwapFirst(register _cmsTRANSFORM* info,
266 register cmsUInt16Number wIn[],
267 register cmsUInt8Number* accum,
268 register cmsUInt32Number Stride)
271 wIn[0] = FROM_8_TO_16(*accum); accum++; // R
272 wIn[1] = FROM_8_TO_16(*accum); accum++; // G
273 wIn[2] = FROM_8_TO_16(*accum); accum++; // B
281 cmsUInt8Number* Unroll3BytesSwap(register _cmsTRANSFORM* info,
282 register cmsUInt16Number wIn[],
283 register cmsUInt8Number* accum,
284 register cmsUInt32Number Stride)
286 wIn[2] = FROM_8_TO_16(*accum); accum++; // B
287 wIn[1] = FROM_8_TO_16(*accum); accum++; // G
288 wIn[0] = FROM_8_TO_16(*accum); accum++; // R
294 cmsUInt8Number* UnrollLabV2_8(register _cmsTRANSFORM* info,
295 register cmsUInt16Number wIn[],
296 register cmsUInt8Number* accum,
297 register cmsUInt32Number Stride)
299 wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L
300 wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a
301 wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b
307 cmsUInt8Number* UnrollALabV2_8(register _cmsTRANSFORM* info,
308 register cmsUInt16Number wIn[],
309 register cmsUInt8Number* accum,
310 register cmsUInt32Number Stride)
313 wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L
314 wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a
315 wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b
321 cmsUInt8Number* UnrollLabV2_16(register _cmsTRANSFORM* info,
322 register cmsUInt16Number wIn[],
323 register cmsUInt8Number* accum,
324 register cmsUInt32Number Stride)
326 wIn[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // L
327 wIn[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // a
328 wIn[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // b
335 cmsUInt8Number* Unroll2Bytes(register _cmsTRANSFORM* info,
336 register cmsUInt16Number wIn[],
337 register cmsUInt8Number* accum,
338 register cmsUInt32Number Stride)
340 wIn[0] = FROM_8_TO_16(*accum); accum++; // ch1
341 wIn[1] = FROM_8_TO_16(*accum); accum++; // ch2
348 // Monochrome duplicates L into RGB for null-transforms
350 cmsUInt8Number* Unroll1Byte(register _cmsTRANSFORM* info,
351 register cmsUInt16Number wIn[],
352 register cmsUInt8Number* accum,
353 register cmsUInt32Number Stride)
355 wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L
361 cmsUInt8Number* Unroll1ByteSkip1(register _cmsTRANSFORM* info,
362 register cmsUInt16Number wIn[],
363 register cmsUInt8Number* accum,
364 register cmsUInt32Number Stride)
366 wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L
372 cmsUInt8Number* Unroll1ByteSkip2(register _cmsTRANSFORM* info,
373 register cmsUInt16Number wIn[],
374 register cmsUInt8Number* accum,
375 register cmsUInt32Number Stride)
377 wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L
383 cmsUInt8Number* Unroll1ByteReversed(register _cmsTRANSFORM* info,
384 register cmsUInt16Number wIn[],
385 register cmsUInt8Number* accum,
386 register cmsUInt32Number Stride)
388 wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(FROM_8_TO_16(*accum)); accum++; // L
394 cmsUInt8Number* UnrollAnyWords(register _cmsTRANSFORM* info,
395 register cmsUInt16Number wIn[],
396 register cmsUInt8Number* accum,
397 register cmsUInt32Number Stride)
399 int nChan = T_CHANNELS(info -> InputFormat);
400 int SwapEndian = T_ENDIAN16(info -> InputFormat);
401 int DoSwap = T_DOSWAP(info ->InputFormat);
402 int Reverse = T_FLAVOR(info ->InputFormat);
403 int SwapFirst = T_SWAPFIRST(info -> InputFormat);
404 int Extra = T_EXTRA(info -> InputFormat);
405 int ExtraFirst = DoSwap && !SwapFirst;
409 accum += Extra * sizeof(cmsUInt16Number);
412 for (i=0; i < nChan; i++) {
414 int index = DoSwap ? (nChan - i - 1) : i;
415 cmsUInt16Number v = *(cmsUInt16Number*) accum;
418 v = CHANGE_ENDIAN(v);
420 wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;
422 accum += sizeof(cmsUInt16Number);
426 accum += Extra * sizeof(cmsUInt16Number);
429 if (Extra == 0 && SwapFirst) {
431 cmsUInt16Number tmp = wIn[0];
433 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
441 cmsUInt8Number* UnrollPlanarWords(register _cmsTRANSFORM* info,
442 register cmsUInt16Number wIn[],
443 register cmsUInt8Number* accum,
444 register cmsUInt32Number Stride)
446 int nChan = T_CHANNELS(info -> InputFormat);
447 int DoSwap= T_DOSWAP(info ->InputFormat);
448 int Reverse= T_FLAVOR(info ->InputFormat);
449 int SwapEndian = T_ENDIAN16(info -> InputFormat);
451 cmsUInt8Number* Init = accum;
454 accum += T_EXTRA(info -> InputFormat) * Stride * sizeof(cmsUInt16Number);
457 for (i=0; i < nChan; i++) {
459 int index = DoSwap ? (nChan - i - 1) : i;
460 cmsUInt16Number v = *(cmsUInt16Number*) accum;
463 v = CHANGE_ENDIAN(v);
465 wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;
467 accum += Stride * sizeof(cmsUInt16Number);
470 return (Init + sizeof(cmsUInt16Number));
475 cmsUInt8Number* Unroll4Words(register _cmsTRANSFORM* info,
476 register cmsUInt16Number wIn[],
477 register cmsUInt8Number* accum,
478 register cmsUInt32Number Stride)
480 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
481 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
482 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
483 wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
489 cmsUInt8Number* Unroll4WordsReverse(register _cmsTRANSFORM* info,
490 register cmsUInt16Number wIn[],
491 register cmsUInt8Number* accum,
492 register cmsUInt32Number Stride)
494 wIn[0] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // C
495 wIn[1] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // M
496 wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // Y
497 wIn[3] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // K
503 cmsUInt8Number* Unroll4WordsSwapFirst(register _cmsTRANSFORM* info,
504 register cmsUInt16Number wIn[],
505 register cmsUInt8Number* accum,
506 register cmsUInt32Number Stride)
508 wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
509 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
510 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
511 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
518 cmsUInt8Number* Unroll4WordsSwap(register _cmsTRANSFORM* info,
519 register cmsUInt16Number wIn[],
520 register cmsUInt8Number* accum,
521 register cmsUInt32Number Stride)
523 wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
524 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
525 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
526 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
532 cmsUInt8Number* Unroll4WordsSwapSwapFirst(register _cmsTRANSFORM* info,
533 register cmsUInt16Number wIn[],
534 register cmsUInt8Number* accum,
535 register cmsUInt32Number Stride)
537 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // K
538 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // Y
539 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // M
540 wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // C
546 cmsUInt8Number* Unroll3Words(register _cmsTRANSFORM* info,
547 register cmsUInt16Number wIn[],
548 register cmsUInt8Number* accum,
549 register cmsUInt32Number Stride)
551 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C R
552 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M G
553 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y B
558 cmsUInt8Number* Unroll3WordsSwap(register _cmsTRANSFORM* info,
559 register cmsUInt16Number wIn[],
560 register cmsUInt8Number* accum,
561 register cmsUInt32Number Stride)
563 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // C R
564 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M G
565 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // Y B
570 cmsUInt8Number* Unroll3WordsSkip1Swap(register _cmsTRANSFORM* info,
571 register cmsUInt16Number wIn[],
572 register cmsUInt8Number* accum,
573 register cmsUInt32Number Stride)
576 wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // R
577 wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G
578 wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // B
584 cmsUInt8Number* Unroll3WordsSkip1SwapFirst(register _cmsTRANSFORM* info,
585 register cmsUInt16Number wIn[],
586 register cmsUInt8Number* accum,
587 register cmsUInt32Number Stride)
590 wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // R
591 wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G
592 wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // B
598 cmsUInt8Number* Unroll1Word(register _cmsTRANSFORM* info,
599 register cmsUInt16Number wIn[],
600 register cmsUInt8Number* accum,
601 register cmsUInt32Number Stride)
603 wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // L
608 cmsUInt8Number* Unroll1WordReversed(register _cmsTRANSFORM* info,
609 register cmsUInt16Number wIn[],
610 register cmsUInt8Number* accum,
611 register cmsUInt32Number Stride)
613 wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2;
618 cmsUInt8Number* Unroll1WordSkip3(register _cmsTRANSFORM* info,
619 register cmsUInt16Number wIn[],
620 register cmsUInt8Number* accum,
621 register cmsUInt32Number Stride)
623 wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum;
630 cmsUInt8Number* Unroll2Words(register _cmsTRANSFORM* info,
631 register cmsUInt16Number wIn[],
632 register cmsUInt8Number* accum,
633 register cmsUInt32Number Stride)
635 wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // ch1
636 wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // ch2
642 // This is a conversion of Lab double to 16 bits
644 cmsUInt8Number* UnrollLabDoubleTo16(register _cmsTRANSFORM* info,
645 register cmsUInt16Number wIn[],
646 register cmsUInt8Number* accum,
647 register cmsUInt32Number Stride)
649 if (T_PLANAR(info -> InputFormat)) {
651 cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
657 Lab.b = Pt[Stride*2];
659 cmsFloat2LabEncoded(wIn, &Lab);
660 return accum + sizeof(cmsFloat64Number);
664 cmsFloat2LabEncoded(wIn, (cmsCIELab*) accum);
665 accum += sizeof(cmsCIELab) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number);
670 // This is a conversion of XYZ double to 16 bits
672 cmsUInt8Number* UnrollXYZDoubleTo16(register _cmsTRANSFORM* info,
673 register cmsUInt16Number wIn[],
674 register cmsUInt8Number* accum,
675 register cmsUInt32Number Stride)
677 if (T_PLANAR(info -> InputFormat)) {
679 cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
684 XYZ.Z = Pt[Stride*2];
685 cmsFloat2XYZEncoded(wIn, &XYZ);
687 return accum + sizeof(cmsFloat64Number);
692 cmsFloat2XYZEncoded(wIn, (cmsCIEXYZ*) accum);
693 accum += sizeof(cmsCIEXYZ) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number);
699 // Check if space is marked as ink
700 cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type)
702 switch (T_COLORSPACE(Type)) {
716 case PT_MCH15: return TRUE;
718 default: return FALSE;
722 // Inks does come in percentage, remaining cases are between 0..1.0, again to 16 bits
724 cmsUInt8Number* UnrollDoubleTo16(register _cmsTRANSFORM* info,
725 register cmsUInt16Number wIn[],
726 register cmsUInt8Number* accum,
727 register cmsUInt32Number Stride)
729 cmsFloat64Number* Inks = (cmsFloat64Number*) accum;
730 int nChan = T_CHANNELS(info -> InputFormat);
731 int Planar = T_PLANAR(info -> InputFormat);
734 cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
736 for (i=0; i < nChan; i++) {
740 v = Inks[i * Stride];
744 wIn[i] = _cmsQuickSaturateWord(v * maximum);
747 if (T_PLANAR(info -> InputFormat))
748 return accum + sizeof(cmsFloat64Number);
750 return accum + (nChan + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat64Number);
754 cmsUInt8Number* UnrollFloatTo16(register _cmsTRANSFORM* info,
755 register cmsUInt16Number wIn[],
756 register cmsUInt8Number* accum,
757 register cmsUInt32Number Stride)
759 cmsFloat32Number* Inks = (cmsFloat32Number*) accum;
760 int nChan = T_CHANNELS(info -> InputFormat);
761 int Planar = T_PLANAR(info -> InputFormat);
764 cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
766 for (i=0; i < nChan; i++) {
770 v = Inks[i * Stride];
774 wIn[i] = _cmsQuickSaturateWord(v * maximum);
777 if (T_PLANAR(info -> InputFormat))
778 return accum + sizeof(cmsFloat32Number);
780 return accum + (nChan + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat32Number);
784 // For 1 channel, we need to duplicate data (it comes in 0..1.0 range)
786 cmsUInt8Number* UnrollDouble1Chan(register _cmsTRANSFORM* info,
787 register cmsUInt16Number wIn[],
788 register cmsUInt8Number* accum,
789 register cmsUInt32Number Stride)
791 cmsFloat64Number* Inks = (cmsFloat64Number*) accum;
793 wIn[0] = wIn[1] = wIn[2] = _cmsQuickSaturateWord(Inks[0] * 65535.0);
795 return accum + sizeof(cmsFloat64Number);
798 //-------------------------------------------------------------------------------------------------------------------
800 // True float transformation.
802 // For anything going from cmsFloat32Number
804 cmsUInt8Number* UnrollFloatsToFloat(_cmsTRANSFORM* info,
805 cmsFloat32Number wIn[],
806 cmsUInt8Number* accum,
807 cmsUInt32Number Stride)
809 cmsFloat32Number* Inks = (cmsFloat32Number*) accum;
810 int nChan = T_CHANNELS(info -> InputFormat);
811 int Planar = T_PLANAR(info -> InputFormat);
813 cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0;
816 for (i=0; i < nChan; i++) {
819 wIn[i] = (cmsFloat32Number) (Inks[i * Stride] / maximum);
821 wIn[i] = (cmsFloat32Number) (Inks[i] / maximum);
824 if (T_PLANAR(info -> InputFormat))
825 return accum + sizeof(cmsFloat32Number);
827 return accum + (nChan + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat32Number);
830 // For anything going from double
832 cmsUInt8Number* UnrollDoublesToFloat(_cmsTRANSFORM* info,
833 cmsFloat32Number wIn[],
834 cmsUInt8Number* accum,
835 cmsUInt32Number Stride)
837 cmsFloat64Number* Inks = (cmsFloat64Number*) accum;
838 int nChan = T_CHANNELS(info -> InputFormat);
839 int Planar = T_PLANAR(info -> InputFormat);
841 cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0;
843 for (i=0; i < nChan; i++) {
846 wIn[i] = (cmsFloat32Number) (Inks[i * Stride] / maximum);
848 wIn[i] = (cmsFloat32Number) (Inks[i] / maximum);
851 if (T_PLANAR(info -> InputFormat))
852 return accum + sizeof(cmsFloat64Number);
854 return accum + (nChan + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat64Number);
858 // From Lab double to cmsFloat32Number
860 cmsUInt8Number* UnrollLabDoubleToFloat(_cmsTRANSFORM* info,
861 cmsFloat32Number wIn[],
862 cmsUInt8Number* accum,
863 cmsUInt32Number Stride)
865 cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
867 if (T_PLANAR(info -> InputFormat)) {
869 wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1
870 wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0); // form -128..+127 to 0..1
871 wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);
873 return accum + sizeof(cmsFloat64Number);
877 wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1
878 wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0); // form -128..+127 to 0..1
879 wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);
881 accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat));
886 // From Lab double to cmsFloat32Number
888 cmsUInt8Number* UnrollLabFloatToFloat(_cmsTRANSFORM* info,
889 cmsFloat32Number wIn[],
890 cmsUInt8Number* accum,
891 cmsUInt32Number Stride)
893 cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
895 if (T_PLANAR(info -> InputFormat)) {
897 wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1
898 wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0); // form -128..+127 to 0..1
899 wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);
901 return accum + sizeof(cmsFloat32Number);
905 wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1
906 wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0); // form -128..+127 to 0..1
907 wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);
909 accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat));
915 // 1.15 fixed point, that means maximum value is MAX_ENCODEABLE_XYZ (0xFFFF)
917 cmsUInt8Number* UnrollXYZDoubleToFloat(_cmsTRANSFORM* info,
918 cmsFloat32Number wIn[],
919 cmsUInt8Number* accum,
920 cmsUInt32Number Stride)
922 cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
924 if (T_PLANAR(info -> InputFormat)) {
926 wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
927 wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);
928 wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);
930 return accum + sizeof(cmsFloat64Number);
934 wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
935 wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);
936 wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);
938 accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat));
944 cmsUInt8Number* UnrollXYZFloatToFloat(_cmsTRANSFORM* info,
945 cmsFloat32Number wIn[],
946 cmsUInt8Number* accum,
947 cmsUInt32Number Stride)
949 cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
951 if (T_PLANAR(info -> InputFormat)) {
953 wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
954 wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);
955 wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);
957 return accum + sizeof(cmsFloat32Number);
961 wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
962 wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);
963 wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);
965 accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat));
970 // Packing routines -----------------------------------------------------------------------------------------------------------
973 // Generic chunky for byte
976 cmsUInt8Number* PackAnyBytes(register _cmsTRANSFORM* info,
977 register cmsUInt16Number wOut[],
978 register cmsUInt8Number* output,
979 register cmsUInt32Number Stride)
981 int nChan = T_CHANNELS(info -> OutputFormat);
982 int DoSwap = T_DOSWAP(info ->OutputFormat);
983 int Reverse = T_FLAVOR(info ->OutputFormat);
984 int Extra = T_EXTRA(info -> OutputFormat);
985 int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
986 int ExtraFirst = DoSwap && !SwapFirst;
987 cmsUInt8Number* swap1;
988 cmsUInt8Number v = 0;
997 for (i=0; i < nChan; i++) {
999 int index = DoSwap ? (nChan - i - 1) : i;
1001 v = FROM_16_TO_8(wOut[index]);
1004 v = REVERSE_FLAVOR_8(v);
1013 if (Extra == 0 && SwapFirst) {
1015 memmove(swap1 + 1, swap1, nChan-1);
1026 cmsUInt8Number* PackAnyWords(register _cmsTRANSFORM* info,
1027 register cmsUInt16Number wOut[],
1028 register cmsUInt8Number* output,
1029 register cmsUInt32Number Stride)
1031 int nChan = T_CHANNELS(info -> OutputFormat);
1032 int SwapEndian = T_ENDIAN16(info -> InputFormat);
1033 int DoSwap = T_DOSWAP(info ->OutputFormat);
1034 int Reverse = T_FLAVOR(info ->OutputFormat);
1035 int Extra = T_EXTRA(info -> OutputFormat);
1036 int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
1037 int ExtraFirst = DoSwap && !SwapFirst;
1038 cmsUInt16Number* swap1;
1039 cmsUInt16Number v = 0;
1042 swap1 = (cmsUInt16Number*) output;
1045 output += Extra * sizeof(cmsUInt16Number);
1048 for (i=0; i < nChan; i++) {
1050 int index = DoSwap ? (nChan - i - 1) : i;
1055 v = CHANGE_ENDIAN(v);
1058 v = REVERSE_FLAVOR_16(v);
1060 *(cmsUInt16Number*) output = v;
1062 output += sizeof(cmsUInt16Number);
1066 output += Extra * sizeof(cmsUInt16Number);
1069 if (Extra == 0 && SwapFirst) {
1071 memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number));
1081 cmsUInt8Number* PackPlanarBytes(register _cmsTRANSFORM* info,
1082 register cmsUInt16Number wOut[],
1083 register cmsUInt8Number* output,
1084 register cmsUInt32Number Stride)
1086 int nChan = T_CHANNELS(info -> OutputFormat);
1087 int DoSwap = T_DOSWAP(info ->OutputFormat);
1088 int Reverse= T_FLAVOR(info ->OutputFormat);
1090 cmsUInt8Number* Init = output;
1092 for (i=0; i < nChan; i++) {
1094 int index = DoSwap ? (nChan - i - 1) : i;
1095 cmsUInt8Number v = FROM_16_TO_8(wOut[index]);
1097 *(cmsUInt8Number*) output = (cmsUInt8Number) (Reverse ? REVERSE_FLAVOR_8(v) : v);
1106 cmsUInt8Number* PackPlanarWords(register _cmsTRANSFORM* info,
1107 register cmsUInt16Number wOut[],
1108 register cmsUInt8Number* output,
1109 register cmsUInt32Number Stride)
1111 int nChan = T_CHANNELS(info -> OutputFormat);
1112 int DoSwap = T_DOSWAP(info ->OutputFormat);
1113 int Reverse= T_FLAVOR(info ->OutputFormat);
1114 int SwapEndian = T_ENDIAN16(info -> OutputFormat);
1116 cmsUInt8Number* Init = output;
1120 output += T_EXTRA(info -> OutputFormat) * Stride * sizeof(cmsUInt16Number);
1123 for (i=0; i < nChan; i++) {
1125 int index = DoSwap ? (nChan - i - 1) : i;
1130 v = CHANGE_ENDIAN(v);
1133 v = REVERSE_FLAVOR_16(v);
1135 *(cmsUInt16Number*) output = v;
1136 output += (Stride * sizeof(cmsUInt16Number));
1139 return (Init + sizeof(cmsUInt16Number));
1142 // CMYKcm (unrolled for speed)
1145 cmsUInt8Number* Pack6Bytes(register _cmsTRANSFORM* info,
1146 register cmsUInt16Number wOut[],
1147 register cmsUInt8Number* output,
1148 register cmsUInt32Number Stride)
1150 *output++ = FROM_16_TO_8(wOut[0]);
1151 *output++ = FROM_16_TO_8(wOut[1]);
1152 *output++ = FROM_16_TO_8(wOut[2]);
1153 *output++ = FROM_16_TO_8(wOut[3]);
1154 *output++ = FROM_16_TO_8(wOut[4]);
1155 *output++ = FROM_16_TO_8(wOut[5]);
1163 cmsUInt8Number* Pack6BytesSwap(register _cmsTRANSFORM* info,
1164 register cmsUInt16Number wOut[],
1165 register cmsUInt8Number* output,
1166 register cmsUInt32Number Stride)
1168 *output++ = FROM_16_TO_8(wOut[5]);
1169 *output++ = FROM_16_TO_8(wOut[4]);
1170 *output++ = FROM_16_TO_8(wOut[3]);
1171 *output++ = FROM_16_TO_8(wOut[2]);
1172 *output++ = FROM_16_TO_8(wOut[1]);
1173 *output++ = FROM_16_TO_8(wOut[0]);
1180 cmsUInt8Number* Pack6Words(register _cmsTRANSFORM* info,
1181 register cmsUInt16Number wOut[],
1182 register cmsUInt8Number* output,
1183 register cmsUInt32Number Stride)
1185 *(cmsUInt16Number*) output = wOut[0];
1187 *(cmsUInt16Number*) output = wOut[1];
1189 *(cmsUInt16Number*) output = wOut[2];
1191 *(cmsUInt16Number*) output = wOut[3];
1193 *(cmsUInt16Number*) output = wOut[4];
1195 *(cmsUInt16Number*) output = wOut[5];
1203 cmsUInt8Number* Pack6WordsSwap(register _cmsTRANSFORM* info,
1204 register cmsUInt16Number wOut[],
1205 register cmsUInt8Number* output,
1206 register cmsUInt32Number Stride)
1208 *(cmsUInt16Number*) output = wOut[5];
1210 *(cmsUInt16Number*) output = wOut[4];
1212 *(cmsUInt16Number*) output = wOut[3];
1214 *(cmsUInt16Number*) output = wOut[2];
1216 *(cmsUInt16Number*) output = wOut[1];
1218 *(cmsUInt16Number*) output = wOut[0];
1226 cmsUInt8Number* Pack4Bytes(register _cmsTRANSFORM* info,
1227 register cmsUInt16Number wOut[],
1228 register cmsUInt8Number* output,
1229 register cmsUInt32Number Stride)
1231 *output++ = FROM_16_TO_8(wOut[0]);
1232 *output++ = FROM_16_TO_8(wOut[1]);
1233 *output++ = FROM_16_TO_8(wOut[2]);
1234 *output++ = FROM_16_TO_8(wOut[3]);
1240 cmsUInt8Number* Pack4BytesReverse(register _cmsTRANSFORM* info,
1241 register cmsUInt16Number wOut[],
1242 register cmsUInt8Number* output,
1243 register cmsUInt32Number Stride)
1245 *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[0]));
1246 *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[1]));
1247 *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[2]));
1248 *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[3]));
1255 cmsUInt8Number* Pack4BytesSwapFirst(register _cmsTRANSFORM* info,
1256 register cmsUInt16Number wOut[],
1257 register cmsUInt8Number* output,
1258 register cmsUInt32Number Stride)
1260 *output++ = FROM_16_TO_8(wOut[3]);
1261 *output++ = FROM_16_TO_8(wOut[0]);
1262 *output++ = FROM_16_TO_8(wOut[1]);
1263 *output++ = FROM_16_TO_8(wOut[2]);
1270 cmsUInt8Number* Pack4BytesSwap(register _cmsTRANSFORM* info,
1271 register cmsUInt16Number wOut[],
1272 register cmsUInt8Number* output,
1273 register cmsUInt32Number Stride)
1275 *output++ = FROM_16_TO_8(wOut[3]);
1276 *output++ = FROM_16_TO_8(wOut[2]);
1277 *output++ = FROM_16_TO_8(wOut[1]);
1278 *output++ = FROM_16_TO_8(wOut[0]);
1284 cmsUInt8Number* Pack4BytesSwapSwapFirst(register _cmsTRANSFORM* info,
1285 register cmsUInt16Number wOut[],
1286 register cmsUInt8Number* output,
1287 register cmsUInt32Number Stride)
1289 *output++ = FROM_16_TO_8(wOut[2]);
1290 *output++ = FROM_16_TO_8(wOut[1]);
1291 *output++ = FROM_16_TO_8(wOut[0]);
1292 *output++ = FROM_16_TO_8(wOut[3]);
1298 cmsUInt8Number* Pack4Words(register _cmsTRANSFORM* info,
1299 register cmsUInt16Number wOut[],
1300 register cmsUInt8Number* output,
1301 register cmsUInt32Number Stride)
1303 *(cmsUInt16Number*) output = wOut[0];
1305 *(cmsUInt16Number*) output = wOut[1];
1307 *(cmsUInt16Number*) output = wOut[2];
1309 *(cmsUInt16Number*) output = wOut[3];
1316 cmsUInt8Number* Pack4WordsReverse(register _cmsTRANSFORM* info,
1317 register cmsUInt16Number wOut[],
1318 register cmsUInt8Number* output,
1319 register cmsUInt32Number Stride)
1321 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]);
1323 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[1]);
1325 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[2]);
1327 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[3]);
1335 cmsUInt8Number* Pack4WordsSwap(register _cmsTRANSFORM* info,
1336 register cmsUInt16Number wOut[],
1337 register cmsUInt8Number* output,
1338 register cmsUInt32Number Stride)
1340 *(cmsUInt16Number*) output = wOut[3];
1342 *(cmsUInt16Number*) output = wOut[2];
1344 *(cmsUInt16Number*) output = wOut[1];
1346 *(cmsUInt16Number*) output = wOut[0];
1354 cmsUInt8Number* Pack4WordsBigEndian(register _cmsTRANSFORM* info,
1355 register cmsUInt16Number wOut[],
1356 register cmsUInt8Number* output,
1357 register cmsUInt32Number Stride)
1359 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
1361 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]);
1363 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]);
1365 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[3]);
1373 cmsUInt8Number* PackLabV2_8(register _cmsTRANSFORM* info,
1374 register cmsUInt16Number wOut[],
1375 register cmsUInt8Number* output,
1376 register cmsUInt32Number Stride)
1378 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0]));
1379 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1]));
1380 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2]));
1386 cmsUInt8Number* PackALabV2_8(register _cmsTRANSFORM* info,
1387 register cmsUInt16Number wOut[],
1388 register cmsUInt8Number* output,
1389 register cmsUInt32Number Stride)
1392 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0]));
1393 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1]));
1394 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2]));
1400 cmsUInt8Number* PackLabV2_16(register _cmsTRANSFORM* info,
1401 register cmsUInt16Number wOut[],
1402 register cmsUInt8Number* output,
1403 register cmsUInt32Number Stride)
1405 *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[0]);
1407 *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[1]);
1409 *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[2]);
1416 cmsUInt8Number* Pack3Bytes(register _cmsTRANSFORM* info,
1417 register cmsUInt16Number wOut[],
1418 register cmsUInt8Number* output,
1419 register cmsUInt32Number Stride)
1421 *output++ = FROM_16_TO_8(wOut[0]);
1422 *output++ = FROM_16_TO_8(wOut[1]);
1423 *output++ = FROM_16_TO_8(wOut[2]);
1429 cmsUInt8Number* Pack3BytesOptimized(register _cmsTRANSFORM* info,
1430 register cmsUInt16Number wOut[],
1431 register cmsUInt8Number* output,
1432 register cmsUInt32Number Stride)
1434 *output++ = (wOut[0] & 0xFF);
1435 *output++ = (wOut[1] & 0xFF);
1436 *output++ = (wOut[2] & 0xFF);
1442 cmsUInt8Number* Pack3BytesSwap(register _cmsTRANSFORM* info,
1443 register cmsUInt16Number wOut[],
1444 register cmsUInt8Number* output,
1445 register cmsUInt32Number Stride)
1447 *output++ = FROM_16_TO_8(wOut[2]);
1448 *output++ = FROM_16_TO_8(wOut[1]);
1449 *output++ = FROM_16_TO_8(wOut[0]);
1455 cmsUInt8Number* Pack3BytesSwapOptimized(register _cmsTRANSFORM* info,
1456 register cmsUInt16Number wOut[],
1457 register cmsUInt8Number* output,
1458 register cmsUInt32Number Stride)
1460 *output++ = (wOut[2] & 0xFF);
1461 *output++ = (wOut[1] & 0xFF);
1462 *output++ = (wOut[0] & 0xFF);
1469 cmsUInt8Number* Pack3Words(register _cmsTRANSFORM* info,
1470 register cmsUInt16Number wOut[],
1471 register cmsUInt8Number* output,
1472 register cmsUInt32Number Stride)
1474 *(cmsUInt16Number*) output = wOut[0];
1476 *(cmsUInt16Number*) output = wOut[1];
1478 *(cmsUInt16Number*) output = wOut[2];
1485 cmsUInt8Number* Pack3WordsSwap(register _cmsTRANSFORM* info,
1486 register cmsUInt16Number wOut[],
1487 register cmsUInt8Number* output,
1488 register cmsUInt32Number Stride)
1490 *(cmsUInt16Number*) output = wOut[2];
1492 *(cmsUInt16Number*) output = wOut[1];
1494 *(cmsUInt16Number*) output = wOut[0];
1501 cmsUInt8Number* Pack3WordsBigEndian(register _cmsTRANSFORM* info,
1502 register cmsUInt16Number wOut[],
1503 register cmsUInt8Number* output,
1504 register cmsUInt32Number Stride)
1506 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
1508 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]);
1510 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]);
1517 cmsUInt8Number* Pack3BytesAndSkip1(register _cmsTRANSFORM* Info,
1518 register cmsUInt16Number wOut[],
1519 register cmsUInt8Number* output,
1520 register cmsUInt32Number Stride)
1522 *output++ = FROM_16_TO_8(wOut[0]);
1523 *output++ = FROM_16_TO_8(wOut[1]);
1524 *output++ = FROM_16_TO_8(wOut[2]);
1531 cmsUInt8Number* Pack3BytesAndSkip1Optimized(register _cmsTRANSFORM* Info,
1532 register cmsUInt16Number wOut[],
1533 register cmsUInt8Number* output,
1534 register cmsUInt32Number Stride)
1536 *output++ = (wOut[0] & 0xFF);
1537 *output++ = (wOut[1] & 0xFF);
1538 *output++ = (wOut[2] & 0xFF);
1546 cmsUInt8Number* Pack3BytesAndSkip1SwapFirst(register _cmsTRANSFORM* Info,
1547 register cmsUInt16Number wOut[],
1548 register cmsUInt8Number* output,
1549 register cmsUInt32Number Stride)
1552 *output++ = FROM_16_TO_8(wOut[0]);
1553 *output++ = FROM_16_TO_8(wOut[1]);
1554 *output++ = FROM_16_TO_8(wOut[2]);
1560 cmsUInt8Number* Pack3BytesAndSkip1SwapFirstOptimized(register _cmsTRANSFORM* Info,
1561 register cmsUInt16Number wOut[],
1562 register cmsUInt8Number* output,
1563 register cmsUInt32Number Stride)
1566 *output++ = (wOut[0] & 0xFF);
1567 *output++ = (wOut[1] & 0xFF);
1568 *output++ = (wOut[2] & 0xFF);
1574 cmsUInt8Number* Pack3BytesAndSkip1Swap(register _cmsTRANSFORM* Info,
1575 register cmsUInt16Number wOut[],
1576 register cmsUInt8Number* output,
1577 register cmsUInt32Number Stride)
1580 *output++ = FROM_16_TO_8(wOut[2]);
1581 *output++ = FROM_16_TO_8(wOut[1]);
1582 *output++ = FROM_16_TO_8(wOut[0]);
1588 cmsUInt8Number* Pack3BytesAndSkip1SwapOptimized(register _cmsTRANSFORM* Info,
1589 register cmsUInt16Number wOut[],
1590 register cmsUInt8Number* output,
1591 register cmsUInt32Number Stride)
1594 *output++ = (wOut[2] & 0xFF);
1595 *output++ = (wOut[1] & 0xFF);
1596 *output++ = (wOut[0] & 0xFF);
1603 cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirst(register _cmsTRANSFORM* Info,
1604 register cmsUInt16Number wOut[],
1605 register cmsUInt8Number* output,
1606 register cmsUInt32Number Stride)
1608 *output++ = FROM_16_TO_8(wOut[2]);
1609 *output++ = FROM_16_TO_8(wOut[1]);
1610 *output++ = FROM_16_TO_8(wOut[0]);
1617 cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirstOptimized(register _cmsTRANSFORM* Info,
1618 register cmsUInt16Number wOut[],
1619 register cmsUInt8Number* output,
1620 register cmsUInt32Number Stride)
1622 *output++ = (wOut[2] & 0xFF);
1623 *output++ = (wOut[1] & 0xFF);
1624 *output++ = (wOut[0] & 0xFF);
1631 cmsUInt8Number* Pack3WordsAndSkip1(register _cmsTRANSFORM* Info,
1632 register cmsUInt16Number wOut[],
1633 register cmsUInt8Number* output,
1634 register cmsUInt32Number Stride)
1636 *(cmsUInt16Number*) output = wOut[0];
1638 *(cmsUInt16Number*) output = wOut[1];
1640 *(cmsUInt16Number*) output = wOut[2];
1648 cmsUInt8Number* Pack3WordsAndSkip1Swap(register _cmsTRANSFORM* Info,
1649 register cmsUInt16Number wOut[],
1650 register cmsUInt8Number* output,
1651 register cmsUInt32Number Stride)
1654 *(cmsUInt16Number*) output = wOut[2];
1656 *(cmsUInt16Number*) output = wOut[1];
1658 *(cmsUInt16Number*) output = wOut[0];
1666 cmsUInt8Number* Pack3WordsAndSkip1SwapFirst(register _cmsTRANSFORM* Info,
1667 register cmsUInt16Number wOut[],
1668 register cmsUInt8Number* output,
1669 register cmsUInt32Number Stride)
1672 *(cmsUInt16Number*) output = wOut[0];
1674 *(cmsUInt16Number*) output = wOut[1];
1676 *(cmsUInt16Number*) output = wOut[2];
1684 cmsUInt8Number* Pack3WordsAndSkip1SwapSwapFirst(register _cmsTRANSFORM* Info,
1685 register cmsUInt16Number wOut[],
1686 register cmsUInt8Number* output,
1687 register cmsUInt32Number Stride)
1689 *(cmsUInt16Number*) output = wOut[2];
1691 *(cmsUInt16Number*) output = wOut[1];
1693 *(cmsUInt16Number*) output = wOut[0];
1703 cmsUInt8Number* Pack1Byte(register _cmsTRANSFORM* Info,
1704 register cmsUInt16Number wOut[],
1705 register cmsUInt8Number* output,
1706 register cmsUInt32Number Stride)
1708 *output++ = FROM_16_TO_8(wOut[0]);
1714 cmsUInt8Number* Pack1ByteReversed(register _cmsTRANSFORM* Info,
1715 register cmsUInt16Number wOut[],
1716 register cmsUInt8Number* output,
1717 register cmsUInt32Number Stride)
1719 *output++ = FROM_16_TO_8(REVERSE_FLAVOR_16(wOut[0]));
1725 cmsUInt8Number* Pack1ByteSkip1(register _cmsTRANSFORM* Info,
1726 register cmsUInt16Number wOut[],
1727 register cmsUInt8Number* output,
1728 register cmsUInt32Number Stride)
1730 *output++ = FROM_16_TO_8(wOut[0]);
1737 cmsUInt8Number* Pack1ByteSkip1SwapFirst(register _cmsTRANSFORM* Info,
1738 register cmsUInt16Number wOut[],
1739 register cmsUInt8Number* output,
1740 register cmsUInt32Number Stride)
1743 *output++ = FROM_16_TO_8(wOut[0]);
1749 cmsUInt8Number* Pack1Word(register _cmsTRANSFORM* Info,
1750 register cmsUInt16Number wOut[],
1751 register cmsUInt8Number* output,
1752 register cmsUInt32Number Stride)
1754 *(cmsUInt16Number*) output = wOut[0];
1762 cmsUInt8Number* Pack1WordReversed(register _cmsTRANSFORM* Info,
1763 register cmsUInt16Number wOut[],
1764 register cmsUInt8Number* output,
1765 register cmsUInt32Number Stride)
1767 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]);
1774 cmsUInt8Number* Pack1WordBigEndian(register _cmsTRANSFORM* Info,
1775 register cmsUInt16Number wOut[],
1776 register cmsUInt8Number* output,
1777 register cmsUInt32Number Stride)
1779 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
1787 cmsUInt8Number* Pack1WordSkip1(register _cmsTRANSFORM* Info,
1788 register cmsUInt16Number wOut[],
1789 register cmsUInt8Number* output,
1790 register cmsUInt32Number Stride)
1792 *(cmsUInt16Number*) output = wOut[0];
1799 cmsUInt8Number* Pack1WordSkip1SwapFirst(register _cmsTRANSFORM* Info,
1800 register cmsUInt16Number wOut[],
1801 register cmsUInt8Number* output,
1802 register cmsUInt32Number Stride)
1805 *(cmsUInt16Number*) output = wOut[0];
1812 // Unencoded Float values -- don't try optimize speed
1814 cmsUInt8Number* PackLabDoubleFrom16(register _cmsTRANSFORM* Info,
1815 register cmsUInt16Number wOut[],
1816 register cmsUInt8Number* output,
1817 register cmsUInt32Number Stride)
1820 if (T_PLANAR(Info -> OutputFormat)) {
1823 cmsFloat64Number* Out = (cmsFloat64Number*) output;
1824 cmsLabEncoded2Float(&Lab, wOut);
1827 Out[Stride] = Lab.a;
1828 Out[Stride*2] = Lab.b;
1830 return output + sizeof(cmsFloat64Number);
1834 cmsLabEncoded2Float((cmsCIELab*) output, wOut);
1835 return output + (sizeof(cmsCIELab) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
1841 cmsUInt8Number* PackXYZDoubleFrom16(register _cmsTRANSFORM* Info,
1842 register cmsUInt16Number wOut[],
1843 register cmsUInt8Number* output,
1844 register cmsUInt32Number Stride)
1846 if (T_PLANAR(Info -> OutputFormat)) {
1849 cmsFloat64Number* Out = (cmsFloat64Number*) output;
1850 cmsXYZEncoded2Float(&XYZ, wOut);
1853 Out[Stride] = XYZ.Y;
1854 Out[Stride*2] = XYZ.Z;
1856 return output + sizeof(cmsFloat64Number);
1861 cmsXYZEncoded2Float((cmsCIEXYZ*) output, wOut);
1863 return output + (sizeof(cmsCIEXYZ) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
1868 cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* Info,
1869 register cmsUInt16Number wOut[],
1870 register cmsUInt8Number* output,
1871 register cmsUInt32Number Stride)
1873 cmsFloat64Number* Inks = (cmsFloat64Number*) output;
1874 int nChan = T_CHANNELS(Info -> OutputFormat);
1876 cmsFloat64Number maximum = IsInkSpace(Info ->InputFormat) ? 655.35 : 65535.0;
1878 if (T_PLANAR(Info -> OutputFormat)) {
1880 for (i=0; i < nChan; i++) {
1882 Inks[i*Stride] = wOut[i] / maximum;
1885 return output + sizeof(cmsFloat64Number);
1889 for (i=0; i < nChan; i++) {
1891 Inks[i] = wOut[i] / maximum;
1895 return output + (nChan + T_EXTRA(Info ->OutputFormat)) * sizeof(cmsFloat64Number);
1901 cmsUInt8Number* PackFloatFrom16(register _cmsTRANSFORM* Info,
1902 register cmsUInt16Number wOut[],
1903 register cmsUInt8Number* output,
1904 register cmsUInt32Number Stride)
1906 cmsFloat32Number* Inks = (cmsFloat32Number*) output;
1907 int nChan = T_CHANNELS(Info -> OutputFormat);
1909 cmsFloat64Number maximum = IsInkSpace(Info ->OutputFormat) ? 655.35 : 65535.0;
1911 if (T_PLANAR(Info -> OutputFormat)) {
1913 for (i=0; i < nChan; i++) {
1915 Inks[i*Stride] = (cmsFloat32Number) (wOut[i] / maximum);
1918 return output + sizeof(cmsFloat32Number);
1922 for (i=0; i < nChan; i++) {
1924 Inks[i] = (cmsFloat32Number) (wOut[i] / maximum);
1928 return output + (nChan + T_EXTRA(Info ->OutputFormat)) * sizeof(cmsFloat32Number);
1934 // --------------------------------------------------------------------------------------------------------
1937 cmsUInt8Number* PackChunkyFloatsFromFloat(_cmsTRANSFORM* info,
1938 cmsFloat32Number wOut[],
1939 cmsUInt8Number* output,
1940 cmsUInt32Number Stride)
1942 int nChan = T_CHANNELS(info -> OutputFormat);
1943 int DoSwap = T_DOSWAP(info ->OutputFormat);
1944 int Reverse = T_FLAVOR(info ->OutputFormat);
1945 int Extra = T_EXTRA(info -> OutputFormat);
1946 int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
1947 int ExtraFirst = DoSwap && !SwapFirst;
1948 cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0;
1949 cmsFloat32Number* swap1;
1950 cmsFloat64Number v = 0;
1953 swap1 = (cmsFloat32Number*) output;
1956 output += Extra * sizeof(cmsFloat32Number);
1959 for (i=0; i < nChan; i++) {
1961 int index = DoSwap ? (nChan - i - 1) : i;
1963 v = wOut[index] * maximum;
1968 *(cmsFloat32Number*) output = (cmsFloat32Number) v;
1970 output += sizeof(cmsFloat32Number);
1974 output += Extra * sizeof(cmsFloat32Number);
1977 if (Extra == 0 && SwapFirst) {
1979 memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat32Number));
1980 *swap1 = (cmsFloat32Number) v;
1988 cmsUInt8Number* PackPlanarFloatsFromFloat(_cmsTRANSFORM* info,
1989 cmsFloat32Number wOut[],
1990 cmsUInt8Number* output,
1991 cmsUInt32Number Stride)
1993 int nChan = T_CHANNELS(info -> OutputFormat);
1994 int DoSwap = T_DOSWAP(info ->OutputFormat);
1995 int Reverse= T_FLAVOR(info ->OutputFormat);
1997 cmsUInt8Number* Init = output;
1998 cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0;
2002 output += T_EXTRA(info -> OutputFormat) * Stride * sizeof(cmsFloat32Number);
2005 for (i=0; i < nChan; i++) {
2007 int index = DoSwap ? (nChan - i - 1) : i;
2009 v = wOut[index] * maximum;
2014 *(cmsFloat32Number*) output = (cmsFloat32Number) v;
2015 output += (Stride * sizeof(cmsFloat32Number));
2018 return (Init + sizeof(cmsFloat32Number));
2023 cmsUInt8Number* PackChunkyDoublesFromFloat(_cmsTRANSFORM* info,
2024 cmsFloat32Number wOut[],
2025 cmsUInt8Number* output,
2026 cmsUInt32Number Stride)
2028 int nChan = T_CHANNELS(info -> OutputFormat);
2029 int DoSwap = T_DOSWAP(info ->OutputFormat);
2030 int Reverse = T_FLAVOR(info ->OutputFormat);
2031 int Extra = T_EXTRA(info -> OutputFormat);
2032 int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
2033 int ExtraFirst = DoSwap && !SwapFirst;
2034 cmsFloat64Number* swap1;
2035 cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0;
2036 cmsFloat64Number v = 0;
2039 swap1 = (cmsFloat64Number*) output;
2042 output += Extra * sizeof(cmsFloat64Number);
2045 for (i=0; i < nChan; i++) {
2047 int index = DoSwap ? (nChan - i - 1) : i;
2049 v = (cmsFloat64Number) wOut[index] * maximum;
2054 *(cmsFloat64Number*) output = v;
2056 output += sizeof(cmsFloat64Number);
2060 output += Extra * sizeof(cmsFloat64Number);
2063 if (Extra == 0 && SwapFirst) {
2065 memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number));
2074 cmsUInt8Number* PackPlanarDoublesFromFloat(_cmsTRANSFORM* info,
2075 cmsFloat32Number wOut[],
2076 cmsUInt8Number* output,
2077 cmsUInt32Number Stride)
2079 int nChan = T_CHANNELS(info -> OutputFormat);
2080 int DoSwap = T_DOSWAP(info ->OutputFormat);
2081 int Reverse= T_FLAVOR(info ->OutputFormat);
2083 cmsUInt8Number* Init = output;
2084 cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0;
2088 output += T_EXTRA(info -> OutputFormat) * Stride * sizeof(cmsFloat64Number);
2091 for (i=0; i < nChan; i++) {
2093 int index = DoSwap ? (nChan - i - 1) : i;
2095 v = (cmsFloat64Number) wOut[index] * maximum;
2100 *(cmsFloat64Number*) output = v;
2101 output += (Stride * sizeof(cmsFloat64Number));
2104 return (Init + sizeof(cmsFloat64Number));
2111 cmsUInt8Number* PackLabFloatFromFloat(_cmsTRANSFORM* Info,
2112 cmsFloat32Number wOut[],
2113 cmsUInt8Number* output,
2114 cmsUInt32Number Stride)
2116 cmsFloat32Number* Out = (cmsFloat32Number*) output;
2118 if (T_PLANAR(Info -> OutputFormat)) {
2120 Out[0] = (cmsFloat32Number) (wOut[0] * 100.0);
2121 Out[Stride] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0);
2122 Out[Stride*2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0);
2124 return output + sizeof(cmsFloat32Number);
2128 Out[0] = (cmsFloat32Number) (wOut[0] * 100.0);
2129 Out[1] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0);
2130 Out[2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0);
2132 return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
2138 cmsUInt8Number* PackLabDoubleFromFloat(_cmsTRANSFORM* Info,
2139 cmsFloat32Number wOut[],
2140 cmsUInt8Number* output,
2141 cmsUInt32Number Stride)
2143 cmsFloat64Number* Out = (cmsFloat64Number*) output;
2145 if (T_PLANAR(Info -> OutputFormat)) {
2147 Out[0] = (cmsFloat64Number) (wOut[0] * 100.0);
2148 Out[Stride] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0);
2149 Out[Stride*2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0);
2151 return output + sizeof(cmsFloat64Number);
2155 Out[0] = (cmsFloat64Number) (wOut[0] * 100.0);
2156 Out[1] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0);
2157 Out[2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0);
2159 return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
2165 // From 0..1 range to 0..MAX_ENCODEABLE_XYZ
2167 cmsUInt8Number* PackXYZFloatFromFloat(_cmsTRANSFORM* Info,
2168 cmsFloat32Number wOut[],
2169 cmsUInt8Number* output,
2170 cmsUInt32Number Stride)
2172 cmsFloat32Number* Out = (cmsFloat32Number*) output;
2174 if (T_PLANAR(Info -> OutputFormat)) {
2176 Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
2177 Out[Stride] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
2178 Out[Stride*2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
2180 return output + sizeof(cmsFloat32Number);
2184 Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
2185 Out[1] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
2186 Out[2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
2188 return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
2194 // Same, but convert to double
2196 cmsUInt8Number* PackXYZDoubleFromFloat(_cmsTRANSFORM* Info,
2197 cmsFloat32Number wOut[],
2198 cmsUInt8Number* output,
2199 cmsUInt32Number Stride)
2201 cmsFloat64Number* Out = (cmsFloat64Number*) output;
2203 if (T_PLANAR(Info -> OutputFormat)) {
2205 Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
2206 Out[Stride] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
2207 Out[Stride*2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
2209 return output + sizeof(cmsFloat64Number);
2213 Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
2214 Out[1] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
2215 Out[2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
2217 return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
2223 // ----------------------------------------------------------------------------------------------------------------
2226 static cmsFormatters16 InputFormatters16[] = {
2228 // Type Mask Function
2229 // ---------------------------- ------------------------------------ ----------------------------
2230 { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleTo16},
2231 { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleTo16},
2232 { TYPE_GRAY_DBL, 0, UnrollDouble1Chan},
2233 { FLOAT_SH(1)|BYTES_SH(0), ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, UnrollDoubleTo16},
2234 { FLOAT_SH(1)|BYTES_SH(4), ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, UnrollFloatTo16},
2237 { CHANNELS_SH(1)|BYTES_SH(1), ANYSPACE, Unroll1Byte},
2238 { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Unroll1ByteSkip1},
2239 { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(2), ANYSPACE, Unroll1ByteSkip2},
2240 { CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll1ByteReversed},
2241 { COLORSPACE_SH(PT_MCH2)|CHANNELS_SH(2)|BYTES_SH(1), 0, Unroll2Bytes},
2243 { TYPE_LabV2_8, 0, UnrollLabV2_8 },
2244 { TYPE_ALabV2_8, 0, UnrollALabV2_8 },
2245 { TYPE_LabV2_16, 0, UnrollLabV2_16 },
2247 { CHANNELS_SH(3)|BYTES_SH(1), ANYSPACE, Unroll3Bytes},
2248 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSwap},
2249 { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSkip1Swap},
2250 { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3BytesSkip1SwapFirst},
2252 { CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Unroll4Bytes},
2253 { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll4BytesReverse},
2254 { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapFirst},
2255 { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll4BytesSwap},
2256 { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapSwapFirst},
2258 { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarBytes},
2259 { BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollChunkyBytes},
2262 { CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Unroll1Word},
2263 { CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Unroll1WordReversed},
2264 { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(3), ANYSPACE, Unroll1WordSkip3},
2266 { CHANNELS_SH(2)|BYTES_SH(2), ANYSPACE, Unroll2Words},
2267 { CHANNELS_SH(3)|BYTES_SH(2), ANYSPACE, Unroll3Words},
2268 { CHANNELS_SH(4)|BYTES_SH(2), ANYSPACE, Unroll4Words},
2270 { CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Unroll3WordsSwap},
2271 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3WordsSkip1SwapFirst},
2272 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3WordsSkip1Swap},
2273 { CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Unroll4WordsReverse},
2274 { CHANNELS_SH(4)|BYTES_SH(2)|SWAPFIRST_SH(1), ANYSPACE, Unroll4WordsSwapFirst},
2275 { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Unroll4WordsSwap},
2276 { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4WordsSwapSwapFirst},
2279 { BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarWords },
2280 { BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollAnyWords},
2285 static cmsFormattersFloat InputFormattersFloat[] = {
2287 // Type Mask Function
2288 // ---------------------------- ------------------------------------ ----------------------------
2289 { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleToFloat},
2290 { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, UnrollLabFloatToFloat},
2291 { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleToFloat},
2292 { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, UnrollXYZFloatToFloat},
2294 { FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollFloatsToFloat},
2295 { FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollDoublesToFloat},
2299 // Bit fields set to one in the mask are not compared
2301 cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags)
2307 if (!(dwFlags & CMS_PACK_FLAGS_FLOAT)) {
2309 for (i=0; i < sizeof(InputFormatters16) / sizeof(cmsFormatters16); i++) {
2310 cmsFormatters16* f = InputFormatters16 + i;
2312 if ((dwInput & ~f ->Mask) == f ->Type) {
2319 for (i=0; i < sizeof(InputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {
2320 cmsFormattersFloat* f = InputFormattersFloat + i;
2322 if ((dwInput & ~f ->Mask) == f ->Type) {
2323 fr.FmtFloat = f ->Frm;
2333 static cmsFormatters16 OutputFormatters16[] = {
2334 // Type Mask Function
2335 // ---------------------------- ------------------------------------ ----------------------------
2337 { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, PackLabDoubleFrom16},
2338 { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFrom16},
2339 { FLOAT_SH(1)|BYTES_SH(0), ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackDoubleFrom16},
2340 { FLOAT_SH(1)|BYTES_SH(4), ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackFloatFrom16},
2342 { CHANNELS_SH(1)|BYTES_SH(1), ANYSPACE, Pack1Byte},
2343 { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Pack1ByteSkip1},
2344 { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack1ByteSkip1SwapFirst},
2346 { CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Pack1ByteReversed},
2348 { TYPE_LabV2_8, 0, PackLabV2_8 },
2349 { TYPE_ALabV2_8, 0, PackALabV2_8 },
2350 { TYPE_LabV2_16, 0, PackLabV2_16 },
2352 { CHANNELS_SH(3)|BYTES_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesOptimized},
2353 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesAndSkip1Optimized},
2354 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1),
2355 ANYSPACE, Pack3BytesAndSkip1SwapFirstOptimized},
2356 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1),
2357 ANYSPACE, Pack3BytesAndSkip1SwapSwapFirstOptimized},
2358 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1),
2359 ANYSPACE, Pack3BytesAndSkip1SwapOptimized},
2360 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesSwapOptimized},
2364 { CHANNELS_SH(3)|BYTES_SH(1), ANYSPACE, Pack3Bytes},
2365 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Pack3BytesAndSkip1},
2366 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack3BytesAndSkip1SwapFirst},
2367 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
2368 ANYSPACE, Pack3BytesAndSkip1SwapSwapFirst},
2369 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1), ANYSPACE, Pack3BytesAndSkip1Swap},
2370 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack3BytesSwap},
2371 { CHANNELS_SH(6)|BYTES_SH(1), ANYSPACE, Pack6Bytes},
2372 { CHANNELS_SH(6)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack6BytesSwap},
2373 { CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Pack4Bytes},
2374 { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Pack4BytesReverse},
2375 { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapFirst},
2376 { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack4BytesSwap},
2377 { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapSwapFirst},
2379 { BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyBytes},
2380 { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarBytes},
2382 { CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Pack1Word},
2383 { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1), ANYSPACE, Pack1WordSkip1},
2384 { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack1WordSkip1SwapFirst},
2385 { CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Pack1WordReversed},
2386 { CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack1WordBigEndian},
2387 { CHANNELS_SH(3)|BYTES_SH(2), ANYSPACE, Pack3Words},
2388 { CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack3WordsSwap},
2389 { CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack3WordsBigEndian},
2390 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1), ANYSPACE, Pack3WordsAndSkip1},
2391 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack3WordsAndSkip1Swap},
2392 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack3WordsAndSkip1SwapFirst},
2394 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
2395 ANYSPACE, Pack3WordsAndSkip1SwapSwapFirst},
2397 { CHANNELS_SH(4)|BYTES_SH(2), ANYSPACE, Pack4Words},
2398 { CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Pack4WordsReverse},
2399 { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack4WordsSwap},
2400 { CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack4WordsBigEndian},
2402 { CHANNELS_SH(6)|BYTES_SH(2), ANYSPACE, Pack6Words},
2403 { CHANNELS_SH(6)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack6WordsSwap},
2405 { BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYENDIAN|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarWords},
2406 { BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyWords}
2411 static cmsFormattersFloat OutputFormattersFloat[] = {
2412 // Type Mask Function
2413 // ---------------------------- --------------------------------------------------- ----------------------------
2414 { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFromFloat},
2415 { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, PackXYZFloatFromFloat},
2416 { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, PackLabDoubleFromFloat},
2417 { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFromFloat},
2418 { FLOAT_SH(1)|BYTES_SH(4),
2419 ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackChunkyFloatsFromFloat },
2420 { FLOAT_SH(1)|BYTES_SH(4)|PLANAR_SH(1), ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarFloatsFromFloat},
2421 { FLOAT_SH(1)|BYTES_SH(0),
2422 ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackChunkyDoublesFromFloat },
2423 { FLOAT_SH(1)|BYTES_SH(0)|PLANAR_SH(1), ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarDoublesFromFloat},
2429 // Bit fields set to one in the mask are not compared
2430 cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags)
2436 if (dwFlags & CMS_PACK_FLAGS_FLOAT) {
2438 for (i=0; i < sizeof(OutputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {
2439 cmsFormattersFloat* f = OutputFormattersFloat + i;
2441 if ((dwInput & ~f ->Mask) == f ->Type) {
2442 fr.FmtFloat = f ->Frm;
2450 for (i=0; i < sizeof(OutputFormatters16) / sizeof(cmsFormatters16); i++) {
2451 cmsFormatters16* f = OutputFormatters16 + i;
2453 if ((dwInput & ~f ->Mask) == f ->Type) {
2465 typedef struct _cms_formatters_factory_list {
2467 cmsFormatterFactory Factory;
2468 struct _cms_formatters_factory_list *Next;
2470 } cmsFormattersFactoryList;
2472 static cmsFormattersFactoryList* FactoryList = NULL;
2475 // Formatters management
2476 cmsBool _cmsRegisterFormattersPlugin(cmsPluginBase* Data)
2478 cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data;
2479 cmsFormattersFactoryList* fl ;
2488 fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(sizeof(cmsFormattersFactoryList));
2489 if (fl == NULL) return FALSE;
2491 fl ->Factory = Plugin ->FormattersFactory;
2493 fl ->Next = FactoryList;
2499 cmsFormatter _cmsGetFormatter(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8
2500 cmsFormatterDirection Dir,
2501 cmsUInt32Number dwFlags) // Float or 16 bits
2503 cmsFormattersFactoryList* f;
2505 for (f = FactoryList; f != NULL; f = f ->Next) {
2507 cmsFormatter fn = f ->Factory(Type, Dir, dwFlags);
2508 if (fn.Fmt16 != NULL) return fn;
2511 // Revert to default
2512 if (Dir == cmsFormatterInput)
2513 return _cmsGetStockInputFormatter(Type, dwFlags);
2515 return _cmsGetStockOutputFormatter(Type, dwFlags);
2519 // Return whatever given formatter refers to float values
2520 cmsBool _cmsFormatterIsFloat(cmsUInt32Number Type)
2522 return T_FLOAT(Type) ? TRUE : FALSE;
2525 // Return whatever given formatter refers to 8 bits
2526 cmsBool _cmsFormatterIs8bit(cmsUInt32Number Type)
2528 int Bytes = T_BYTES(Type);
2530 return (Bytes == 1);
2533 // Build a suitable formatter for the colorspace of this profile
2534 cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat)
2537 cmsColorSpaceSignature ColorSpace = cmsGetColorSpace(hProfile);
2538 cmsUInt32Number ColorSpaceBits = _cmsLCMScolorSpace(ColorSpace);
2539 cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace);
2540 cmsUInt32Number Float = lIsFloat ? 1 : 0;
2542 // Create a fake formatter for result
2543 return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
2546 // Build a suitable formatter for the colorspace of this profile
2547 cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat)
2550 cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile);
2551 int ColorSpaceBits = _cmsLCMScolorSpace(ColorSpace);
2552 cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace);
2553 cmsUInt32Number Float = lIsFloat ? 1 : 0;
2555 // Create a fake formatter for result
2556 return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);