comparison mupdf-source/thirdparty/lcms2/src/cmspack.c @ 3:2c135c81b16c

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