dmime: Implement band track IDirectMusicTrack_Play.
[wine.git] / libs / lcms2 / src / cmspack.c
blob5a96712a485adfe24a952b3c0571cf4d10ebd65a
1 //---------------------------------------------------------------------------------
2 //
3 // Little Color Management System
4 // Copyright (c) 1998-2023 Marti Maria Saguer
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the Software
11 // is furnished to do so, subject to the following conditions:
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
32 // as special case)
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)
47 int a = (x << 8 | x) >> 8; // * 257 / 256
48 if ( a > 0xffff) return 0xffff;
49 return (cmsUInt16Number) a;
52 // * 0xf00 / 0xffff = * 256 / 257
53 cmsINLINE cmsUInt16Number FomLabV4ToLabV2(cmsUInt16Number x)
55 return (cmsUInt16Number) (((x << 8) + 0x80) / 257);
59 typedef struct {
60 cmsUInt32Number Type;
61 cmsUInt32Number Mask;
62 cmsFormatter16 Frm;
64 } cmsFormatters16;
66 typedef struct {
67 cmsUInt32Number Type;
68 cmsUInt32Number Mask;
69 cmsFormatterFloat Frm;
71 } cmsFormattersFloat;
74 #define ANYSPACE COLORSPACE_SH(31)
75 #define ANYCHANNELS CHANNELS_SH(15)
76 #define ANYEXTRA EXTRA_SH(7)
77 #define ANYPLANAR PLANAR_SH(1)
78 #define ANYENDIAN ENDIAN16_SH(1)
79 #define ANYSWAP DOSWAP_SH(1)
80 #define ANYSWAPFIRST SWAPFIRST_SH(1)
81 #define ANYFLAVOR FLAVOR_SH(1)
82 #define ANYPREMUL PREMUL_SH(1)
85 // Suppress waning about info never being used
87 #ifdef _MSC_VER
88 #pragma warning(disable : 4100)
89 #endif
91 // Unpacking routines (16 bits) ----------------------------------------------------------------------------------------
94 // Does almost everything but is slow
95 static
96 cmsUInt8Number* UnrollChunkyBytes(CMSREGISTER _cmsTRANSFORM* info,
97 CMSREGISTER cmsUInt16Number wIn[],
98 CMSREGISTER cmsUInt8Number* accum,
99 CMSREGISTER cmsUInt32Number Stride)
101 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
102 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);
103 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
104 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);
105 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);
106 cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
108 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
109 cmsUInt32Number v;
110 cmsUInt32Number i;
111 cmsUInt32Number alpha_factor = 1;
113 if (ExtraFirst) {
115 if (Premul && Extra)
116 alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[0]));
118 accum += Extra;
120 else
122 if (Premul && Extra)
123 alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[nChan]));
126 for (i=0; i < nChan; i++) {
128 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
130 v = FROM_8_TO_16(*accum);
131 v = Reverse ? REVERSE_FLAVOR_16(v) : v;
133 if (Premul && alpha_factor > 0)
135 v = ((cmsUInt32Number)((cmsUInt32Number)v << 16) / alpha_factor);
136 if (v > 0xffff) v = 0xffff;
139 wIn[index] = (cmsUInt16Number) v;
140 accum++;
143 if (!ExtraFirst) {
144 accum += Extra;
147 if (Extra == 0 && SwapFirst) {
148 cmsUInt16Number tmp = wIn[0];
150 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
151 wIn[nChan-1] = tmp;
154 return accum;
156 cmsUNUSED_PARAMETER(info);
157 cmsUNUSED_PARAMETER(Stride);
162 // Extra channels are just ignored because come in the next planes
163 static
164 cmsUInt8Number* UnrollPlanarBytes(CMSREGISTER _cmsTRANSFORM* info,
165 CMSREGISTER cmsUInt16Number wIn[],
166 CMSREGISTER cmsUInt8Number* accum,
167 CMSREGISTER cmsUInt32Number Stride)
169 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
170 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);
171 cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->InputFormat);
172 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
173 cmsUInt32Number i;
174 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
175 cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
176 cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
177 cmsUInt8Number* Init = accum;
178 cmsUInt32Number alpha_factor = 1;
180 if (ExtraFirst) {
182 if (Premul && Extra)
183 alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[0]));
186 accum += Extra * Stride;
188 else
190 if (Premul && Extra)
191 alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[(nChan) * Stride]));
194 for (i=0; i < nChan; i++) {
196 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
197 cmsUInt32Number v = FROM_8_TO_16(*accum);
199 v = Reverse ? REVERSE_FLAVOR_16(v) : v;
201 if (Premul && alpha_factor > 0)
203 v = ((cmsUInt32Number)((cmsUInt32Number)v << 16) / alpha_factor);
204 if (v > 0xffff) v = 0xffff;
207 wIn[index] = (cmsUInt16Number) v;
208 accum += Stride;
211 return (Init + 1);
215 // Special cases, provided for performance
216 static
217 cmsUInt8Number* Unroll4Bytes(CMSREGISTER _cmsTRANSFORM* info,
218 CMSREGISTER cmsUInt16Number wIn[],
219 CMSREGISTER cmsUInt8Number* accum,
220 CMSREGISTER cmsUInt32Number Stride)
222 wIn[0] = FROM_8_TO_16(*accum); accum++; // C
223 wIn[1] = FROM_8_TO_16(*accum); accum++; // M
224 wIn[2] = FROM_8_TO_16(*accum); accum++; // Y
225 wIn[3] = FROM_8_TO_16(*accum); accum++; // K
227 return accum;
229 cmsUNUSED_PARAMETER(info);
230 cmsUNUSED_PARAMETER(Stride);
233 static
234 cmsUInt8Number* Unroll4BytesReverse(CMSREGISTER _cmsTRANSFORM* info,
235 CMSREGISTER cmsUInt16Number wIn[],
236 CMSREGISTER cmsUInt8Number* accum,
237 CMSREGISTER cmsUInt32Number Stride)
239 wIn[0] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // C
240 wIn[1] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // M
241 wIn[2] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // Y
242 wIn[3] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // K
244 return accum;
246 cmsUNUSED_PARAMETER(info);
247 cmsUNUSED_PARAMETER(Stride);
250 static
251 cmsUInt8Number* Unroll4BytesSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
252 CMSREGISTER cmsUInt16Number wIn[],
253 CMSREGISTER cmsUInt8Number* accum,
254 CMSREGISTER cmsUInt32Number Stride)
256 wIn[3] = FROM_8_TO_16(*accum); accum++; // K
257 wIn[0] = FROM_8_TO_16(*accum); accum++; // C
258 wIn[1] = FROM_8_TO_16(*accum); accum++; // M
259 wIn[2] = FROM_8_TO_16(*accum); accum++; // Y
261 return accum;
263 cmsUNUSED_PARAMETER(info);
264 cmsUNUSED_PARAMETER(Stride);
267 // KYMC
268 static
269 cmsUInt8Number* Unroll4BytesSwap(CMSREGISTER _cmsTRANSFORM* info,
270 CMSREGISTER cmsUInt16Number wIn[],
271 CMSREGISTER cmsUInt8Number* accum,
272 CMSREGISTER cmsUInt32Number Stride)
274 wIn[3] = FROM_8_TO_16(*accum); accum++; // K
275 wIn[2] = FROM_8_TO_16(*accum); accum++; // Y
276 wIn[1] = FROM_8_TO_16(*accum); accum++; // M
277 wIn[0] = FROM_8_TO_16(*accum); accum++; // C
279 return accum;
281 cmsUNUSED_PARAMETER(info);
282 cmsUNUSED_PARAMETER(Stride);
285 static
286 cmsUInt8Number* Unroll4BytesSwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
287 CMSREGISTER cmsUInt16Number wIn[],
288 CMSREGISTER cmsUInt8Number* accum,
289 CMSREGISTER cmsUInt32Number Stride)
291 wIn[2] = FROM_8_TO_16(*accum); accum++; // K
292 wIn[1] = FROM_8_TO_16(*accum); accum++; // Y
293 wIn[0] = FROM_8_TO_16(*accum); accum++; // M
294 wIn[3] = FROM_8_TO_16(*accum); accum++; // C
296 return accum;
298 cmsUNUSED_PARAMETER(info);
299 cmsUNUSED_PARAMETER(Stride);
302 static
303 cmsUInt8Number* Unroll3Bytes(CMSREGISTER _cmsTRANSFORM* info,
304 CMSREGISTER cmsUInt16Number wIn[],
305 CMSREGISTER cmsUInt8Number* accum,
306 CMSREGISTER cmsUInt32Number Stride)
308 wIn[0] = FROM_8_TO_16(*accum); accum++; // R
309 wIn[1] = FROM_8_TO_16(*accum); accum++; // G
310 wIn[2] = FROM_8_TO_16(*accum); accum++; // B
312 return accum;
314 cmsUNUSED_PARAMETER(info);
315 cmsUNUSED_PARAMETER(Stride);
318 static
319 cmsUInt8Number* Unroll3BytesSkip1Swap(CMSREGISTER _cmsTRANSFORM* info,
320 CMSREGISTER cmsUInt16Number wIn[],
321 CMSREGISTER cmsUInt8Number* accum,
322 CMSREGISTER cmsUInt32Number Stride)
324 accum++; // A
325 wIn[2] = FROM_8_TO_16(*accum); accum++; // B
326 wIn[1] = FROM_8_TO_16(*accum); accum++; // G
327 wIn[0] = FROM_8_TO_16(*accum); accum++; // R
329 return accum;
331 cmsUNUSED_PARAMETER(info);
332 cmsUNUSED_PARAMETER(Stride);
335 static
336 cmsUInt8Number* Unroll3BytesSkip1SwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
337 CMSREGISTER cmsUInt16Number wIn[],
338 CMSREGISTER cmsUInt8Number* accum,
339 CMSREGISTER cmsUInt32Number Stride)
341 wIn[2] = FROM_8_TO_16(*accum); accum++; // B
342 wIn[1] = FROM_8_TO_16(*accum); accum++; // G
343 wIn[0] = FROM_8_TO_16(*accum); accum++; // R
344 accum++; // A
346 return accum;
348 cmsUNUSED_PARAMETER(info);
349 cmsUNUSED_PARAMETER(Stride);
352 static
353 cmsUInt8Number* Unroll3BytesSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,
354 CMSREGISTER cmsUInt16Number wIn[],
355 CMSREGISTER cmsUInt8Number* accum,
356 CMSREGISTER cmsUInt32Number Stride)
358 accum++; // A
359 wIn[0] = FROM_8_TO_16(*accum); accum++; // R
360 wIn[1] = FROM_8_TO_16(*accum); accum++; // G
361 wIn[2] = FROM_8_TO_16(*accum); accum++; // B
363 return accum;
365 cmsUNUSED_PARAMETER(info);
366 cmsUNUSED_PARAMETER(Stride);
370 // BRG
371 static
372 cmsUInt8Number* Unroll3BytesSwap(CMSREGISTER _cmsTRANSFORM* info,
373 CMSREGISTER cmsUInt16Number wIn[],
374 CMSREGISTER cmsUInt8Number* accum,
375 CMSREGISTER cmsUInt32Number Stride)
377 wIn[2] = FROM_8_TO_16(*accum); accum++; // B
378 wIn[1] = FROM_8_TO_16(*accum); accum++; // G
379 wIn[0] = FROM_8_TO_16(*accum); accum++; // R
381 return accum;
383 cmsUNUSED_PARAMETER(info);
384 cmsUNUSED_PARAMETER(Stride);
387 static
388 cmsUInt8Number* UnrollLabV2_8(CMSREGISTER _cmsTRANSFORM* info,
389 CMSREGISTER cmsUInt16Number wIn[],
390 CMSREGISTER cmsUInt8Number* accum,
391 CMSREGISTER cmsUInt32Number Stride)
393 wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L
394 wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a
395 wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b
397 return accum;
399 cmsUNUSED_PARAMETER(info);
400 cmsUNUSED_PARAMETER(Stride);
403 static
404 cmsUInt8Number* UnrollALabV2_8(CMSREGISTER _cmsTRANSFORM* info,
405 CMSREGISTER cmsUInt16Number wIn[],
406 CMSREGISTER cmsUInt8Number* accum,
407 CMSREGISTER cmsUInt32Number Stride)
409 accum++; // A
410 wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L
411 wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a
412 wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b
414 return accum;
416 cmsUNUSED_PARAMETER(info);
417 cmsUNUSED_PARAMETER(Stride);
420 static
421 cmsUInt8Number* UnrollLabV2_16(CMSREGISTER _cmsTRANSFORM* info,
422 CMSREGISTER cmsUInt16Number wIn[],
423 CMSREGISTER cmsUInt8Number* accum,
424 CMSREGISTER cmsUInt32Number Stride)
426 wIn[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // L
427 wIn[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // a
428 wIn[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // b
430 return accum;
432 cmsUNUSED_PARAMETER(info);
433 cmsUNUSED_PARAMETER(Stride);
436 // for duplex
437 static
438 cmsUInt8Number* Unroll2Bytes(CMSREGISTER _cmsTRANSFORM* info,
439 CMSREGISTER cmsUInt16Number wIn[],
440 CMSREGISTER cmsUInt8Number* accum,
441 CMSREGISTER cmsUInt32Number Stride)
443 wIn[0] = FROM_8_TO_16(*accum); accum++; // ch1
444 wIn[1] = FROM_8_TO_16(*accum); accum++; // ch2
446 return accum;
448 cmsUNUSED_PARAMETER(info);
449 cmsUNUSED_PARAMETER(Stride);
455 // Monochrome duplicates L into RGB for null-transforms
456 static
457 cmsUInt8Number* Unroll1Byte(CMSREGISTER _cmsTRANSFORM* info,
458 CMSREGISTER cmsUInt16Number wIn[],
459 CMSREGISTER cmsUInt8Number* accum,
460 CMSREGISTER cmsUInt32Number Stride)
462 wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L
464 return accum;
466 cmsUNUSED_PARAMETER(info);
467 cmsUNUSED_PARAMETER(Stride);
471 static
472 cmsUInt8Number* Unroll1ByteSkip1(CMSREGISTER _cmsTRANSFORM* info,
473 CMSREGISTER cmsUInt16Number wIn[],
474 CMSREGISTER cmsUInt8Number* accum,
475 CMSREGISTER cmsUInt32Number Stride)
477 wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L
478 accum += 1;
480 return accum;
482 cmsUNUSED_PARAMETER(info);
483 cmsUNUSED_PARAMETER(Stride);
486 static
487 cmsUInt8Number* Unroll1ByteSkip2(CMSREGISTER _cmsTRANSFORM* info,
488 CMSREGISTER cmsUInt16Number wIn[],
489 CMSREGISTER cmsUInt8Number* accum,
490 CMSREGISTER cmsUInt32Number Stride)
492 wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L
493 accum += 2;
495 return accum;
497 cmsUNUSED_PARAMETER(info);
498 cmsUNUSED_PARAMETER(Stride);
501 static
502 cmsUInt8Number* Unroll1ByteReversed(CMSREGISTER _cmsTRANSFORM* info,
503 CMSREGISTER cmsUInt16Number wIn[],
504 CMSREGISTER cmsUInt8Number* accum,
505 CMSREGISTER cmsUInt32Number Stride)
507 wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(FROM_8_TO_16(*accum)); accum++; // L
509 return accum;
511 cmsUNUSED_PARAMETER(info);
512 cmsUNUSED_PARAMETER(Stride);
516 static
517 cmsUInt8Number* UnrollAnyWords(CMSREGISTER _cmsTRANSFORM* info,
518 CMSREGISTER cmsUInt16Number wIn[],
519 CMSREGISTER cmsUInt8Number* accum,
520 CMSREGISTER cmsUInt32Number Stride)
522 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
523 cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);
524 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);
525 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
526 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);
527 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);
528 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
529 cmsUInt32Number i;
531 if (ExtraFirst) {
532 accum += Extra * sizeof(cmsUInt16Number);
535 for (i=0; i < nChan; i++) {
537 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
538 cmsUInt16Number v = *(cmsUInt16Number*) accum;
540 if (SwapEndian)
541 v = CHANGE_ENDIAN(v);
543 wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;
545 accum += sizeof(cmsUInt16Number);
548 if (!ExtraFirst) {
549 accum += Extra * sizeof(cmsUInt16Number);
552 if (Extra == 0 && SwapFirst) {
554 cmsUInt16Number tmp = wIn[0];
556 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
557 wIn[nChan-1] = tmp;
560 return accum;
562 cmsUNUSED_PARAMETER(Stride);
566 static
567 cmsUInt8Number* UnrollAnyWordsPremul(CMSREGISTER _cmsTRANSFORM* info,
568 CMSREGISTER cmsUInt16Number wIn[],
569 CMSREGISTER cmsUInt8Number* accum,
570 CMSREGISTER cmsUInt32Number Stride)
572 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
573 cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);
574 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);
575 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
576 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);
577 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
578 cmsUInt32Number i;
580 cmsUInt16Number alpha = (ExtraFirst ? accum[0] : accum[nChan - 1]);
581 cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));
583 if (ExtraFirst) {
584 accum += sizeof(cmsUInt16Number);
587 for (i=0; i < nChan; i++) {
589 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
590 cmsUInt32Number v = *(cmsUInt16Number*) accum;
592 if (SwapEndian)
593 v = CHANGE_ENDIAN(v);
595 if (alpha_factor > 0) {
597 v = (v << 16) / alpha_factor;
598 if (v > 0xffff) v = 0xffff;
601 wIn[index] = (cmsUInt16Number) (Reverse ? REVERSE_FLAVOR_16(v) : v);
603 accum += sizeof(cmsUInt16Number);
606 if (!ExtraFirst) {
607 accum += sizeof(cmsUInt16Number);
610 return accum;
612 cmsUNUSED_PARAMETER(Stride);
617 static
618 cmsUInt8Number* UnrollPlanarWords(CMSREGISTER _cmsTRANSFORM* info,
619 CMSREGISTER cmsUInt16Number wIn[],
620 CMSREGISTER cmsUInt8Number* accum,
621 CMSREGISTER cmsUInt32Number Stride)
623 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
624 cmsUInt32Number DoSwap= T_DOSWAP(info ->InputFormat);
625 cmsUInt32Number Reverse= T_FLAVOR(info ->InputFormat);
626 cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);
627 cmsUInt32Number i;
628 cmsUInt8Number* Init = accum;
630 if (DoSwap) {
631 accum += T_EXTRA(info -> InputFormat) * Stride;
634 for (i=0; i < nChan; i++) {
636 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
637 cmsUInt16Number v = *(cmsUInt16Number*) accum;
639 if (SwapEndian)
640 v = CHANGE_ENDIAN(v);
642 wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;
644 accum += Stride;
647 return (Init + sizeof(cmsUInt16Number));
650 static
651 cmsUInt8Number* UnrollPlanarWordsPremul(CMSREGISTER _cmsTRANSFORM* info,
652 CMSREGISTER cmsUInt16Number wIn[],
653 CMSREGISTER cmsUInt8Number* accum,
654 CMSREGISTER cmsUInt32Number Stride)
656 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
657 cmsUInt32Number DoSwap= T_DOSWAP(info ->InputFormat);
658 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
659 cmsUInt32Number Reverse= T_FLAVOR(info ->InputFormat);
660 cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);
661 cmsUInt32Number i;
662 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
663 cmsUInt8Number* Init = accum;
665 cmsUInt16Number alpha = (ExtraFirst ? accum[0] : accum[(nChan - 1) * Stride]);
666 cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));
668 if (ExtraFirst) {
669 accum += Stride;
672 for (i=0; i < nChan; i++) {
674 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
675 cmsUInt32Number v = (cmsUInt32Number) *(cmsUInt16Number*) accum;
677 if (SwapEndian)
678 v = CHANGE_ENDIAN(v);
680 if (alpha_factor > 0) {
682 v = (v << 16) / alpha_factor;
683 if (v > 0xffff) v = 0xffff;
686 wIn[index] = (cmsUInt16Number) (Reverse ? REVERSE_FLAVOR_16(v) : v);
688 accum += Stride;
691 return (Init + sizeof(cmsUInt16Number));
694 static
695 cmsUInt8Number* Unroll4Words(CMSREGISTER _cmsTRANSFORM* info,
696 CMSREGISTER cmsUInt16Number wIn[],
697 CMSREGISTER cmsUInt8Number* accum,
698 CMSREGISTER cmsUInt32Number Stride)
700 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
701 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
702 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
703 wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
705 return accum;
707 cmsUNUSED_PARAMETER(info);
708 cmsUNUSED_PARAMETER(Stride);
711 static
712 cmsUInt8Number* Unroll4WordsReverse(CMSREGISTER _cmsTRANSFORM* info,
713 CMSREGISTER cmsUInt16Number wIn[],
714 CMSREGISTER cmsUInt8Number* accum,
715 CMSREGISTER cmsUInt32Number Stride)
717 wIn[0] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // C
718 wIn[1] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // M
719 wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // Y
720 wIn[3] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // K
722 return accum;
724 cmsUNUSED_PARAMETER(info);
725 cmsUNUSED_PARAMETER(Stride);
728 static
729 cmsUInt8Number* Unroll4WordsSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
730 CMSREGISTER cmsUInt16Number wIn[],
731 CMSREGISTER cmsUInt8Number* accum,
732 CMSREGISTER cmsUInt32Number Stride)
734 wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
735 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
736 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
737 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
739 return accum;
741 cmsUNUSED_PARAMETER(info);
742 cmsUNUSED_PARAMETER(Stride);
745 // KYMC
746 static
747 cmsUInt8Number* Unroll4WordsSwap(CMSREGISTER _cmsTRANSFORM* info,
748 CMSREGISTER cmsUInt16Number wIn[],
749 CMSREGISTER cmsUInt8Number* accum,
750 CMSREGISTER cmsUInt32Number Stride)
752 wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
753 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
754 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
755 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
757 return accum;
759 cmsUNUSED_PARAMETER(info);
760 cmsUNUSED_PARAMETER(Stride);
763 static
764 cmsUInt8Number* Unroll4WordsSwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
765 CMSREGISTER cmsUInt16Number wIn[],
766 CMSREGISTER cmsUInt8Number* accum,
767 CMSREGISTER cmsUInt32Number Stride)
769 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // K
770 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // Y
771 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // M
772 wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // C
774 return accum;
776 cmsUNUSED_PARAMETER(info);
777 cmsUNUSED_PARAMETER(Stride);
780 static
781 cmsUInt8Number* Unroll3Words(CMSREGISTER _cmsTRANSFORM* info,
782 CMSREGISTER cmsUInt16Number wIn[],
783 CMSREGISTER cmsUInt8Number* accum,
784 CMSREGISTER cmsUInt32Number Stride)
786 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C R
787 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M G
788 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y B
790 return accum;
792 cmsUNUSED_PARAMETER(info);
793 cmsUNUSED_PARAMETER(Stride);
796 static
797 cmsUInt8Number* Unroll3WordsSwap(CMSREGISTER _cmsTRANSFORM* info,
798 CMSREGISTER cmsUInt16Number wIn[],
799 CMSREGISTER cmsUInt8Number* accum,
800 CMSREGISTER cmsUInt32Number Stride)
802 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // C R
803 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M G
804 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // Y B
806 return accum;
808 cmsUNUSED_PARAMETER(info);
809 cmsUNUSED_PARAMETER(Stride);
812 static
813 cmsUInt8Number* Unroll3WordsSkip1Swap(CMSREGISTER _cmsTRANSFORM* info,
814 CMSREGISTER cmsUInt16Number wIn[],
815 CMSREGISTER cmsUInt8Number* accum,
816 CMSREGISTER cmsUInt32Number Stride)
818 accum += 2; // A
819 wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // R
820 wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G
821 wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // B
823 return accum;
825 cmsUNUSED_PARAMETER(info);
826 cmsUNUSED_PARAMETER(Stride);
829 static
830 cmsUInt8Number* Unroll3WordsSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,
831 CMSREGISTER cmsUInt16Number wIn[],
832 CMSREGISTER cmsUInt8Number* accum,
833 CMSREGISTER cmsUInt32Number Stride)
835 accum += 2; // A
836 wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // R
837 wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G
838 wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // B
840 return accum;
842 cmsUNUSED_PARAMETER(info);
843 cmsUNUSED_PARAMETER(Stride);
846 static
847 cmsUInt8Number* Unroll1Word(CMSREGISTER _cmsTRANSFORM* info,
848 CMSREGISTER cmsUInt16Number wIn[],
849 CMSREGISTER cmsUInt8Number* accum,
850 CMSREGISTER cmsUInt32Number Stride)
852 wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // L
854 return accum;
856 cmsUNUSED_PARAMETER(info);
857 cmsUNUSED_PARAMETER(Stride);
860 static
861 cmsUInt8Number* Unroll1WordReversed(CMSREGISTER _cmsTRANSFORM* info,
862 CMSREGISTER cmsUInt16Number wIn[],
863 CMSREGISTER cmsUInt8Number* accum,
864 CMSREGISTER cmsUInt32Number Stride)
866 wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2;
868 return accum;
870 cmsUNUSED_PARAMETER(info);
871 cmsUNUSED_PARAMETER(Stride);
874 static
875 cmsUInt8Number* Unroll1WordSkip3(CMSREGISTER _cmsTRANSFORM* info,
876 CMSREGISTER cmsUInt16Number wIn[],
877 CMSREGISTER cmsUInt8Number* accum,
878 CMSREGISTER cmsUInt32Number Stride)
880 wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum;
882 accum += 8;
884 return accum;
886 cmsUNUSED_PARAMETER(info);
887 cmsUNUSED_PARAMETER(Stride);
890 static
891 cmsUInt8Number* Unroll2Words(CMSREGISTER _cmsTRANSFORM* info,
892 CMSREGISTER cmsUInt16Number wIn[],
893 CMSREGISTER cmsUInt8Number* accum,
894 CMSREGISTER cmsUInt32Number Stride)
896 wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // ch1
897 wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // ch2
899 return accum;
901 cmsUNUSED_PARAMETER(info);
902 cmsUNUSED_PARAMETER(Stride);
906 // This is a conversion of Lab double to 16 bits
907 static
908 cmsUInt8Number* UnrollLabDoubleTo16(CMSREGISTER _cmsTRANSFORM* info,
909 CMSREGISTER cmsUInt16Number wIn[],
910 CMSREGISTER cmsUInt8Number* accum,
911 CMSREGISTER cmsUInt32Number Stride)
913 if (T_PLANAR(info -> InputFormat)) {
915 cmsCIELab Lab;
916 cmsUInt8Number* pos_L;
917 cmsUInt8Number* pos_a;
918 cmsUInt8Number* pos_b;
920 pos_L = accum;
921 pos_a = accum + Stride;
922 pos_b = accum + Stride * 2;
924 Lab.L = *(cmsFloat64Number*) pos_L;
925 Lab.a = *(cmsFloat64Number*) pos_a;
926 Lab.b = *(cmsFloat64Number*) pos_b;
928 cmsFloat2LabEncoded(wIn, &Lab);
929 return accum + sizeof(cmsFloat64Number);
931 else {
933 cmsFloat2LabEncoded(wIn, (cmsCIELab*) accum);
934 accum += sizeof(cmsCIELab) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number);
935 return accum;
940 // This is a conversion of Lab float to 16 bits
941 static
942 cmsUInt8Number* UnrollLabFloatTo16(CMSREGISTER _cmsTRANSFORM* info,
943 CMSREGISTER cmsUInt16Number wIn[],
944 CMSREGISTER cmsUInt8Number* accum,
945 CMSREGISTER cmsUInt32Number Stride)
947 cmsCIELab Lab;
949 if (T_PLANAR(info -> InputFormat)) {
951 cmsUInt8Number* pos_L;
952 cmsUInt8Number* pos_a;
953 cmsUInt8Number* pos_b;
955 pos_L = accum;
956 pos_a = accum + Stride;
957 pos_b = accum + Stride * 2;
959 Lab.L = *(cmsFloat32Number*)pos_L;
960 Lab.a = *(cmsFloat32Number*)pos_a;
961 Lab.b = *(cmsFloat32Number*)pos_b;
963 cmsFloat2LabEncoded(wIn, &Lab);
964 return accum + sizeof(cmsFloat32Number);
966 else {
968 Lab.L = ((cmsFloat32Number*) accum)[0];
969 Lab.a = ((cmsFloat32Number*) accum)[1];
970 Lab.b = ((cmsFloat32Number*) accum)[2];
972 cmsFloat2LabEncoded(wIn, &Lab);
973 accum += (3 + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat32Number);
974 return accum;
978 // This is a conversion of XYZ double to 16 bits
979 static
980 cmsUInt8Number* UnrollXYZDoubleTo16(CMSREGISTER _cmsTRANSFORM* info,
981 CMSREGISTER cmsUInt16Number wIn[],
982 CMSREGISTER cmsUInt8Number* accum,
983 CMSREGISTER cmsUInt32Number Stride)
985 if (T_PLANAR(info -> InputFormat)) {
987 cmsCIEXYZ XYZ;
988 cmsUInt8Number* pos_X;
989 cmsUInt8Number* pos_Y;
990 cmsUInt8Number* pos_Z;
992 pos_X = accum;
993 pos_Y = accum + Stride;
994 pos_Z = accum + Stride * 2;
996 XYZ.X = *(cmsFloat64Number*)pos_X;
997 XYZ.Y = *(cmsFloat64Number*)pos_Y;
998 XYZ.Z = *(cmsFloat64Number*)pos_Z;
1000 cmsFloat2XYZEncoded(wIn, &XYZ);
1002 return accum + sizeof(cmsFloat64Number);
1006 else {
1007 cmsFloat2XYZEncoded(wIn, (cmsCIEXYZ*) accum);
1008 accum += sizeof(cmsCIEXYZ) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number);
1010 return accum;
1014 // This is a conversion of XYZ float to 16 bits
1015 static
1016 cmsUInt8Number* UnrollXYZFloatTo16(CMSREGISTER _cmsTRANSFORM* info,
1017 CMSREGISTER cmsUInt16Number wIn[],
1018 CMSREGISTER cmsUInt8Number* accum,
1019 CMSREGISTER cmsUInt32Number Stride)
1021 if (T_PLANAR(info -> InputFormat)) {
1023 cmsCIEXYZ XYZ;
1024 cmsUInt8Number* pos_X;
1025 cmsUInt8Number* pos_Y;
1026 cmsUInt8Number* pos_Z;
1028 pos_X = accum;
1029 pos_Y = accum + Stride;
1030 pos_Z = accum + Stride * 2;
1032 XYZ.X = *(cmsFloat32Number*)pos_X;
1033 XYZ.Y = *(cmsFloat32Number*)pos_Y;
1034 XYZ.Z = *(cmsFloat32Number*)pos_Z;
1036 cmsFloat2XYZEncoded(wIn, &XYZ);
1038 return accum + sizeof(cmsFloat32Number);
1042 else {
1043 cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
1044 cmsCIEXYZ XYZ;
1046 XYZ.X = Pt[0];
1047 XYZ.Y = Pt[1];
1048 XYZ.Z = Pt[2];
1049 cmsFloat2XYZEncoded(wIn, &XYZ);
1051 accum += 3 * sizeof(cmsFloat32Number) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat32Number);
1053 return accum;
1057 // Check if space is marked as ink
1058 cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type)
1060 switch (T_COLORSPACE(Type)) {
1062 case PT_CMY:
1063 case PT_CMYK:
1064 case PT_MCH5:
1065 case PT_MCH6:
1066 case PT_MCH7:
1067 case PT_MCH8:
1068 case PT_MCH9:
1069 case PT_MCH10:
1070 case PT_MCH11:
1071 case PT_MCH12:
1072 case PT_MCH13:
1073 case PT_MCH14:
1074 case PT_MCH15: return TRUE;
1076 default: return FALSE;
1080 // Return the size in bytes of a given formatter
1081 static
1082 cmsUInt32Number PixelSize(cmsUInt32Number Format)
1084 cmsUInt32Number fmt_bytes = T_BYTES(Format);
1086 // For double, the T_BYTES field is zero
1087 if (fmt_bytes == 0)
1088 return sizeof(cmsUInt64Number);
1090 // Otherwise, it is already correct for all formats
1091 return fmt_bytes;
1094 // Inks does come in percentage, remaining cases are between 0..1.0, again to 16 bits
1095 static
1096 cmsUInt8Number* UnrollDoubleTo16(CMSREGISTER _cmsTRANSFORM* info,
1097 CMSREGISTER cmsUInt16Number wIn[],
1098 CMSREGISTER cmsUInt8Number* accum,
1099 CMSREGISTER cmsUInt32Number Stride)
1102 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
1103 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);
1104 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
1105 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);
1106 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);
1107 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1108 cmsUInt32Number Planar = T_PLANAR(info -> InputFormat);
1109 cmsFloat64Number v;
1110 cmsUInt16Number vi;
1111 cmsUInt32Number i, start = 0;
1112 cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
1115 Stride /= PixelSize(info->InputFormat);
1117 if (ExtraFirst)
1118 start = Extra;
1120 for (i=0; i < nChan; i++) {
1122 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1124 if (Planar)
1125 v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[(i + start) * Stride];
1126 else
1127 v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[i + start];
1129 vi = _cmsQuickSaturateWord(v * maximum);
1131 if (Reverse)
1132 vi = REVERSE_FLAVOR_16(vi);
1134 wIn[index] = vi;
1138 if (Extra == 0 && SwapFirst) {
1139 cmsUInt16Number tmp = wIn[0];
1141 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
1142 wIn[nChan-1] = tmp;
1145 if (T_PLANAR(info -> InputFormat))
1146 return accum + sizeof(cmsFloat64Number);
1147 else
1148 return accum + (nChan + Extra) * sizeof(cmsFloat64Number);
1153 static
1154 cmsUInt8Number* UnrollFloatTo16(CMSREGISTER _cmsTRANSFORM* info,
1155 CMSREGISTER cmsUInt16Number wIn[],
1156 CMSREGISTER cmsUInt8Number* accum,
1157 CMSREGISTER cmsUInt32Number Stride)
1160 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
1161 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);
1162 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
1163 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);
1164 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);
1165 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1166 cmsUInt32Number Planar = T_PLANAR(info -> InputFormat);
1167 cmsFloat32Number v;
1168 cmsUInt16Number vi;
1169 cmsUInt32Number i, start = 0;
1170 cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
1172 Stride /= PixelSize(info->InputFormat);
1174 if (ExtraFirst)
1175 start = Extra;
1177 for (i=0; i < nChan; i++) {
1179 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1181 if (Planar)
1182 v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride];
1183 else
1184 v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[i + start];
1186 vi = _cmsQuickSaturateWord(v * maximum);
1188 if (Reverse)
1189 vi = REVERSE_FLAVOR_16(vi);
1191 wIn[index] = vi;
1195 if (Extra == 0 && SwapFirst) {
1196 cmsUInt16Number tmp = wIn[0];
1198 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
1199 wIn[nChan-1] = tmp;
1202 if (T_PLANAR(info -> InputFormat))
1203 return accum + sizeof(cmsFloat32Number);
1204 else
1205 return accum + (nChan + Extra) * sizeof(cmsFloat32Number);
1211 // For 1 channel, we need to duplicate data (it comes in 0..1.0 range)
1212 static
1213 cmsUInt8Number* UnrollDouble1Chan(CMSREGISTER _cmsTRANSFORM* info,
1214 CMSREGISTER cmsUInt16Number wIn[],
1215 CMSREGISTER cmsUInt8Number* accum,
1216 CMSREGISTER cmsUInt32Number Stride)
1218 cmsFloat64Number* Inks = (cmsFloat64Number*) accum;
1220 wIn[0] = wIn[1] = wIn[2] = _cmsQuickSaturateWord(Inks[0] * 65535.0);
1222 return accum + sizeof(cmsFloat64Number);
1224 cmsUNUSED_PARAMETER(info);
1225 cmsUNUSED_PARAMETER(Stride);
1228 //-------------------------------------------------------------------------------------------------------------------
1230 // For anything going from cmsUInt8Number
1231 static
1232 cmsUInt8Number* Unroll8ToFloat(_cmsTRANSFORM* info,
1233 cmsFloat32Number wIn[],
1234 cmsUInt8Number* accum,
1235 cmsUInt32Number Stride)
1238 cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
1239 cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
1240 cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
1241 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
1242 cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
1243 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1244 cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
1245 cmsFloat32Number v;
1246 cmsUInt32Number i, start = 0;
1248 Stride /= PixelSize(info->InputFormat);
1250 if (ExtraFirst)
1251 start = Extra;
1253 for (i = 0; i < nChan; i++) {
1255 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1257 if (Planar)
1258 v = (cmsFloat32Number) ((cmsUInt8Number *)accum)[(i + start) * Stride];
1259 else
1260 v = (cmsFloat32Number) ((cmsUInt8Number *)accum)[i + start];
1262 v /= 255.0F;
1264 wIn[index] = Reverse ? 1 - v : v;
1268 if (Extra == 0 && SwapFirst) {
1269 cmsFloat32Number tmp = wIn[0];
1271 memmove(&wIn[0], &wIn[1], (nChan - 1) * sizeof(cmsFloat32Number));
1272 wIn[nChan - 1] = tmp;
1275 if (T_PLANAR(info->InputFormat))
1276 return accum + sizeof(cmsUInt8Number);
1277 else
1278 return accum + (nChan + Extra) * sizeof(cmsUInt8Number);
1282 // For anything going from cmsUInt16Number
1283 static
1284 cmsUInt8Number* Unroll16ToFloat(_cmsTRANSFORM* info,
1285 cmsFloat32Number wIn[],
1286 cmsUInt8Number* accum,
1287 cmsUInt32Number Stride)
1290 cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
1291 cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
1292 cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
1293 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
1294 cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
1295 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1296 cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
1297 cmsFloat32Number v;
1298 cmsUInt32Number i, start = 0;
1300 Stride /= PixelSize(info->InputFormat);
1302 if (ExtraFirst)
1303 start = Extra;
1305 for (i = 0; i < nChan; i++) {
1307 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1309 if (Planar)
1310 v = (cmsFloat32Number)((cmsUInt16Number*)accum)[(i + start) * Stride];
1311 else
1312 v = (cmsFloat32Number)((cmsUInt16Number*)accum)[i + start];
1314 v /= 65535.0F;
1316 wIn[index] = Reverse ? 1 - v : v;
1320 if (Extra == 0 && SwapFirst) {
1321 cmsFloat32Number tmp = wIn[0];
1323 memmove(&wIn[0], &wIn[1], (nChan - 1) * sizeof(cmsFloat32Number));
1324 wIn[nChan - 1] = tmp;
1327 if (T_PLANAR(info->InputFormat))
1328 return accum + sizeof(cmsUInt16Number);
1329 else
1330 return accum + (nChan + Extra) * sizeof(cmsUInt16Number);
1334 // For anything going from cmsFloat32Number
1335 static
1336 cmsUInt8Number* UnrollFloatsToFloat(_cmsTRANSFORM* info,
1337 cmsFloat32Number wIn[],
1338 cmsUInt8Number* accum,
1339 cmsUInt32Number Stride)
1342 cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
1343 cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
1344 cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
1345 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
1346 cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
1347 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1348 cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
1349 cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
1350 cmsFloat32Number v;
1351 cmsUInt32Number i, start = 0;
1352 cmsFloat32Number maximum = IsInkSpace(info->InputFormat) ? 100.0F : 1.0F;
1353 cmsFloat32Number alpha_factor = 1.0f;
1354 cmsFloat32Number* ptr = (cmsFloat32Number*)accum;
1356 Stride /= PixelSize(info->InputFormat);
1358 if (Premul && Extra)
1360 if (Planar)
1361 alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan * Stride]) / maximum;
1362 else
1363 alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
1366 if (ExtraFirst)
1367 start = Extra;
1369 for (i=0; i < nChan; i++) {
1371 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1373 if (Planar)
1374 v = ptr[(i + start) * Stride];
1375 else
1376 v = ptr[i + start];
1378 if (Premul && alpha_factor > 0)
1379 v /= alpha_factor;
1381 v /= maximum;
1383 wIn[index] = Reverse ? 1 - v : v;
1387 if (Extra == 0 && SwapFirst) {
1388 cmsFloat32Number tmp = wIn[0];
1390 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));
1391 wIn[nChan-1] = tmp;
1394 if (T_PLANAR(info -> InputFormat))
1395 return accum + sizeof(cmsFloat32Number);
1396 else
1397 return accum + (nChan + Extra) * sizeof(cmsFloat32Number);
1400 // For anything going from double
1402 static
1403 cmsUInt8Number* UnrollDoublesToFloat(_cmsTRANSFORM* info,
1404 cmsFloat32Number wIn[],
1405 cmsUInt8Number* accum,
1406 cmsUInt32Number Stride)
1409 cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
1410 cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
1411 cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
1412 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
1413 cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
1414 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1415 cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
1416 cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
1417 cmsFloat64Number v;
1418 cmsUInt32Number i, start = 0;
1419 cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0;
1420 cmsFloat64Number alpha_factor = 1.0;
1421 cmsFloat64Number* ptr = (cmsFloat64Number*)accum;
1423 Stride /= PixelSize(info->InputFormat);
1425 if (Premul && Extra)
1427 if (Planar)
1428 alpha_factor = (ExtraFirst ? ptr[0] : ptr[(nChan) * Stride]) / maximum;
1429 else
1430 alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
1433 if (ExtraFirst)
1434 start = Extra;
1436 for (i=0; i < nChan; i++) {
1438 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1440 if (Planar)
1441 v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[(i + start) * Stride];
1442 else
1443 v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[i + start];
1446 if (Premul && alpha_factor > 0)
1447 v /= alpha_factor;
1449 v /= maximum;
1451 wIn[index] = (cmsFloat32Number) (Reverse ? 1.0 - v : v);
1455 if (Extra == 0 && SwapFirst) {
1456 cmsFloat32Number tmp = wIn[0];
1458 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));
1459 wIn[nChan-1] = tmp;
1462 if (T_PLANAR(info -> InputFormat))
1463 return accum + sizeof(cmsFloat64Number);
1464 else
1465 return accum + (nChan + Extra) * sizeof(cmsFloat64Number);
1470 // From Lab double to cmsFloat32Number
1471 static
1472 cmsUInt8Number* UnrollLabDoubleToFloat(_cmsTRANSFORM* info,
1473 cmsFloat32Number wIn[],
1474 cmsUInt8Number* accum,
1475 cmsUInt32Number Stride)
1477 cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
1479 if (T_PLANAR(info -> InputFormat)) {
1481 Stride /= PixelSize(info->InputFormat);
1483 wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1
1484 wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0); // form -128..+127 to 0..1
1485 wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);
1487 return accum + sizeof(cmsFloat64Number);
1489 else {
1491 wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1
1492 wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0); // form -128..+127 to 0..1
1493 wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);
1495 accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat));
1496 return accum;
1500 // From Lab double to cmsFloat32Number
1501 static
1502 cmsUInt8Number* UnrollLabFloatToFloat(_cmsTRANSFORM* info,
1503 cmsFloat32Number wIn[],
1504 cmsUInt8Number* accum,
1505 cmsUInt32Number Stride)
1507 cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
1509 if (T_PLANAR(info -> InputFormat)) {
1511 Stride /= PixelSize(info->InputFormat);
1513 wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1
1514 wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0); // form -128..+127 to 0..1
1515 wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);
1517 return accum + sizeof(cmsFloat32Number);
1519 else {
1521 wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1
1522 wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0); // form -128..+127 to 0..1
1523 wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);
1525 accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat));
1526 return accum;
1530 // 1.15 fixed point, that means maximum value is MAX_ENCODEABLE_XYZ (0xFFFF)
1531 static
1532 cmsUInt8Number* UnrollXYZDoubleToFloat(_cmsTRANSFORM* info,
1533 cmsFloat32Number wIn[],
1534 cmsUInt8Number* accum,
1535 cmsUInt32Number Stride)
1537 cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
1539 if (T_PLANAR(info -> InputFormat)) {
1541 Stride /= PixelSize(info->InputFormat);
1543 wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
1544 wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);
1545 wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);
1547 return accum + sizeof(cmsFloat64Number);
1549 else {
1551 wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
1552 wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);
1553 wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);
1555 accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat));
1556 return accum;
1560 static
1561 cmsUInt8Number* UnrollXYZFloatToFloat(_cmsTRANSFORM* info,
1562 cmsFloat32Number wIn[],
1563 cmsUInt8Number* accum,
1564 cmsUInt32Number Stride)
1566 cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
1568 if (T_PLANAR(info -> InputFormat)) {
1570 Stride /= PixelSize(info->InputFormat);
1572 wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
1573 wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);
1574 wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);
1576 return accum + sizeof(cmsFloat32Number);
1578 else {
1580 wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
1581 wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);
1582 wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);
1584 accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat));
1585 return accum;
1590 cmsINLINE void lab4toFloat(cmsFloat32Number wIn[], cmsUInt16Number lab4[3])
1592 cmsFloat32Number L = (cmsFloat32Number) lab4[0] / 655.35F;
1593 cmsFloat32Number a = ((cmsFloat32Number) lab4[1] / 257.0F) - 128.0F;
1594 cmsFloat32Number b = ((cmsFloat32Number) lab4[2] / 257.0F) - 128.0F;
1596 wIn[0] = (L / 100.0F); // from 0..100 to 0..1
1597 wIn[1] = ((a + 128.0F) / 255.0F); // form -128..+127 to 0..1
1598 wIn[2] = ((b + 128.0F) / 255.0F);
1602 static
1603 cmsUInt8Number* UnrollLabV2_8ToFloat(_cmsTRANSFORM* info,
1604 cmsFloat32Number wIn[],
1605 cmsUInt8Number* accum,
1606 cmsUInt32Number Stride)
1608 cmsUInt16Number lab4[3];
1610 lab4[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L
1611 lab4[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a
1612 lab4[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b
1614 lab4toFloat(wIn, lab4);
1616 return accum;
1618 cmsUNUSED_PARAMETER(info);
1619 cmsUNUSED_PARAMETER(Stride);
1622 static
1623 cmsUInt8Number* UnrollALabV2_8ToFloat(_cmsTRANSFORM* info,
1624 cmsFloat32Number wIn[],
1625 cmsUInt8Number* accum,
1626 cmsUInt32Number Stride)
1628 cmsUInt16Number lab4[3];
1630 accum++; // A
1631 lab4[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L
1632 lab4[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a
1633 lab4[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b
1635 lab4toFloat(wIn, lab4);
1637 return accum;
1639 cmsUNUSED_PARAMETER(info);
1640 cmsUNUSED_PARAMETER(Stride);
1643 static
1644 cmsUInt8Number* UnrollLabV2_16ToFloat(_cmsTRANSFORM* info,
1645 cmsFloat32Number wIn[],
1646 cmsUInt8Number* accum,
1647 cmsUInt32Number Stride)
1649 cmsUInt16Number lab4[3];
1651 lab4[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // L
1652 lab4[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // a
1653 lab4[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // b
1655 lab4toFloat(wIn, lab4);
1657 return accum;
1659 cmsUNUSED_PARAMETER(info);
1660 cmsUNUSED_PARAMETER(Stride);
1664 // Packing routines -----------------------------------------------------------------------------------------------------------
1667 // Generic chunky for byte
1668 static
1669 cmsUInt8Number* PackChunkyBytes(CMSREGISTER _cmsTRANSFORM* info,
1670 CMSREGISTER cmsUInt16Number wOut[],
1671 CMSREGISTER cmsUInt8Number* output,
1672 CMSREGISTER cmsUInt32Number Stride)
1674 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
1675 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
1676 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
1677 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
1678 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
1679 cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
1680 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1681 cmsUInt8Number* swap1;
1682 cmsUInt16Number v = 0;
1683 cmsUInt32Number i;
1684 cmsUInt32Number alpha_factor = 0;
1686 swap1 = output;
1688 if (ExtraFirst) {
1690 if (Premul && Extra)
1691 alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[0]));
1693 output += Extra;
1695 else
1697 if (Premul && Extra)
1698 alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[nChan]));
1701 for (i=0; i < nChan; i++) {
1703 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1705 v = wOut[index];
1707 if (Reverse)
1708 v = REVERSE_FLAVOR_16(v);
1710 if (Premul)
1712 v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
1715 *output++ = FROM_16_TO_8(v);
1718 if (!ExtraFirst) {
1719 output += Extra;
1722 if (Extra == 0 && SwapFirst) {
1724 memmove(swap1 + 1, swap1, nChan-1);
1725 *swap1 = FROM_16_TO_8(v);
1728 return output;
1730 cmsUNUSED_PARAMETER(Stride);
1733 static
1734 cmsUInt8Number* PackChunkyWords(CMSREGISTER _cmsTRANSFORM* info,
1735 CMSREGISTER cmsUInt16Number wOut[],
1736 CMSREGISTER cmsUInt8Number* output,
1737 CMSREGISTER cmsUInt32Number Stride)
1739 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
1740 cmsUInt32Number SwapEndian = T_ENDIAN16(info->OutputFormat);
1741 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
1742 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
1743 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
1744 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
1745 cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
1746 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1747 cmsUInt16Number* swap1;
1748 cmsUInt16Number v = 0;
1749 cmsUInt32Number i;
1750 cmsUInt32Number alpha_factor = 0;
1752 swap1 = (cmsUInt16Number*) output;
1754 if (ExtraFirst) {
1756 if (Premul && Extra)
1757 alpha_factor = _cmsToFixedDomain(*(cmsUInt16Number*) output);
1759 output += Extra * sizeof(cmsUInt16Number);
1761 else
1763 if (Premul && Extra)
1764 alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*) output)[nChan]);
1767 for (i=0; i < nChan; i++) {
1769 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1771 v = wOut[index];
1773 if (SwapEndian)
1774 v = CHANGE_ENDIAN(v);
1776 if (Reverse)
1777 v = REVERSE_FLAVOR_16(v);
1779 if (Premul)
1781 v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
1784 *(cmsUInt16Number*) output = v;
1786 output += sizeof(cmsUInt16Number);
1789 if (!ExtraFirst) {
1790 output += Extra * sizeof(cmsUInt16Number);
1793 if (Extra == 0 && SwapFirst) {
1795 memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number));
1796 *swap1 = v;
1799 return output;
1801 cmsUNUSED_PARAMETER(Stride);
1806 static
1807 cmsUInt8Number* PackPlanarBytes(CMSREGISTER _cmsTRANSFORM* info,
1808 CMSREGISTER cmsUInt16Number wOut[],
1809 CMSREGISTER cmsUInt8Number* output,
1810 CMSREGISTER cmsUInt32Number Stride)
1812 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
1813 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
1814 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
1815 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
1816 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
1817 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1818 cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
1819 cmsUInt32Number i;
1820 cmsUInt8Number* Init = output;
1821 cmsUInt32Number alpha_factor = 0;
1824 if (ExtraFirst) {
1826 if (Premul && Extra)
1827 alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[0]));
1829 output += Extra * Stride;
1831 else
1833 if (Premul && Extra)
1834 alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[nChan * Stride]));
1838 for (i=0; i < nChan; i++) {
1840 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1841 cmsUInt16Number v = wOut[index];
1843 if (Reverse)
1844 v = REVERSE_FLAVOR_16(v);
1846 if (Premul)
1848 v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
1851 *(cmsUInt8Number*)output = FROM_16_TO_8(v);
1853 output += Stride;
1856 return (Init + 1);
1858 cmsUNUSED_PARAMETER(Stride);
1862 static
1863 cmsUInt8Number* PackPlanarWords(CMSREGISTER _cmsTRANSFORM* info,
1864 CMSREGISTER cmsUInt16Number wOut[],
1865 CMSREGISTER cmsUInt8Number* output,
1866 CMSREGISTER cmsUInt32Number Stride)
1868 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
1869 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
1870 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
1871 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
1872 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
1873 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
1874 cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
1875 cmsUInt32Number SwapEndian = T_ENDIAN16(info->OutputFormat);
1876 cmsUInt32Number i;
1877 cmsUInt8Number* Init = output;
1878 cmsUInt16Number v;
1879 cmsUInt32Number alpha_factor = 0;
1881 if (ExtraFirst) {
1883 if (Premul && Extra)
1884 alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*) output)[0]);
1886 output += Extra * Stride;
1888 else
1890 if (Premul && Extra)
1891 alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*)output)[nChan * Stride]);
1894 for (i=0; i < nChan; i++) {
1896 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
1898 v = wOut[index];
1900 if (SwapEndian)
1901 v = CHANGE_ENDIAN(v);
1903 if (Reverse)
1904 v = REVERSE_FLAVOR_16(v);
1906 if (Premul)
1908 v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
1911 *(cmsUInt16Number*) output = v;
1912 output += Stride;
1915 return (Init + sizeof(cmsUInt16Number));
1918 // CMYKcm (unrolled for speed)
1920 static
1921 cmsUInt8Number* Pack6Bytes(CMSREGISTER _cmsTRANSFORM* info,
1922 CMSREGISTER cmsUInt16Number wOut[],
1923 CMSREGISTER cmsUInt8Number* output,
1924 CMSREGISTER cmsUInt32Number Stride)
1926 *output++ = FROM_16_TO_8(wOut[0]);
1927 *output++ = FROM_16_TO_8(wOut[1]);
1928 *output++ = FROM_16_TO_8(wOut[2]);
1929 *output++ = FROM_16_TO_8(wOut[3]);
1930 *output++ = FROM_16_TO_8(wOut[4]);
1931 *output++ = FROM_16_TO_8(wOut[5]);
1933 return output;
1935 cmsUNUSED_PARAMETER(info);
1936 cmsUNUSED_PARAMETER(Stride);
1939 // KCMYcm
1941 static
1942 cmsUInt8Number* Pack6BytesSwap(CMSREGISTER _cmsTRANSFORM* info,
1943 CMSREGISTER cmsUInt16Number wOut[],
1944 CMSREGISTER cmsUInt8Number* output,
1945 CMSREGISTER cmsUInt32Number Stride)
1947 *output++ = FROM_16_TO_8(wOut[5]);
1948 *output++ = FROM_16_TO_8(wOut[4]);
1949 *output++ = FROM_16_TO_8(wOut[3]);
1950 *output++ = FROM_16_TO_8(wOut[2]);
1951 *output++ = FROM_16_TO_8(wOut[1]);
1952 *output++ = FROM_16_TO_8(wOut[0]);
1954 return output;
1956 cmsUNUSED_PARAMETER(info);
1957 cmsUNUSED_PARAMETER(Stride);
1960 // CMYKcm
1961 static
1962 cmsUInt8Number* Pack6Words(CMSREGISTER _cmsTRANSFORM* info,
1963 CMSREGISTER cmsUInt16Number wOut[],
1964 CMSREGISTER cmsUInt8Number* output,
1965 CMSREGISTER cmsUInt32Number Stride)
1967 *(cmsUInt16Number*) output = wOut[0];
1968 output+= 2;
1969 *(cmsUInt16Number*) output = wOut[1];
1970 output+= 2;
1971 *(cmsUInt16Number*) output = wOut[2];
1972 output+= 2;
1973 *(cmsUInt16Number*) output = wOut[3];
1974 output+= 2;
1975 *(cmsUInt16Number*) output = wOut[4];
1976 output+= 2;
1977 *(cmsUInt16Number*) output = wOut[5];
1978 output+= 2;
1980 return output;
1982 cmsUNUSED_PARAMETER(info);
1983 cmsUNUSED_PARAMETER(Stride);
1986 // KCMYcm
1987 static
1988 cmsUInt8Number* Pack6WordsSwap(CMSREGISTER _cmsTRANSFORM* info,
1989 CMSREGISTER cmsUInt16Number wOut[],
1990 CMSREGISTER cmsUInt8Number* output,
1991 CMSREGISTER cmsUInt32Number Stride)
1993 *(cmsUInt16Number*) output = wOut[5];
1994 output+= 2;
1995 *(cmsUInt16Number*) output = wOut[4];
1996 output+= 2;
1997 *(cmsUInt16Number*) output = wOut[3];
1998 output+= 2;
1999 *(cmsUInt16Number*) output = wOut[2];
2000 output+= 2;
2001 *(cmsUInt16Number*) output = wOut[1];
2002 output+= 2;
2003 *(cmsUInt16Number*) output = wOut[0];
2004 output+= 2;
2006 return output;
2008 cmsUNUSED_PARAMETER(info);
2009 cmsUNUSED_PARAMETER(Stride);
2013 static
2014 cmsUInt8Number* Pack4Bytes(CMSREGISTER _cmsTRANSFORM* info,
2015 CMSREGISTER cmsUInt16Number wOut[],
2016 CMSREGISTER cmsUInt8Number* output,
2017 CMSREGISTER cmsUInt32Number Stride)
2019 *output++ = FROM_16_TO_8(wOut[0]);
2020 *output++ = FROM_16_TO_8(wOut[1]);
2021 *output++ = FROM_16_TO_8(wOut[2]);
2022 *output++ = FROM_16_TO_8(wOut[3]);
2024 return output;
2026 cmsUNUSED_PARAMETER(info);
2027 cmsUNUSED_PARAMETER(Stride);
2030 static
2031 cmsUInt8Number* Pack4BytesReverse(CMSREGISTER _cmsTRANSFORM* info,
2032 CMSREGISTER cmsUInt16Number wOut[],
2033 CMSREGISTER cmsUInt8Number* output,
2034 CMSREGISTER cmsUInt32Number Stride)
2036 *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[0]));
2037 *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[1]));
2038 *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[2]));
2039 *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[3]));
2041 return output;
2043 cmsUNUSED_PARAMETER(info);
2044 cmsUNUSED_PARAMETER(Stride);
2048 static
2049 cmsUInt8Number* Pack4BytesSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
2050 CMSREGISTER cmsUInt16Number wOut[],
2051 CMSREGISTER cmsUInt8Number* output,
2052 CMSREGISTER cmsUInt32Number Stride)
2054 *output++ = FROM_16_TO_8(wOut[3]);
2055 *output++ = FROM_16_TO_8(wOut[0]);
2056 *output++ = FROM_16_TO_8(wOut[1]);
2057 *output++ = FROM_16_TO_8(wOut[2]);
2059 return output;
2061 cmsUNUSED_PARAMETER(info);
2062 cmsUNUSED_PARAMETER(Stride);
2065 // ABGR
2066 static
2067 cmsUInt8Number* Pack4BytesSwap(CMSREGISTER _cmsTRANSFORM* info,
2068 CMSREGISTER cmsUInt16Number wOut[],
2069 CMSREGISTER cmsUInt8Number* output,
2070 CMSREGISTER cmsUInt32Number Stride)
2072 *output++ = FROM_16_TO_8(wOut[3]);
2073 *output++ = FROM_16_TO_8(wOut[2]);
2074 *output++ = FROM_16_TO_8(wOut[1]);
2075 *output++ = FROM_16_TO_8(wOut[0]);
2077 return output;
2079 cmsUNUSED_PARAMETER(info);
2080 cmsUNUSED_PARAMETER(Stride);
2083 static
2084 cmsUInt8Number* Pack4BytesSwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
2085 CMSREGISTER cmsUInt16Number wOut[],
2086 CMSREGISTER cmsUInt8Number* output,
2087 CMSREGISTER cmsUInt32Number Stride)
2089 *output++ = FROM_16_TO_8(wOut[2]);
2090 *output++ = FROM_16_TO_8(wOut[1]);
2091 *output++ = FROM_16_TO_8(wOut[0]);
2092 *output++ = FROM_16_TO_8(wOut[3]);
2094 return output;
2096 cmsUNUSED_PARAMETER(info);
2097 cmsUNUSED_PARAMETER(Stride);
2100 static
2101 cmsUInt8Number* Pack4Words(CMSREGISTER _cmsTRANSFORM* info,
2102 CMSREGISTER cmsUInt16Number wOut[],
2103 CMSREGISTER cmsUInt8Number* output,
2104 CMSREGISTER cmsUInt32Number Stride)
2106 *(cmsUInt16Number*) output = wOut[0];
2107 output+= 2;
2108 *(cmsUInt16Number*) output = wOut[1];
2109 output+= 2;
2110 *(cmsUInt16Number*) output = wOut[2];
2111 output+= 2;
2112 *(cmsUInt16Number*) output = wOut[3];
2113 output+= 2;
2115 return output;
2117 cmsUNUSED_PARAMETER(info);
2118 cmsUNUSED_PARAMETER(Stride);
2121 static
2122 cmsUInt8Number* Pack4WordsReverse(CMSREGISTER _cmsTRANSFORM* info,
2123 CMSREGISTER cmsUInt16Number wOut[],
2124 CMSREGISTER cmsUInt8Number* output,
2125 CMSREGISTER cmsUInt32Number Stride)
2127 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]);
2128 output+= 2;
2129 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[1]);
2130 output+= 2;
2131 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[2]);
2132 output+= 2;
2133 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[3]);
2134 output+= 2;
2136 return output;
2138 cmsUNUSED_PARAMETER(info);
2139 cmsUNUSED_PARAMETER(Stride);
2142 // ABGR
2143 static
2144 cmsUInt8Number* Pack4WordsSwap(CMSREGISTER _cmsTRANSFORM* info,
2145 CMSREGISTER cmsUInt16Number wOut[],
2146 CMSREGISTER cmsUInt8Number* output,
2147 CMSREGISTER cmsUInt32Number Stride)
2149 *(cmsUInt16Number*) output = wOut[3];
2150 output+= 2;
2151 *(cmsUInt16Number*) output = wOut[2];
2152 output+= 2;
2153 *(cmsUInt16Number*) output = wOut[1];
2154 output+= 2;
2155 *(cmsUInt16Number*) output = wOut[0];
2156 output+= 2;
2158 return output;
2160 cmsUNUSED_PARAMETER(info);
2161 cmsUNUSED_PARAMETER(Stride);
2164 // CMYK
2165 static
2166 cmsUInt8Number* Pack4WordsBigEndian(CMSREGISTER _cmsTRANSFORM* info,
2167 CMSREGISTER cmsUInt16Number wOut[],
2168 CMSREGISTER cmsUInt8Number* output,
2169 CMSREGISTER cmsUInt32Number Stride)
2171 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
2172 output+= 2;
2173 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]);
2174 output+= 2;
2175 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]);
2176 output+= 2;
2177 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[3]);
2178 output+= 2;
2180 return output;
2182 cmsUNUSED_PARAMETER(info);
2183 cmsUNUSED_PARAMETER(Stride);
2187 static
2188 cmsUInt8Number* PackLabV2_8(CMSREGISTER _cmsTRANSFORM* info,
2189 CMSREGISTER cmsUInt16Number wOut[],
2190 CMSREGISTER cmsUInt8Number* output,
2191 CMSREGISTER cmsUInt32Number Stride)
2193 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0]));
2194 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1]));
2195 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2]));
2197 return output;
2199 cmsUNUSED_PARAMETER(info);
2200 cmsUNUSED_PARAMETER(Stride);
2203 static
2204 cmsUInt8Number* PackALabV2_8(CMSREGISTER _cmsTRANSFORM* info,
2205 CMSREGISTER cmsUInt16Number wOut[],
2206 CMSREGISTER cmsUInt8Number* output,
2207 CMSREGISTER cmsUInt32Number Stride)
2209 output++;
2210 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0]));
2211 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1]));
2212 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2]));
2214 return output;
2216 cmsUNUSED_PARAMETER(info);
2217 cmsUNUSED_PARAMETER(Stride);
2220 static
2221 cmsUInt8Number* PackLabV2_16(CMSREGISTER _cmsTRANSFORM* info,
2222 CMSREGISTER cmsUInt16Number wOut[],
2223 CMSREGISTER cmsUInt8Number* output,
2224 CMSREGISTER cmsUInt32Number Stride)
2226 *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[0]);
2227 output += 2;
2228 *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[1]);
2229 output += 2;
2230 *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[2]);
2231 output += 2;
2233 return output;
2235 cmsUNUSED_PARAMETER(info);
2236 cmsUNUSED_PARAMETER(Stride);
2239 static
2240 cmsUInt8Number* Pack3Bytes(CMSREGISTER _cmsTRANSFORM* info,
2241 CMSREGISTER cmsUInt16Number wOut[],
2242 CMSREGISTER cmsUInt8Number* output,
2243 CMSREGISTER cmsUInt32Number Stride)
2245 *output++ = FROM_16_TO_8(wOut[0]);
2246 *output++ = FROM_16_TO_8(wOut[1]);
2247 *output++ = FROM_16_TO_8(wOut[2]);
2249 return output;
2251 cmsUNUSED_PARAMETER(info);
2252 cmsUNUSED_PARAMETER(Stride);
2255 static
2256 cmsUInt8Number* Pack3BytesOptimized(CMSREGISTER _cmsTRANSFORM* info,
2257 CMSREGISTER cmsUInt16Number wOut[],
2258 CMSREGISTER cmsUInt8Number* output,
2259 CMSREGISTER cmsUInt32Number Stride)
2261 *output++ = (wOut[0] & 0xFFU);
2262 *output++ = (wOut[1] & 0xFFU);
2263 *output++ = (wOut[2] & 0xFFU);
2265 return output;
2267 cmsUNUSED_PARAMETER(info);
2268 cmsUNUSED_PARAMETER(Stride);
2271 static
2272 cmsUInt8Number* Pack3BytesSwap(CMSREGISTER _cmsTRANSFORM* info,
2273 CMSREGISTER cmsUInt16Number wOut[],
2274 CMSREGISTER cmsUInt8Number* output,
2275 CMSREGISTER cmsUInt32Number Stride)
2277 *output++ = FROM_16_TO_8(wOut[2]);
2278 *output++ = FROM_16_TO_8(wOut[1]);
2279 *output++ = FROM_16_TO_8(wOut[0]);
2281 return output;
2283 cmsUNUSED_PARAMETER(info);
2284 cmsUNUSED_PARAMETER(Stride);
2287 static
2288 cmsUInt8Number* Pack3BytesSwapOptimized(CMSREGISTER _cmsTRANSFORM* info,
2289 CMSREGISTER cmsUInt16Number wOut[],
2290 CMSREGISTER cmsUInt8Number* output,
2291 CMSREGISTER cmsUInt32Number Stride)
2293 *output++ = (wOut[2] & 0xFFU);
2294 *output++ = (wOut[1] & 0xFFU);
2295 *output++ = (wOut[0] & 0xFFU);
2297 return output;
2299 cmsUNUSED_PARAMETER(info);
2300 cmsUNUSED_PARAMETER(Stride);
2304 static
2305 cmsUInt8Number* Pack3Words(CMSREGISTER _cmsTRANSFORM* info,
2306 CMSREGISTER cmsUInt16Number wOut[],
2307 CMSREGISTER cmsUInt8Number* output,
2308 CMSREGISTER cmsUInt32Number Stride)
2310 *(cmsUInt16Number*) output = wOut[0];
2311 output+= 2;
2312 *(cmsUInt16Number*) output = wOut[1];
2313 output+= 2;
2314 *(cmsUInt16Number*) output = wOut[2];
2315 output+= 2;
2317 return output;
2319 cmsUNUSED_PARAMETER(info);
2320 cmsUNUSED_PARAMETER(Stride);
2323 static
2324 cmsUInt8Number* Pack3WordsSwap(CMSREGISTER _cmsTRANSFORM* info,
2325 CMSREGISTER cmsUInt16Number wOut[],
2326 CMSREGISTER cmsUInt8Number* output,
2327 CMSREGISTER cmsUInt32Number Stride)
2329 *(cmsUInt16Number*) output = wOut[2];
2330 output+= 2;
2331 *(cmsUInt16Number*) output = wOut[1];
2332 output+= 2;
2333 *(cmsUInt16Number*) output = wOut[0];
2334 output+= 2;
2336 return output;
2338 cmsUNUSED_PARAMETER(info);
2339 cmsUNUSED_PARAMETER(Stride);
2342 static
2343 cmsUInt8Number* Pack3WordsBigEndian(CMSREGISTER _cmsTRANSFORM* info,
2344 CMSREGISTER cmsUInt16Number wOut[],
2345 CMSREGISTER cmsUInt8Number* output,
2346 CMSREGISTER cmsUInt32Number Stride)
2348 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
2349 output+= 2;
2350 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]);
2351 output+= 2;
2352 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]);
2353 output+= 2;
2355 return output;
2357 cmsUNUSED_PARAMETER(info);
2358 cmsUNUSED_PARAMETER(Stride);
2361 static
2362 cmsUInt8Number* Pack3BytesAndSkip1(CMSREGISTER _cmsTRANSFORM* info,
2363 CMSREGISTER cmsUInt16Number wOut[],
2364 CMSREGISTER cmsUInt8Number* output,
2365 CMSREGISTER cmsUInt32Number Stride)
2367 *output++ = FROM_16_TO_8(wOut[0]);
2368 *output++ = FROM_16_TO_8(wOut[1]);
2369 *output++ = FROM_16_TO_8(wOut[2]);
2370 output++;
2372 return output;
2374 cmsUNUSED_PARAMETER(info);
2375 cmsUNUSED_PARAMETER(Stride);
2378 static
2379 cmsUInt8Number* Pack3BytesAndSkip1Optimized(CMSREGISTER _cmsTRANSFORM* info,
2380 CMSREGISTER cmsUInt16Number wOut[],
2381 CMSREGISTER cmsUInt8Number* output,
2382 CMSREGISTER cmsUInt32Number Stride)
2384 *output++ = (wOut[0] & 0xFFU);
2385 *output++ = (wOut[1] & 0xFFU);
2386 *output++ = (wOut[2] & 0xFFU);
2387 output++;
2389 return output;
2391 cmsUNUSED_PARAMETER(info);
2392 cmsUNUSED_PARAMETER(Stride);
2396 static
2397 cmsUInt8Number* Pack3BytesAndSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,
2398 CMSREGISTER cmsUInt16Number wOut[],
2399 CMSREGISTER cmsUInt8Number* output,
2400 CMSREGISTER cmsUInt32Number Stride)
2402 output++;
2403 *output++ = FROM_16_TO_8(wOut[0]);
2404 *output++ = FROM_16_TO_8(wOut[1]);
2405 *output++ = FROM_16_TO_8(wOut[2]);
2407 return output;
2409 cmsUNUSED_PARAMETER(info);
2410 cmsUNUSED_PARAMETER(Stride);
2413 static
2414 cmsUInt8Number* Pack3BytesAndSkip1SwapFirstOptimized(CMSREGISTER _cmsTRANSFORM* info,
2415 CMSREGISTER cmsUInt16Number wOut[],
2416 CMSREGISTER cmsUInt8Number* output,
2417 CMSREGISTER cmsUInt32Number Stride)
2419 output++;
2420 *output++ = (wOut[0] & 0xFFU);
2421 *output++ = (wOut[1] & 0xFFU);
2422 *output++ = (wOut[2] & 0xFFU);
2424 return output;
2426 cmsUNUSED_PARAMETER(info);
2427 cmsUNUSED_PARAMETER(Stride);
2430 static
2431 cmsUInt8Number* Pack3BytesAndSkip1Swap(CMSREGISTER _cmsTRANSFORM* info,
2432 CMSREGISTER cmsUInt16Number wOut[],
2433 CMSREGISTER cmsUInt8Number* output,
2434 CMSREGISTER cmsUInt32Number Stride)
2436 output++;
2437 *output++ = FROM_16_TO_8(wOut[2]);
2438 *output++ = FROM_16_TO_8(wOut[1]);
2439 *output++ = FROM_16_TO_8(wOut[0]);
2441 return output;
2443 cmsUNUSED_PARAMETER(info);
2444 cmsUNUSED_PARAMETER(Stride);
2447 static
2448 cmsUInt8Number* Pack3BytesAndSkip1SwapOptimized(CMSREGISTER _cmsTRANSFORM* info,
2449 CMSREGISTER cmsUInt16Number wOut[],
2450 CMSREGISTER cmsUInt8Number* output,
2451 CMSREGISTER cmsUInt32Number Stride)
2453 output++;
2454 *output++ = (wOut[2] & 0xFFU);
2455 *output++ = (wOut[1] & 0xFFU);
2456 *output++ = (wOut[0] & 0xFFU);
2458 return output;
2460 cmsUNUSED_PARAMETER(info);
2461 cmsUNUSED_PARAMETER(Stride);
2465 static
2466 cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
2467 CMSREGISTER cmsUInt16Number wOut[],
2468 CMSREGISTER cmsUInt8Number* output,
2469 CMSREGISTER cmsUInt32Number Stride)
2471 *output++ = FROM_16_TO_8(wOut[2]);
2472 *output++ = FROM_16_TO_8(wOut[1]);
2473 *output++ = FROM_16_TO_8(wOut[0]);
2474 output++;
2476 return output;
2478 cmsUNUSED_PARAMETER(info);
2479 cmsUNUSED_PARAMETER(Stride);
2482 static
2483 cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirstOptimized(CMSREGISTER _cmsTRANSFORM* info,
2484 CMSREGISTER cmsUInt16Number wOut[],
2485 CMSREGISTER cmsUInt8Number* output,
2486 CMSREGISTER cmsUInt32Number Stride)
2488 *output++ = (wOut[2] & 0xFFU);
2489 *output++ = (wOut[1] & 0xFFU);
2490 *output++ = (wOut[0] & 0xFFU);
2491 output++;
2493 return output;
2495 cmsUNUSED_PARAMETER(info);
2496 cmsUNUSED_PARAMETER(Stride);
2499 static
2500 cmsUInt8Number* Pack3WordsAndSkip1(CMSREGISTER _cmsTRANSFORM* info,
2501 CMSREGISTER cmsUInt16Number wOut[],
2502 CMSREGISTER cmsUInt8Number* output,
2503 CMSREGISTER cmsUInt32Number Stride)
2505 *(cmsUInt16Number*) output = wOut[0];
2506 output+= 2;
2507 *(cmsUInt16Number*) output = wOut[1];
2508 output+= 2;
2509 *(cmsUInt16Number*) output = wOut[2];
2510 output+= 2;
2511 output+= 2;
2513 return output;
2515 cmsUNUSED_PARAMETER(info);
2516 cmsUNUSED_PARAMETER(Stride);
2519 static
2520 cmsUInt8Number* Pack3WordsAndSkip1Swap(CMSREGISTER _cmsTRANSFORM* info,
2521 CMSREGISTER cmsUInt16Number wOut[],
2522 CMSREGISTER cmsUInt8Number* output,
2523 CMSREGISTER cmsUInt32Number Stride)
2525 output+= 2;
2526 *(cmsUInt16Number*) output = wOut[2];
2527 output+= 2;
2528 *(cmsUInt16Number*) output = wOut[1];
2529 output+= 2;
2530 *(cmsUInt16Number*) output = wOut[0];
2531 output+= 2;
2533 return output;
2535 cmsUNUSED_PARAMETER(info);
2536 cmsUNUSED_PARAMETER(Stride);
2540 static
2541 cmsUInt8Number* Pack3WordsAndSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,
2542 CMSREGISTER cmsUInt16Number wOut[],
2543 CMSREGISTER cmsUInt8Number* output,
2544 CMSREGISTER cmsUInt32Number Stride)
2546 output+= 2;
2547 *(cmsUInt16Number*) output = wOut[0];
2548 output+= 2;
2549 *(cmsUInt16Number*) output = wOut[1];
2550 output+= 2;
2551 *(cmsUInt16Number*) output = wOut[2];
2552 output+= 2;
2554 return output;
2556 cmsUNUSED_PARAMETER(info);
2557 cmsUNUSED_PARAMETER(Stride);
2561 static
2562 cmsUInt8Number* Pack3WordsAndSkip1SwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
2563 CMSREGISTER cmsUInt16Number wOut[],
2564 CMSREGISTER cmsUInt8Number* output,
2565 CMSREGISTER cmsUInt32Number Stride)
2567 *(cmsUInt16Number*) output = wOut[2];
2568 output+= 2;
2569 *(cmsUInt16Number*) output = wOut[1];
2570 output+= 2;
2571 *(cmsUInt16Number*) output = wOut[0];
2572 output+= 2;
2573 output+= 2;
2575 return output;
2577 cmsUNUSED_PARAMETER(info);
2578 cmsUNUSED_PARAMETER(Stride);
2583 static
2584 cmsUInt8Number* Pack1Byte(CMSREGISTER _cmsTRANSFORM* info,
2585 CMSREGISTER cmsUInt16Number wOut[],
2586 CMSREGISTER cmsUInt8Number* output,
2587 CMSREGISTER cmsUInt32Number Stride)
2589 *output++ = FROM_16_TO_8(wOut[0]);
2591 return output;
2593 cmsUNUSED_PARAMETER(info);
2594 cmsUNUSED_PARAMETER(Stride);
2598 static
2599 cmsUInt8Number* Pack1ByteReversed(CMSREGISTER _cmsTRANSFORM* info,
2600 CMSREGISTER cmsUInt16Number wOut[],
2601 CMSREGISTER cmsUInt8Number* output,
2602 CMSREGISTER cmsUInt32Number Stride)
2604 *output++ = FROM_16_TO_8(REVERSE_FLAVOR_16(wOut[0]));
2606 return output;
2608 cmsUNUSED_PARAMETER(info);
2609 cmsUNUSED_PARAMETER(Stride);
2613 static
2614 cmsUInt8Number* Pack1ByteSkip1(CMSREGISTER _cmsTRANSFORM* info,
2615 CMSREGISTER cmsUInt16Number wOut[],
2616 CMSREGISTER cmsUInt8Number* output,
2617 CMSREGISTER cmsUInt32Number Stride)
2619 *output++ = FROM_16_TO_8(wOut[0]);
2620 output++;
2622 return output;
2624 cmsUNUSED_PARAMETER(info);
2625 cmsUNUSED_PARAMETER(Stride);
2629 static
2630 cmsUInt8Number* Pack1ByteSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,
2631 CMSREGISTER cmsUInt16Number wOut[],
2632 CMSREGISTER cmsUInt8Number* output,
2633 CMSREGISTER cmsUInt32Number Stride)
2635 output++;
2636 *output++ = FROM_16_TO_8(wOut[0]);
2638 return output;
2640 cmsUNUSED_PARAMETER(info);
2641 cmsUNUSED_PARAMETER(Stride);
2644 static
2645 cmsUInt8Number* Pack1Word(CMSREGISTER _cmsTRANSFORM* info,
2646 CMSREGISTER cmsUInt16Number wOut[],
2647 CMSREGISTER cmsUInt8Number* output,
2648 CMSREGISTER cmsUInt32Number Stride)
2650 *(cmsUInt16Number*) output = wOut[0];
2651 output+= 2;
2653 return output;
2655 cmsUNUSED_PARAMETER(info);
2656 cmsUNUSED_PARAMETER(Stride);
2660 static
2661 cmsUInt8Number* Pack1WordReversed(CMSREGISTER _cmsTRANSFORM* info,
2662 CMSREGISTER cmsUInt16Number wOut[],
2663 CMSREGISTER cmsUInt8Number* output,
2664 CMSREGISTER cmsUInt32Number Stride)
2666 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]);
2667 output+= 2;
2669 return output;
2671 cmsUNUSED_PARAMETER(info);
2672 cmsUNUSED_PARAMETER(Stride);
2675 static
2676 cmsUInt8Number* Pack1WordBigEndian(CMSREGISTER _cmsTRANSFORM* info,
2677 CMSREGISTER cmsUInt16Number wOut[],
2678 CMSREGISTER cmsUInt8Number* output,
2679 CMSREGISTER cmsUInt32Number Stride)
2681 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
2682 output+= 2;
2684 return output;
2686 cmsUNUSED_PARAMETER(info);
2687 cmsUNUSED_PARAMETER(Stride);
2691 static
2692 cmsUInt8Number* Pack1WordSkip1(CMSREGISTER _cmsTRANSFORM* info,
2693 CMSREGISTER cmsUInt16Number wOut[],
2694 CMSREGISTER cmsUInt8Number* output,
2695 CMSREGISTER cmsUInt32Number Stride)
2697 *(cmsUInt16Number*) output = wOut[0];
2698 output+= 4;
2700 return output;
2702 cmsUNUSED_PARAMETER(info);
2703 cmsUNUSED_PARAMETER(Stride);
2706 static
2707 cmsUInt8Number* Pack1WordSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,
2708 CMSREGISTER cmsUInt16Number wOut[],
2709 CMSREGISTER cmsUInt8Number* output,
2710 CMSREGISTER cmsUInt32Number Stride)
2712 output += 2;
2713 *(cmsUInt16Number*) output = wOut[0];
2714 output+= 2;
2716 return output;
2718 cmsUNUSED_PARAMETER(info);
2719 cmsUNUSED_PARAMETER(Stride);
2723 // Unencoded Float values -- don't try optimize speed
2724 static
2725 cmsUInt8Number* PackLabDoubleFrom16(CMSREGISTER _cmsTRANSFORM* info,
2726 CMSREGISTER cmsUInt16Number wOut[],
2727 CMSREGISTER cmsUInt8Number* output,
2728 CMSREGISTER cmsUInt32Number Stride)
2731 if (T_PLANAR(info -> OutputFormat)) {
2733 cmsCIELab Lab;
2734 cmsFloat64Number* Out = (cmsFloat64Number*) output;
2735 cmsLabEncoded2Float(&Lab, wOut);
2737 Out[0] = Lab.L;
2738 Out[Stride] = Lab.a;
2739 Out[Stride*2] = Lab.b;
2741 return output + sizeof(cmsFloat64Number);
2743 else {
2745 cmsLabEncoded2Float((cmsCIELab*) output, wOut);
2746 return output + (sizeof(cmsCIELab) + T_EXTRA(info ->OutputFormat) * sizeof(cmsFloat64Number));
2751 static
2752 cmsUInt8Number* PackLabFloatFrom16(CMSREGISTER _cmsTRANSFORM* info,
2753 CMSREGISTER cmsUInt16Number wOut[],
2754 CMSREGISTER cmsUInt8Number* output,
2755 CMSREGISTER cmsUInt32Number Stride)
2757 cmsCIELab Lab;
2758 cmsLabEncoded2Float(&Lab, wOut);
2760 if (T_PLANAR(info -> OutputFormat)) {
2762 cmsFloat32Number* Out = (cmsFloat32Number*) output;
2764 Stride /= PixelSize(info->OutputFormat);
2766 Out[0] = (cmsFloat32Number)Lab.L;
2767 Out[Stride] = (cmsFloat32Number)Lab.a;
2768 Out[Stride*2] = (cmsFloat32Number)Lab.b;
2770 return output + sizeof(cmsFloat32Number);
2772 else {
2774 ((cmsFloat32Number*) output)[0] = (cmsFloat32Number) Lab.L;
2775 ((cmsFloat32Number*) output)[1] = (cmsFloat32Number) Lab.a;
2776 ((cmsFloat32Number*) output)[2] = (cmsFloat32Number) Lab.b;
2778 return output + (3 + T_EXTRA(info ->OutputFormat)) * sizeof(cmsFloat32Number);
2782 static
2783 cmsUInt8Number* PackXYZDoubleFrom16(CMSREGISTER _cmsTRANSFORM* Info,
2784 CMSREGISTER cmsUInt16Number wOut[],
2785 CMSREGISTER cmsUInt8Number* output,
2786 CMSREGISTER cmsUInt32Number Stride)
2788 if (T_PLANAR(Info -> OutputFormat)) {
2790 cmsCIEXYZ XYZ;
2791 cmsFloat64Number* Out = (cmsFloat64Number*) output;
2792 cmsXYZEncoded2Float(&XYZ, wOut);
2794 Stride /= PixelSize(Info->OutputFormat);
2796 Out[0] = XYZ.X;
2797 Out[Stride] = XYZ.Y;
2798 Out[Stride*2] = XYZ.Z;
2800 return output + sizeof(cmsFloat64Number);
2803 else {
2805 cmsXYZEncoded2Float((cmsCIEXYZ*) output, wOut);
2807 return output + (sizeof(cmsCIEXYZ) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
2811 static
2812 cmsUInt8Number* PackXYZFloatFrom16(CMSREGISTER _cmsTRANSFORM* Info,
2813 CMSREGISTER cmsUInt16Number wOut[],
2814 CMSREGISTER cmsUInt8Number* output,
2815 CMSREGISTER cmsUInt32Number Stride)
2817 if (T_PLANAR(Info -> OutputFormat)) {
2819 cmsCIEXYZ XYZ;
2820 cmsFloat32Number* Out = (cmsFloat32Number*) output;
2821 cmsXYZEncoded2Float(&XYZ, wOut);
2823 Stride /= PixelSize(Info->OutputFormat);
2825 Out[0] = (cmsFloat32Number) XYZ.X;
2826 Out[Stride] = (cmsFloat32Number) XYZ.Y;
2827 Out[Stride*2] = (cmsFloat32Number) XYZ.Z;
2829 return output + sizeof(cmsFloat32Number);
2832 else {
2834 cmsCIEXYZ XYZ;
2835 cmsFloat32Number* Out = (cmsFloat32Number*) output;
2836 cmsXYZEncoded2Float(&XYZ, wOut);
2838 Out[0] = (cmsFloat32Number) XYZ.X;
2839 Out[1] = (cmsFloat32Number) XYZ.Y;
2840 Out[2] = (cmsFloat32Number) XYZ.Z;
2842 return output + (3 * sizeof(cmsFloat32Number) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
2846 static
2847 cmsUInt8Number* PackDoubleFrom16(CMSREGISTER _cmsTRANSFORM* info,
2848 CMSREGISTER cmsUInt16Number wOut[],
2849 CMSREGISTER cmsUInt8Number* output,
2850 CMSREGISTER cmsUInt32Number Stride)
2852 cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat);
2853 cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat);
2854 cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat);
2855 cmsUInt32Number Extra = T_EXTRA(info -> OutputFormat);
2856 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> OutputFormat);
2857 cmsUInt32Number Planar = T_PLANAR(info -> OutputFormat);
2858 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
2859 cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0;
2860 cmsFloat64Number v = 0;
2861 cmsFloat64Number* swap1 = (cmsFloat64Number*) output;
2862 cmsUInt32Number i, start = 0;
2864 Stride /= PixelSize(info->OutputFormat);
2866 if (ExtraFirst)
2867 start = Extra;
2869 for (i=0; i < nChan; i++) {
2871 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
2873 v = (cmsFloat64Number) wOut[index] / maximum;
2875 if (Reverse)
2876 v = maximum - v;
2878 if (Planar)
2879 ((cmsFloat64Number*) output)[(i + start) * Stride]= v;
2880 else
2881 ((cmsFloat64Number*) output)[i + start] = v;
2885 if (Extra == 0 && SwapFirst) {
2887 memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number));
2888 *swap1 = v;
2891 if (T_PLANAR(info -> OutputFormat))
2892 return output + sizeof(cmsFloat64Number);
2893 else
2894 return output + (nChan + Extra) * sizeof(cmsFloat64Number);
2899 static
2900 cmsUInt8Number* PackFloatFrom16(CMSREGISTER _cmsTRANSFORM* info,
2901 CMSREGISTER cmsUInt16Number wOut[],
2902 CMSREGISTER cmsUInt8Number* output,
2903 CMSREGISTER cmsUInt32Number Stride)
2905 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
2906 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
2907 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
2908 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
2909 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
2910 cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
2911 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
2912 cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 655.35 : 65535.0;
2913 cmsFloat64Number v = 0;
2914 cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
2915 cmsUInt32Number i, start = 0;
2917 Stride /= PixelSize(info->OutputFormat);
2919 if (ExtraFirst)
2920 start = Extra;
2922 for (i = 0; i < nChan; i++) {
2924 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
2926 v = (cmsFloat64Number)wOut[index] / maximum;
2928 if (Reverse)
2929 v = maximum - v;
2931 if (Planar)
2932 ((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v;
2933 else
2934 ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;
2938 if (Extra == 0 && SwapFirst) {
2940 memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));
2941 *swap1 = (cmsFloat32Number)v;
2944 if (T_PLANAR(info->OutputFormat))
2945 return output + sizeof(cmsFloat32Number);
2946 else
2947 return output + (nChan + Extra) * sizeof(cmsFloat32Number);
2952 // --------------------------------------------------------------------------------------------------------
2954 static
2955 cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info,
2956 cmsFloat32Number wOut[],
2957 cmsUInt8Number* output,
2958 cmsUInt32Number Stride)
2960 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
2961 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
2962 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
2963 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
2964 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
2965 cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
2966 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
2967 cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;
2968 cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
2969 cmsFloat64Number v = 0;
2970 cmsUInt32Number i, start = 0;
2972 Stride /= PixelSize(info->OutputFormat);
2974 if (ExtraFirst)
2975 start = Extra;
2977 for (i = 0; i < nChan; i++) {
2979 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
2981 v = wOut[index] * maximum;
2983 if (Reverse)
2984 v = maximum - v;
2986 if (Planar)
2987 ((cmsFloat32Number*)output)[(i + start)* Stride] = (cmsFloat32Number)v;
2988 else
2989 ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;
2993 if (Extra == 0 && SwapFirst) {
2995 memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));
2996 *swap1 = (cmsFloat32Number)v;
2999 if (T_PLANAR(info->OutputFormat))
3000 return output + sizeof(cmsFloat32Number);
3001 else
3002 return output + (nChan + Extra) * sizeof(cmsFloat32Number);
3005 static
3006 cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info,
3007 cmsFloat32Number wOut[],
3008 cmsUInt8Number* output,
3009 cmsUInt32Number Stride)
3011 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
3012 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
3013 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
3014 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
3015 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
3016 cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
3017 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3018 cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;
3019 cmsFloat64Number v = 0;
3020 cmsFloat64Number* swap1 = (cmsFloat64Number*)output;
3021 cmsUInt32Number i, start = 0;
3023 Stride /= PixelSize(info->OutputFormat);
3025 if (ExtraFirst)
3026 start = Extra;
3028 for (i = 0; i < nChan; i++) {
3030 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3032 v = wOut[index] * maximum;
3034 if (Reverse)
3035 v = maximum - v;
3037 if (Planar)
3038 ((cmsFloat64Number*)output)[(i + start) * Stride] = v;
3039 else
3040 ((cmsFloat64Number*)output)[i + start] = v;
3043 if (Extra == 0 && SwapFirst) {
3045 memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat64Number));
3046 *swap1 = v;
3050 if (T_PLANAR(info->OutputFormat))
3051 return output + sizeof(cmsFloat64Number);
3052 else
3053 return output + (nChan + Extra) * sizeof(cmsFloat64Number);
3057 static
3058 cmsUInt8Number* PackLabFloatFromFloat(_cmsTRANSFORM* Info,
3059 cmsFloat32Number wOut[],
3060 cmsUInt8Number* output,
3061 cmsUInt32Number Stride)
3063 cmsFloat32Number* Out = (cmsFloat32Number*) output;
3065 if (T_PLANAR(Info -> OutputFormat)) {
3067 Stride /= PixelSize(Info->OutputFormat);
3069 Out[0] = (cmsFloat32Number) (wOut[0] * 100.0);
3070 Out[Stride] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0);
3071 Out[Stride*2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0);
3073 return output + sizeof(cmsFloat32Number);
3075 else {
3077 Out[0] = (cmsFloat32Number) (wOut[0] * 100.0);
3078 Out[1] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0);
3079 Out[2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0);
3081 return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
3087 static
3088 cmsUInt8Number* PackLabDoubleFromFloat(_cmsTRANSFORM* Info,
3089 cmsFloat32Number wOut[],
3090 cmsUInt8Number* output,
3091 cmsUInt32Number Stride)
3093 cmsFloat64Number* Out = (cmsFloat64Number*) output;
3095 if (T_PLANAR(Info -> OutputFormat)) {
3097 Stride /= PixelSize(Info->OutputFormat);
3099 Out[0] = (cmsFloat64Number) (wOut[0] * 100.0);
3100 Out[Stride] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0);
3101 Out[Stride*2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0);
3103 return output + sizeof(cmsFloat64Number);
3105 else {
3107 Out[0] = (cmsFloat64Number) (wOut[0] * 100.0);
3108 Out[1] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0);
3109 Out[2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0);
3111 return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
3117 // From 0..1 range to 0..MAX_ENCODEABLE_XYZ
3118 static
3119 cmsUInt8Number* PackXYZFloatFromFloat(_cmsTRANSFORM* Info,
3120 cmsFloat32Number wOut[],
3121 cmsUInt8Number* output,
3122 cmsUInt32Number Stride)
3124 cmsFloat32Number* Out = (cmsFloat32Number*) output;
3126 if (T_PLANAR(Info -> OutputFormat)) {
3128 Stride /= PixelSize(Info->OutputFormat);
3130 Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
3131 Out[Stride] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
3132 Out[Stride*2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
3134 return output + sizeof(cmsFloat32Number);
3136 else {
3138 Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
3139 Out[1] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
3140 Out[2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
3142 return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
3147 // Same, but convert to double
3148 static
3149 cmsUInt8Number* PackXYZDoubleFromFloat(_cmsTRANSFORM* Info,
3150 cmsFloat32Number wOut[],
3151 cmsUInt8Number* output,
3152 cmsUInt32Number Stride)
3154 cmsFloat64Number* Out = (cmsFloat64Number*) output;
3156 if (T_PLANAR(Info -> OutputFormat)) {
3158 Stride /= PixelSize(Info->OutputFormat);
3160 Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
3161 Out[Stride] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
3162 Out[Stride*2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
3164 return output + sizeof(cmsFloat64Number);
3166 else {
3168 Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
3169 Out[1] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
3170 Out[2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
3172 return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
3178 // ----------------------------------------------------------------------------------------------------------------
3180 #ifndef CMS_NO_HALF_SUPPORT
3182 // Decodes an stream of half floats to wIn[] described by input format
3184 static
3185 cmsUInt8Number* UnrollHalfTo16(CMSREGISTER _cmsTRANSFORM* info,
3186 CMSREGISTER cmsUInt16Number wIn[],
3187 CMSREGISTER cmsUInt8Number* accum,
3188 CMSREGISTER cmsUInt32Number Stride)
3191 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
3192 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);
3193 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
3194 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);
3195 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);
3196 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3197 cmsUInt32Number Planar = T_PLANAR(info -> InputFormat);
3198 cmsFloat32Number v;
3199 cmsUInt32Number i, start = 0;
3200 cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 655.35F : 65535.0F;
3203 Stride /= PixelSize(info->OutputFormat);
3205 if (ExtraFirst)
3206 start = Extra;
3208 for (i=0; i < nChan; i++) {
3210 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3212 if (Planar)
3213 v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] );
3214 else
3215 v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[i + start] ) ;
3217 if (Reverse) v = maximum - v;
3219 wIn[index] = _cmsQuickSaturateWord((cmsFloat64Number) v * maximum);
3223 if (Extra == 0 && SwapFirst) {
3224 cmsUInt16Number tmp = wIn[0];
3226 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
3227 wIn[nChan-1] = tmp;
3230 if (T_PLANAR(info -> InputFormat))
3231 return accum + sizeof(cmsUInt16Number);
3232 else
3233 return accum + (nChan + Extra) * sizeof(cmsUInt16Number);
3236 // Decodes an stream of half floats to wIn[] described by input format
3238 static
3239 cmsUInt8Number* UnrollHalfToFloat(_cmsTRANSFORM* info,
3240 cmsFloat32Number wIn[],
3241 cmsUInt8Number* accum,
3242 cmsUInt32Number Stride)
3245 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
3246 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);
3247 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
3248 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);
3249 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);
3250 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3251 cmsUInt32Number Planar = T_PLANAR(info -> InputFormat);
3252 cmsFloat32Number v;
3253 cmsUInt32Number i, start = 0;
3254 cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F;
3256 Stride /= PixelSize(info->OutputFormat);
3258 if (ExtraFirst)
3259 start = Extra;
3261 for (i=0; i < nChan; i++) {
3263 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3265 if (Planar)
3266 v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] );
3267 else
3268 v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[i + start] ) ;
3270 v /= maximum;
3272 wIn[index] = Reverse ? 1 - v : v;
3276 if (Extra == 0 && SwapFirst) {
3277 cmsFloat32Number tmp = wIn[0];
3279 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));
3280 wIn[nChan-1] = tmp;
3283 if (T_PLANAR(info -> InputFormat))
3284 return accum + sizeof(cmsUInt16Number);
3285 else
3286 return accum + (nChan + Extra) * sizeof(cmsUInt16Number);
3290 static
3291 cmsUInt8Number* PackHalfFrom16(CMSREGISTER _cmsTRANSFORM* info,
3292 CMSREGISTER cmsUInt16Number wOut[],
3293 CMSREGISTER cmsUInt8Number* output,
3294 CMSREGISTER cmsUInt32Number Stride)
3296 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
3297 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
3298 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
3299 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
3300 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
3301 cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
3302 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3303 cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 655.35F : 65535.0F;
3304 cmsFloat32Number v = 0;
3305 cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
3306 cmsUInt32Number i, start = 0;
3308 Stride /= PixelSize(info->OutputFormat);
3310 if (ExtraFirst)
3311 start = Extra;
3313 for (i = 0; i < nChan; i++) {
3315 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3317 v = (cmsFloat32Number)wOut[index] / maximum;
3319 if (Reverse)
3320 v = maximum - v;
3322 if (Planar)
3323 ((cmsUInt16Number*)output)[(i + start) * Stride] = _cmsFloat2Half(v);
3324 else
3325 ((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v);
3329 if (Extra == 0 && SwapFirst) {
3331 memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number));
3332 *swap1 = _cmsFloat2Half(v);
3335 if (T_PLANAR(info->OutputFormat))
3336 return output + sizeof(cmsUInt16Number);
3337 else
3338 return output + (nChan + Extra) * sizeof(cmsUInt16Number);
3343 static
3344 cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info,
3345 cmsFloat32Number wOut[],
3346 cmsUInt8Number* output,
3347 cmsUInt32Number Stride)
3349 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
3350 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
3351 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
3352 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
3353 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
3354 cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
3355 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
3356 cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 100.0F : 1.0F;
3357 cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
3358 cmsFloat32Number v = 0;
3359 cmsUInt32Number i, start = 0;
3361 Stride /= PixelSize(info->OutputFormat);
3363 if (ExtraFirst)
3364 start = Extra;
3366 for (i = 0; i < nChan; i++) {
3368 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
3370 v = wOut[index] * maximum;
3372 if (Reverse)
3373 v = maximum - v;
3375 if (Planar)
3376 ((cmsUInt16Number*)output)[(i + start)* Stride] = _cmsFloat2Half(v);
3377 else
3378 ((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v);
3382 if (Extra == 0 && SwapFirst) {
3384 memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number));
3385 *swap1 = (cmsUInt16Number)_cmsFloat2Half(v);
3388 if (T_PLANAR(info->OutputFormat))
3389 return output + sizeof(cmsUInt16Number);
3390 else
3391 return output + (nChan + Extra)* sizeof(cmsUInt16Number);
3394 #endif
3396 // ----------------------------------------------------------------------------------------------------------------
3399 static const cmsFormatters16 InputFormatters16[] = {
3401 // Type Mask Function
3402 // ---------------------------- ------------------------------------ ----------------------------
3403 { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleTo16},
3404 { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleTo16},
3405 { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, UnrollLabFloatTo16},
3406 { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, UnrollXYZFloatTo16},
3407 { TYPE_GRAY_DBL, 0, UnrollDouble1Chan},
3408 { FLOAT_SH(1)|BYTES_SH(0), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR|
3409 ANYSWAP|ANYEXTRA|ANYSPACE, UnrollDoubleTo16},
3410 { FLOAT_SH(1)|BYTES_SH(4), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR|
3411 ANYSWAP|ANYEXTRA|ANYSPACE, UnrollFloatTo16},
3412 #ifndef CMS_NO_HALF_SUPPORT
3413 { FLOAT_SH(1)|BYTES_SH(2), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR|
3414 ANYEXTRA|ANYSWAP|ANYSPACE, UnrollHalfTo16},
3415 #endif
3417 { CHANNELS_SH(1)|BYTES_SH(1), ANYSPACE, Unroll1Byte},
3418 { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Unroll1ByteSkip1},
3419 { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(2), ANYSPACE, Unroll1ByteSkip2},
3420 { CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll1ByteReversed},
3421 { COLORSPACE_SH(PT_MCH2)|CHANNELS_SH(2)|BYTES_SH(1), 0, Unroll2Bytes},
3423 { TYPE_LabV2_8, 0, UnrollLabV2_8 },
3424 { TYPE_ALabV2_8, 0, UnrollALabV2_8 },
3425 { TYPE_LabV2_16, 0, UnrollLabV2_16 },
3427 { CHANNELS_SH(3)|BYTES_SH(1), ANYSPACE, Unroll3Bytes},
3428 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSwap},
3429 { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSkip1Swap},
3430 { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3BytesSkip1SwapFirst},
3432 { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
3433 ANYSPACE, Unroll3BytesSkip1SwapSwapFirst},
3435 { CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Unroll4Bytes},
3436 { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll4BytesReverse},
3437 { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapFirst},
3438 { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll4BytesSwap},
3439 { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapSwapFirst},
3441 { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYPREMUL|
3442 ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarBytes},
3444 { BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYPREMUL|
3445 ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollChunkyBytes},
3447 { CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Unroll1Word},
3448 { CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Unroll1WordReversed},
3449 { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(3), ANYSPACE, Unroll1WordSkip3},
3451 { CHANNELS_SH(2)|BYTES_SH(2), ANYSPACE, Unroll2Words},
3452 { CHANNELS_SH(3)|BYTES_SH(2), ANYSPACE, Unroll3Words},
3453 { CHANNELS_SH(4)|BYTES_SH(2), ANYSPACE, Unroll4Words},
3455 { CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Unroll3WordsSwap},
3456 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3WordsSkip1SwapFirst},
3457 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3WordsSkip1Swap},
3458 { CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Unroll4WordsReverse},
3459 { CHANNELS_SH(4)|BYTES_SH(2)|SWAPFIRST_SH(1), ANYSPACE, Unroll4WordsSwapFirst},
3460 { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Unroll4WordsSwap},
3461 { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4WordsSwapSwapFirst},
3464 { BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarWords},
3465 { BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollAnyWords},
3467 { BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE|PREMUL_SH(1), UnrollPlanarWordsPremul},
3468 { BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE|PREMUL_SH(1), UnrollAnyWordsPremul}
3474 static const cmsFormattersFloat InputFormattersFloat[] = {
3476 // Type Mask Function
3477 // ---------------------------- ------------------------------------ ----------------------------
3478 { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleToFloat},
3479 { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, UnrollLabFloatToFloat},
3481 { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleToFloat},
3482 { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, UnrollXYZFloatToFloat},
3484 { FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
3485 ANYPREMUL|ANYCHANNELS|ANYSPACE, UnrollFloatsToFloat},
3487 { FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
3488 ANYCHANNELS|ANYSPACE|ANYPREMUL, UnrollDoublesToFloat},
3490 { TYPE_LabV2_8, 0, UnrollLabV2_8ToFloat },
3491 { TYPE_ALabV2_8, 0, UnrollALabV2_8ToFloat },
3492 { TYPE_LabV2_16, 0, UnrollLabV2_16ToFloat },
3494 { BYTES_SH(1), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
3495 ANYCHANNELS|ANYSPACE, Unroll8ToFloat},
3497 { BYTES_SH(2), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
3498 ANYCHANNELS|ANYSPACE, Unroll16ToFloat},
3499 #ifndef CMS_NO_HALF_SUPPORT
3500 { FLOAT_SH(1)|BYTES_SH(2), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
3501 ANYCHANNELS|ANYSPACE, UnrollHalfToFloat},
3502 #endif
3506 // Bit fields set to one in the mask are not compared
3507 static
3508 cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags)
3510 cmsUInt32Number i;
3511 cmsFormatter fr;
3513 switch (dwFlags) {
3515 case CMS_PACK_FLAGS_16BITS: {
3516 for (i=0; i < sizeof(InputFormatters16) / sizeof(cmsFormatters16); i++) {
3517 const cmsFormatters16* f = InputFormatters16 + i;
3519 if ((dwInput & ~f ->Mask) == f ->Type) {
3520 fr.Fmt16 = f ->Frm;
3521 return fr;
3525 break;
3527 case CMS_PACK_FLAGS_FLOAT: {
3528 for (i=0; i < sizeof(InputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {
3529 const cmsFormattersFloat* f = InputFormattersFloat + i;
3531 if ((dwInput & ~f ->Mask) == f ->Type) {
3532 fr.FmtFloat = f ->Frm;
3533 return fr;
3537 break;
3539 default:;
3543 fr.Fmt16 = NULL;
3544 return fr;
3547 static const cmsFormatters16 OutputFormatters16[] = {
3548 // Type Mask Function
3549 // ---------------------------- ------------------------------------ ----------------------------
3551 { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, PackLabDoubleFrom16},
3552 { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFrom16},
3554 { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFrom16},
3555 { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, PackXYZFloatFrom16},
3557 { FLOAT_SH(1)|BYTES_SH(0), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|
3558 ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackDoubleFrom16},
3559 { FLOAT_SH(1)|BYTES_SH(4), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|
3560 ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackFloatFrom16},
3561 #ifndef CMS_NO_HALF_SUPPORT
3562 { FLOAT_SH(1)|BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|
3563 ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackHalfFrom16},
3564 #endif
3566 { CHANNELS_SH(1)|BYTES_SH(1), ANYSPACE, Pack1Byte},
3567 { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Pack1ByteSkip1},
3568 { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack1ByteSkip1SwapFirst},
3570 { CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Pack1ByteReversed},
3572 { TYPE_LabV2_8, 0, PackLabV2_8 },
3573 { TYPE_ALabV2_8, 0, PackALabV2_8 },
3574 { TYPE_LabV2_16, 0, PackLabV2_16 },
3576 { CHANNELS_SH(3)|BYTES_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesOptimized},
3577 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesAndSkip1Optimized},
3578 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1),
3579 ANYSPACE, Pack3BytesAndSkip1SwapFirstOptimized},
3580 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1),
3581 ANYSPACE, Pack3BytesAndSkip1SwapSwapFirstOptimized},
3582 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1),
3583 ANYSPACE, Pack3BytesAndSkip1SwapOptimized},
3584 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesSwapOptimized},
3588 { CHANNELS_SH(3)|BYTES_SH(1), ANYSPACE, Pack3Bytes},
3589 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Pack3BytesAndSkip1},
3590 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack3BytesAndSkip1SwapFirst},
3591 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
3592 ANYSPACE, Pack3BytesAndSkip1SwapSwapFirst},
3593 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1), ANYSPACE, Pack3BytesAndSkip1Swap},
3594 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack3BytesSwap},
3595 { CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Pack4Bytes},
3596 { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Pack4BytesReverse},
3597 { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapFirst},
3598 { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack4BytesSwap},
3599 { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapSwapFirst},
3600 { CHANNELS_SH(6)|BYTES_SH(1), ANYSPACE, Pack6Bytes},
3601 { CHANNELS_SH(6)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack6BytesSwap},
3603 { BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|
3604 ANYSPACE|ANYPREMUL, PackChunkyBytes},
3606 { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
3607 ANYCHANNELS|ANYSPACE|ANYPREMUL, PackPlanarBytes},
3610 { CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Pack1Word},
3611 { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1), ANYSPACE, Pack1WordSkip1},
3612 { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack1WordSkip1SwapFirst},
3613 { CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Pack1WordReversed},
3614 { CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack1WordBigEndian},
3615 { CHANNELS_SH(3)|BYTES_SH(2), ANYSPACE, Pack3Words},
3616 { CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack3WordsSwap},
3617 { CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack3WordsBigEndian},
3618 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1), ANYSPACE, Pack3WordsAndSkip1},
3619 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack3WordsAndSkip1Swap},
3620 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack3WordsAndSkip1SwapFirst},
3622 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
3623 ANYSPACE, Pack3WordsAndSkip1SwapSwapFirst},
3625 { CHANNELS_SH(4)|BYTES_SH(2), ANYSPACE, Pack4Words},
3626 { CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Pack4WordsReverse},
3627 { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack4WordsSwap},
3628 { CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack4WordsBigEndian},
3630 { CHANNELS_SH(6)|BYTES_SH(2), ANYSPACE, Pack6Words},
3631 { CHANNELS_SH(6)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack6WordsSwap},
3633 { BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|
3634 ANYEXTRA|ANYCHANNELS|ANYSPACE|ANYPREMUL, PackChunkyWords},
3635 { BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYENDIAN|ANYSWAP|ANYEXTRA|
3636 ANYCHANNELS|ANYSPACE|ANYPREMUL, PackPlanarWords}
3641 static const cmsFormattersFloat OutputFormattersFloat[] = {
3642 // Type Mask Function
3643 // ---------------------------- --------------------------------------------------- ----------------------------
3644 { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFromFloat},
3645 { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, PackXYZFloatFromFloat},
3647 { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, PackLabDoubleFromFloat},
3648 { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFromFloat},
3650 { FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR|
3651 ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackFloatsFromFloat },
3652 { FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR|
3653 ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackDoublesFromFloat },
3654 #ifndef CMS_NO_HALF_SUPPORT
3655 { FLOAT_SH(1)|BYTES_SH(2),
3656 ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackHalfFromFloat },
3657 #endif
3662 // Bit fields set to one in the mask are not compared
3663 static
3664 cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags)
3666 cmsUInt32Number i;
3667 cmsFormatter fr;
3669 // Optimization is only a hint
3670 dwInput &= ~OPTIMIZED_SH(1);
3672 switch (dwFlags)
3675 case CMS_PACK_FLAGS_16BITS: {
3677 for (i=0; i < sizeof(OutputFormatters16) / sizeof(cmsFormatters16); i++) {
3678 const cmsFormatters16* f = OutputFormatters16 + i;
3680 if ((dwInput & ~f ->Mask) == f ->Type) {
3681 fr.Fmt16 = f ->Frm;
3682 return fr;
3686 break;
3688 case CMS_PACK_FLAGS_FLOAT: {
3690 for (i=0; i < sizeof(OutputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {
3691 const cmsFormattersFloat* f = OutputFormattersFloat + i;
3693 if ((dwInput & ~f ->Mask) == f ->Type) {
3694 fr.FmtFloat = f ->Frm;
3695 return fr;
3699 break;
3701 default:;
3705 fr.Fmt16 = NULL;
3706 return fr;
3710 typedef struct _cms_formatters_factory_list {
3712 cmsFormatterFactory Factory;
3713 struct _cms_formatters_factory_list *Next;
3715 } cmsFormattersFactoryList;
3717 _cmsFormattersPluginChunkType _cmsFormattersPluginChunk = { NULL };
3720 // Duplicates the zone of memory used by the plug-in in the new context
3721 static
3722 void DupFormatterFactoryList(struct _cmsContext_struct* ctx,
3723 const struct _cmsContext_struct* src)
3725 _cmsFormattersPluginChunkType newHead = { NULL };
3726 cmsFormattersFactoryList* entry;
3727 cmsFormattersFactoryList* Anterior = NULL;
3728 _cmsFormattersPluginChunkType* head = (_cmsFormattersPluginChunkType*) src->chunks[FormattersPlugin];
3730 _cmsAssert(head != NULL);
3732 // Walk the list copying all nodes
3733 for (entry = head->FactoryList;
3734 entry != NULL;
3735 entry = entry ->Next) {
3737 cmsFormattersFactoryList *newEntry = ( cmsFormattersFactoryList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(cmsFormattersFactoryList));
3739 if (newEntry == NULL)
3740 return;
3742 // We want to keep the linked list order, so this is a little bit tricky
3743 newEntry -> Next = NULL;
3744 if (Anterior)
3745 Anterior -> Next = newEntry;
3747 Anterior = newEntry;
3749 if (newHead.FactoryList == NULL)
3750 newHead.FactoryList = newEntry;
3753 ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsFormattersPluginChunkType));
3756 // The interpolation plug-in memory chunk allocator/dup
3757 void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx,
3758 const struct _cmsContext_struct* src)
3760 _cmsAssert(ctx != NULL);
3762 if (src != NULL) {
3764 // Duplicate the LIST
3765 DupFormatterFactoryList(ctx, src);
3767 else {
3768 static _cmsFormattersPluginChunkType FormattersPluginChunk = { NULL };
3769 ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx ->MemPool, &FormattersPluginChunk, sizeof(_cmsFormattersPluginChunkType));
3775 // Formatters management
3776 cmsBool _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Data)
3778 _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);
3779 cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data;
3780 cmsFormattersFactoryList* fl ;
3782 // Reset to built-in defaults
3783 if (Data == NULL) {
3785 ctx ->FactoryList = NULL;
3786 return TRUE;
3789 fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(ContextID, sizeof(cmsFormattersFactoryList));
3790 if (fl == NULL) return FALSE;
3792 fl ->Factory = Plugin ->FormattersFactory;
3794 fl ->Next = ctx -> FactoryList;
3795 ctx ->FactoryList = fl;
3797 return TRUE;
3800 cmsFormatter CMSEXPORT _cmsGetFormatter(cmsContext ContextID,
3801 cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8
3802 cmsFormatterDirection Dir,
3803 cmsUInt32Number dwFlags)
3805 _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);
3806 cmsFormattersFactoryList* f;
3808 if (T_CHANNELS(Type) == 0) {
3809 static const cmsFormatter nullFormatter = { 0 };
3810 return nullFormatter;
3813 for (f =ctx->FactoryList; f != NULL; f = f ->Next) {
3815 cmsFormatter fn = f ->Factory(Type, Dir, dwFlags);
3816 if (fn.Fmt16 != NULL) return fn;
3819 // Revert to default
3820 if (Dir == cmsFormatterInput)
3821 return _cmsGetStockInputFormatter(Type, dwFlags);
3822 else
3823 return _cmsGetStockOutputFormatter(Type, dwFlags);
3827 // Return whatever given formatter refers to float values
3828 cmsBool _cmsFormatterIsFloat(cmsUInt32Number Type)
3830 return T_FLOAT(Type) ? TRUE : FALSE;
3833 // Return whatever given formatter refers to 8 bits
3834 cmsBool _cmsFormatterIs8bit(cmsUInt32Number Type)
3836 cmsUInt32Number Bytes = T_BYTES(Type);
3838 return (Bytes == 1);
3841 // Build a suitable formatter for the colorspace of this profile
3842 cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat)
3845 cmsColorSpaceSignature ColorSpace = cmsGetColorSpace(hProfile);
3846 cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ColorSpace);
3847 cmsInt32Number nOutputChans = cmsChannelsOfColorSpace(ColorSpace);
3848 cmsUInt32Number Float = lIsFloat ? 1U : 0;
3850 // Unsupported color space?
3851 if (nOutputChans < 0) return 0;
3853 // Create a fake formatter for result
3854 return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
3857 // Build a suitable formatter for the colorspace of this profile
3858 cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat)
3861 cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile);
3863 cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ColorSpace);
3864 cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace);
3865 cmsUInt32Number Float = lIsFloat ? 1U : 0;
3867 // Unsupported color space?
3868 if (nOutputChans < 0) return 0;
3870 // Create a fake formatter for result
3871 return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);