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