56
#include "lcms2_internal.h"
61
#define CHANGE_ENDIAN(w) (cmsUInt16Number) ((cmsUInt16Number) ((w)<<8)|((w)>>8))
65
cmsINLINE cmsUInt8Number _cmsQuickSaturateByte(cmsFloat64Number d)
69
if (d >= 255.0) return 255;
71
return (cmsUInt8Number) _cmsQuickFloorWord(d);
77
cmsUInt32Number trueBytesSize(cmsUInt32Number Format)
79
cmsUInt32Number fmt_bytes = T_BYTES(Format);
83
return sizeof(double);
92
typedef void(*cmsFormatterAlphaFn)(void* dst, const void* src);
98
void copy8(void* dst, const void* src)
100
memmove(dst, src, 1);
104
void from8to16(void* dst, const void* src)
106
cmsUInt8Number n = *(cmsUInt8Number*)src;
107
*(cmsUInt16Number*) dst = (cmsUInt16Number) FROM_8_TO_16(n);
111
void from8to16SE(void* dst, const void* src)
113
cmsUInt8Number n = *(cmsUInt8Number*)src;
114
*(cmsUInt16Number*)dst = CHANGE_ENDIAN(FROM_8_TO_16(n));
118
void from8toFLT(void* dst, const void* src)
120
*(cmsFloat32Number*)dst = (cmsFloat32Number) (*(cmsUInt8Number*)src) / 255.0f;
124
void from8toDBL(void* dst, const void* src)
126
*(cmsFloat64Number*)dst = (cmsFloat64Number) (*(cmsUInt8Number*)src) / 255.0;
130
void from8toHLF(void* dst, const void* src)
132
#ifndef CMS_NO_HALF_SUPPORT
133
cmsFloat32Number n = (*(cmsUInt8Number*)src) / 255.0f;
134
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
136
cmsUNUSED_PARAMETER(dst);
137
cmsUNUSED_PARAMETER(src);
144
void from16to8(void* dst, const void* src)
146
cmsUInt16Number n = *(cmsUInt16Number*)src;
147
*(cmsUInt8Number*) dst = FROM_16_TO_8(n);
151
void from16SEto8(void* dst, const void* src)
153
cmsUInt16Number n = *(cmsUInt16Number*)src;
154
*(cmsUInt8Number*)dst = FROM_16_TO_8(CHANGE_ENDIAN(n));
158
void copy16(void* dst, const void* src)
160
memmove(dst, src, 2);
164
void from16to16(void* dst, const void* src)
166
cmsUInt16Number n = *(cmsUInt16Number*)src;
167
*(cmsUInt16Number*)dst = CHANGE_ENDIAN(n);
171
void from16toFLT(void* dst, const void* src)
173
*(cmsFloat32Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f;
177
void from16SEtoFLT(void* dst, const void* src)
179
*(cmsFloat32Number*)dst = (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0f;
183
void from16toDBL(void* dst, const void* src)
185
*(cmsFloat64Number*)dst = (cmsFloat64Number) (*(cmsUInt16Number*)src) / 65535.0;
189
void from16SEtoDBL(void* dst, const void* src)
191
*(cmsFloat64Number*)dst = (cmsFloat64Number) (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0;
195
void from16toHLF(void* dst, const void* src)
197
#ifndef CMS_NO_HALF_SUPPORT
198
cmsFloat32Number n = (*(cmsUInt16Number*)src) / 65535.0f;
199
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
201
cmsUNUSED_PARAMETER(dst);
202
cmsUNUSED_PARAMETER(src);
207
void from16SEtoHLF(void* dst, const void* src)
209
#ifndef CMS_NO_HALF_SUPPORT
210
cmsFloat32Number n = (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0f;
211
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
213
cmsUNUSED_PARAMETER(dst);
214
cmsUNUSED_PARAMETER(src);
220
void fromFLTto8(void* dst, const void* src)
222
cmsFloat32Number n = *(cmsFloat32Number*)src;
223
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0);
227
void fromFLTto16(void* dst, const void* src)
229
cmsFloat32Number n = *(cmsFloat32Number*)src;
230
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0);
234
void fromFLTto16SE(void* dst, const void* src)
236
cmsFloat32Number n = *(cmsFloat32Number*)src;
237
cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0);
239
*(cmsUInt16Number*)dst = CHANGE_ENDIAN(i);
243
void copy32(void* dst, const void* src)
245
memmove(dst, src, sizeof(cmsFloat32Number));
249
void fromFLTtoDBL(void* dst, const void* src)
251
cmsFloat32Number n = *(cmsFloat32Number*)src;
252
*(cmsFloat64Number*)dst = (cmsFloat64Number)n;
256
void fromFLTtoHLF(void* dst, const void* src)
258
#ifndef CMS_NO_HALF_SUPPORT
259
cmsFloat32Number n = *(cmsFloat32Number*)src;
260
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
262
cmsUNUSED_PARAMETER(dst);
263
cmsUNUSED_PARAMETER(src);
271
void fromHLFto8(void* dst, const void* src)
273
#ifndef CMS_NO_HALF_SUPPORT
274
cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
275
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0);
277
cmsUNUSED_PARAMETER(dst);
278
cmsUNUSED_PARAMETER(src);
284
void fromHLFto16(void* dst, const void* src)
286
#ifndef CMS_NO_HALF_SUPPORT
287
cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
288
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0);
290
cmsUNUSED_PARAMETER(dst);
291
cmsUNUSED_PARAMETER(src);
296
void fromHLFto16SE(void* dst, const void* src)
298
#ifndef CMS_NO_HALF_SUPPORT
299
cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
300
cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0);
301
*(cmsUInt16Number*)dst = CHANGE_ENDIAN(i);
303
cmsUNUSED_PARAMETER(dst);
304
cmsUNUSED_PARAMETER(src);
309
void fromHLFtoFLT(void* dst, const void* src)
311
#ifndef CMS_NO_HALF_SUPPORT
312
*(cmsFloat32Number*)dst = _cmsHalf2Float(*(cmsUInt16Number*)src);
314
cmsUNUSED_PARAMETER(dst);
315
cmsUNUSED_PARAMETER(src);
320
void fromHLFtoDBL(void* dst, const void* src)
322
#ifndef CMS_NO_HALF_SUPPORT
323
*(cmsFloat64Number*)dst = (cmsFloat64Number)_cmsHalf2Float(*(cmsUInt16Number*)src);
325
cmsUNUSED_PARAMETER(dst);
326
cmsUNUSED_PARAMETER(src);
332
void fromDBLto8(void* dst, const void* src)
334
cmsFloat64Number n = *(cmsFloat64Number*)src;
335
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0);
339
void fromDBLto16(void* dst, const void* src)
341
cmsFloat64Number n = *(cmsFloat64Number*)src;
342
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
346
void fromDBLto16SE(void* dst, const void* src)
348
cmsFloat64Number n = *(cmsFloat64Number*)src;
349
cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0f);
350
*(cmsUInt16Number*)dst = CHANGE_ENDIAN(i);
354
void fromDBLtoFLT(void* dst, const void* src)
356
cmsFloat64Number n = *(cmsFloat64Number*)src;
357
*(cmsFloat32Number*)dst = (cmsFloat32Number) n;
361
void fromDBLtoHLF(void* dst, const void* src)
363
#ifndef CMS_NO_HALF_SUPPORT
364
cmsFloat32Number n = (cmsFloat32Number) *(cmsFloat64Number*)src;
365
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
367
cmsUNUSED_PARAMETER(dst);
368
cmsUNUSED_PARAMETER(src);
373
void copy64(void* dst, const void* src)
375
memmove(dst, src, sizeof(cmsFloat64Number));
381
int FormatterPos(cmsUInt32Number frm)
383
cmsUInt32Number b = T_BYTES(frm);
385
if (b == 0 && T_FLOAT(frm))
387
#ifndef CMS_NO_HALF_SUPPORT
388
if (b == 2 && T_FLOAT(frm))
391
if (b == 4 && T_FLOAT(frm))
393
if (b == 2 && !T_FLOAT(frm))
400
if (b == 1 && !T_FLOAT(frm))
407
cmsFormatterAlphaFn _cmsGetFormatterAlpha(cmsContext id, cmsUInt32Number in, cmsUInt32Number out)
409
static cmsFormatterAlphaFn FormattersAlpha[6][6] = {
411
{ copy8, from8to16, from8to16SE, from8toHLF, from8toFLT, from8toDBL },
412
{ from16to8, copy16, from16to16, from16toHLF, from16toFLT, from16toDBL },
413
{ from16SEto8, from16to16, copy16, from16SEtoHLF,from16SEtoFLT, from16SEtoDBL },
414
{ fromHLFto8, fromHLFto16, fromHLFto16SE, copy16, fromHLFtoFLT, fromHLFtoDBL },
415
{ fromFLTto8, fromFLTto16, fromFLTto16SE, fromFLTtoHLF, copy32, fromFLTtoDBL },
416
{ fromDBLto8, fromDBLto16, fromDBLto16SE, fromDBLtoHLF, fromDBLtoFLT, copy64 }};
418
int in_n = FormatterPos(in);
419
int out_n = FormatterPos(out);
421
if (in_n < 0 || out_n < 0 || in_n > 5 || out_n > 5) {
423
cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized alpha channel width");
427
return FormattersAlpha[in_n][out_n];
434
cmsBool ComputeIncrementsForChunky(cmsUInt32Number Format,
435
cmsUInt32Number ComponentStartingOrder[],
436
cmsUInt32Number ComponentPointerIncrements[])
438
cmsUInt32Number channels[cmsMAXCHANNELS];
439
cmsUInt32Number extra = T_EXTRA(Format);
440
cmsUInt32Number nchannels = T_CHANNELS(Format);
441
cmsUInt32Number total_chans = nchannels + extra;
443
cmsUInt32Number channelSize = trueBytesSize(Format);
444
cmsUInt32Number pixelSize = channelSize * total_chans;
447
if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
450
memset(channels, 0, sizeof(channels));
453
for (i = 0; i < extra; i++)
454
ComponentPointerIncrements[i] = pixelSize;
457
for (i = 0; i < total_chans; i++)
459
if (T_DOSWAP(Format)) {
460
channels[i] = total_chans - i - 1;
468
if (T_SWAPFIRST(Format) && total_chans > 1) {
470
cmsUInt32Number tmp = channels[0];
471
for (i = 0; i < total_chans-1; i++)
472
channels[i] = channels[i + 1];
474
channels[total_chans - 1] = tmp;
479
for (i = 0; i < total_chans; i++) {
480
channels[i] *= channelSize;
483
for (i = 0; i < extra; i++)
484
ComponentStartingOrder[i] = channels[i + nchannels];
493
cmsBool ComputeIncrementsForPlanar(cmsUInt32Number Format,
494
cmsUInt32Number BytesPerPlane,
495
cmsUInt32Number ComponentStartingOrder[],
496
cmsUInt32Number ComponentPointerIncrements[])
498
cmsUInt32Number channels[cmsMAXCHANNELS];
499
cmsUInt32Number extra = T_EXTRA(Format);
500
cmsUInt32Number nchannels = T_CHANNELS(Format);
501
cmsUInt32Number total_chans = nchannels + extra;
503
cmsUInt32Number channelSize = trueBytesSize(Format);
506
if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
509
memset(channels, 0, sizeof(channels));
512
for (i = 0; i < extra; i++)
513
ComponentPointerIncrements[i] = channelSize;
516
for (i = 0; i < total_chans; i++)
518
if (T_DOSWAP(Format)) {
519
channels[i] = total_chans - i - 1;
527
if (T_SWAPFIRST(Format) && total_chans > 0) {
529
cmsUInt32Number tmp = channels[0];
530
for (i = 0; i < total_chans - 1; i++)
531
channels[i] = channels[i + 1];
533
channels[total_chans - 1] = tmp;
537
for (i = 0; i < total_chans; i++) {
538
channels[i] *= BytesPerPlane;
541
for (i = 0; i < extra; i++)
542
ComponentStartingOrder[i] = channels[i + nchannels];
551
cmsBool ComputeComponentIncrements(cmsUInt32Number Format,
552
cmsUInt32Number BytesPerPlane,
553
cmsUInt32Number ComponentStartingOrder[],
554
cmsUInt32Number ComponentPointerIncrements[])
556
if (T_PLANAR(Format)) {
558
return ComputeIncrementsForPlanar(Format, BytesPerPlane, ComponentStartingOrder, ComponentPointerIncrements);
561
return ComputeIncrementsForChunky(Format, ComponentStartingOrder, ComponentPointerIncrements);
567
void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
569
cmsUInt32Number PixelsPerLine,
570
cmsUInt32Number LineCount,
571
const cmsStride* Stride)
573
cmsUInt32Number i, j, k;
574
cmsUInt32Number nExtra;
575
cmsUInt32Number SourceStartingOrder[cmsMAXCHANNELS];
576
cmsUInt32Number SourceIncrements[cmsMAXCHANNELS];
577
cmsUInt32Number DestStartingOrder[cmsMAXCHANNELS];
578
cmsUInt32Number DestIncrements[cmsMAXCHANNELS];
580
cmsFormatterAlphaFn copyValueFn;
583
if (!(p->dwOriginalFlags & cmsFLAGS_COPY_ALPHA))
587
if (p->InputFormat == p->OutputFormat && in == out)
591
nExtra = T_EXTRA(p->InputFormat);
592
if (nExtra != T_EXTRA(p->OutputFormat))
600
if (!ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements))
602
if (!ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements))
606
copyValueFn = _cmsGetFormatterAlpha(p->ContextID, p->InputFormat, p->OutputFormat);
607
if (copyValueFn == NULL)
612
cmsUInt8Number* SourcePtr;
613
cmsUInt8Number* DestPtr;
615
cmsUInt32Number SourceStrideIncrement = 0;
616
cmsUInt32Number DestStrideIncrement = 0;
619
for (i = 0; i < LineCount; i++) {
622
SourcePtr = (cmsUInt8Number*)in + SourceStartingOrder[0] + SourceStrideIncrement;
623
DestPtr = (cmsUInt8Number*)out + DestStartingOrder[0] + DestStrideIncrement;
625
for (j = 0; j < PixelsPerLine; j++) {
627
copyValueFn(DestPtr, SourcePtr);
629
SourcePtr += SourceIncrements[0];
630
DestPtr += DestIncrements[0];
633
SourceStrideIncrement += Stride->BytesPerLineIn;
634
DestStrideIncrement += Stride->BytesPerLineOut;
640
cmsUInt8Number* SourcePtr[cmsMAXCHANNELS];
641
cmsUInt8Number* DestPtr[cmsMAXCHANNELS];
643
cmsUInt32Number SourceStrideIncrements[cmsMAXCHANNELS];
644
cmsUInt32Number DestStrideIncrements[cmsMAXCHANNELS];
646
memset(SourceStrideIncrements, 0, sizeof(SourceStrideIncrements));
647
memset(DestStrideIncrements, 0, sizeof(DestStrideIncrements));
650
for (i = 0; i < LineCount; i++) {
653
for (j = 0; j < nExtra; j++) {
655
SourcePtr[j] = (cmsUInt8Number*)in + SourceStartingOrder[j] + SourceStrideIncrements[j];
656
DestPtr[j] = (cmsUInt8Number*)out + DestStartingOrder[j] + DestStrideIncrements[j];
659
for (j = 0; j < PixelsPerLine; j++) {
661
for (k = 0; k < nExtra; k++) {
663
copyValueFn(DestPtr[k], SourcePtr[k]);
665
SourcePtr[k] += SourceIncrements[k];
666
DestPtr[k] += DestIncrements[k];
670
for (j = 0; j < nExtra; j++) {
672
SourceStrideIncrements[j] += Stride->BytesPerLineIn;
673
DestStrideIncrements[j] += Stride->BytesPerLineOut;