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