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