comparison mupdf-source/thirdparty/lcms2/src/cmsxform.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 //---------------------------------------------------------------------------------
2 //
3 // Little Color Management System
4 // Copyright (c) 1998-2023 Marti Maria Saguer
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the Software
11 // is furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 //---------------------------------------------------------------------------------
25 //
26
27 #include "lcms2_internal.h"
28
29 // Transformations stuff
30 // -----------------------------------------------------------------------
31
32 #define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0
33
34 // The Context0 observer adaptation state.
35 _cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE };
36
37 // Init and duplicate observer adaptation state
38 void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx,
39 const struct _cmsContext_struct* src)
40 {
41 static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE };
42 void* from;
43
44 if (src != NULL) {
45 from = src ->chunks[AdaptationStateContext];
46 }
47 else {
48 from = &AdaptationStateChunk;
49 }
50
51 ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType));
52 }
53
54
55 // Sets adaptation state for absolute colorimetric intent in the given context. Adaptation state applies on all
56 // but cmsCreateExtendedTransform(). Little CMS can handle incomplete adaptation states.
57 // The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine
58 cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsContext ContextID, cmsFloat64Number d)
59 {
60 cmsFloat64Number prev;
61 _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext);
62
63 // Get previous value for return
64 prev = ptr ->AdaptationState;
65
66 // Set the value if d is positive or zero
67 if (d >= 0.0) {
68
69 ptr ->AdaptationState = d;
70 }
71
72 // Always return previous value
73 return prev;
74 }
75
76
77 // -----------------------------------------------------------------------
78
79 // Alarm codes for 16-bit transformations, because the fixed range of containers there are
80 // no values left to mark out of gamut.
81
82 #define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
83
84 _cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE };
85
86 // Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be
87 // encoded in 16 bits.
88 void CMSEXPORT cmsSetAlarmCodes(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS])
89 {
90 _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext);
91
92 _cmsAssert(ContextAlarmCodes != NULL); // Can't happen
93
94 memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes));
95 }
96
97 // Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context.
98 // Values are meant to be encoded in 16 bits.
99 void CMSEXPORT cmsGetAlarmCodes(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS])
100 {
101 _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext);
102
103 _cmsAssert(ContextAlarmCodes != NULL); // Can't happen
104
105 memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes));
106 }
107
108
109 // Init and duplicate alarm codes
110 void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx,
111 const struct _cmsContext_struct* src)
112 {
113 static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE };
114 void* from;
115
116 if (src != NULL) {
117 from = src ->chunks[AlarmCodesContext];
118 }
119 else {
120 from = &AlarmCodesChunk;
121 }
122
123 ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType));
124 }
125
126 // -----------------------------------------------------------------------
127
128 // Get rid of transform resources
129 void CMSEXPORT cmsDeleteTransform(cmsContext ContextID, cmsHTRANSFORM hTransform)
130 {
131 _cmsTRANSFORM* p = (_cmsTRANSFORM*) hTransform;
132 _cmsTRANSFORMCORE *core;
133 cmsUInt32Number refs;
134
135 if (p == NULL)
136 return;
137
138 core = p->core;
139
140 _cmsAssert(core != NULL);
141
142 refs = _cmsAdjustReferenceCount(&core->refs, -1);
143 _cmsFree(ContextID, (void *) p);
144
145 if (refs != 0)
146 return;
147
148 if (core->GamutCheck)
149 cmsPipelineFree(ContextID, core->GamutCheck);
150
151 if (core->Lut)
152 cmsPipelineFree(ContextID, core->Lut);
153
154 if (core->InputColorant)
155 cmsFreeNamedColorList(ContextID, core->InputColorant);
156
157 if (core->OutputColorant)
158 cmsFreeNamedColorList(ContextID, core->OutputColorant);
159
160 if (core->Sequence)
161 cmsFreeProfileSequenceDescription(ContextID, core->Sequence);
162
163 if (core->UserData)
164 core->FreeUserData(ContextID, core->UserData);
165
166 _cmsFree(ContextID, (void *)core);
167 }
168
169
170 static
171 cmsUInt32Number PixelSize(cmsUInt32Number Format)
172 {
173 cmsUInt32Number fmt_bytes = T_BYTES(Format);
174
175 // For double, the T_BYTES field is zero
176 if (fmt_bytes == 0)
177 return sizeof(cmsUInt64Number);
178
179 // Otherwise, it is already correct for all formats
180 return fmt_bytes;
181 }
182
183
184
185
186 // Apply transform.
187 void CMSEXPORT cmsDoTransform(cmsContext ContextID, cmsHTRANSFORM Transform,
188 const void* InputBuffer,
189 void* OutputBuffer,
190 cmsUInt32Number Size)
191
192 {
193 _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
194 cmsStride stride;
195
196 stride.BytesPerLineIn = 0; // Not used
197 stride.BytesPerLineOut = 0;
198 stride.BytesPerPlaneIn = Size * PixelSize(p->InputFormat);
199 stride.BytesPerPlaneOut = Size * PixelSize(p->OutputFormat);
200
201 p -> xform(ContextID, p, InputBuffer, OutputBuffer, Size, 1, &stride);
202 }
203
204
205 // This is a legacy stride for planar
206 void CMSEXPORT cmsDoTransformStride(cmsContext ContextID, cmsHTRANSFORM Transform,
207 const void* InputBuffer,
208 void* OutputBuffer,
209 cmsUInt32Number Size, cmsUInt32Number Stride)
210
211 {
212 _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
213 cmsStride stride;
214
215 stride.BytesPerLineIn = 0;
216 stride.BytesPerLineOut = 0;
217 stride.BytesPerPlaneIn = Stride;
218 stride.BytesPerPlaneOut = Stride;
219
220 p -> xform(ContextID, p, InputBuffer, OutputBuffer, Size, 1, &stride);
221 }
222
223 // This is the "fast" function for plugins
224 void CMSEXPORT cmsDoTransformLineStride(cmsContext ContextID, cmsHTRANSFORM Transform,
225 const void* InputBuffer,
226 void* OutputBuffer,
227 cmsUInt32Number PixelsPerLine,
228 cmsUInt32Number LineCount,
229 cmsUInt32Number BytesPerLineIn,
230 cmsUInt32Number BytesPerLineOut,
231 cmsUInt32Number BytesPerPlaneIn,
232 cmsUInt32Number BytesPerPlaneOut)
233
234 {
235 _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
236 cmsStride stride;
237
238 stride.BytesPerLineIn = BytesPerLineIn;
239 stride.BytesPerLineOut = BytesPerLineOut;
240 stride.BytesPerPlaneIn = BytesPerPlaneIn;
241 stride.BytesPerPlaneOut = BytesPerPlaneOut;
242
243 p->xform(ContextID, p, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, &stride);
244 }
245
246
247
248 // Transform routines ----------------------------------------------------------------------------------------------------------
249
250 // Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check.
251 // Note that because extended range, we can use a -1.0 value for out of gamut in this case.
252 static
253 void FloatXFORM(cmsContext ContextID, _cmsTRANSFORM* p,
254 const void* in,
255 void* out,
256 cmsUInt32Number PixelsPerLine,
257 cmsUInt32Number LineCount,
258 const cmsStride* Stride)
259 {
260 cmsUInt8Number* accum;
261 cmsUInt8Number* output;
262 cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS];
263 cmsFloat32Number OutOfGamut;
264 cmsUInt32Number i, j, c, strideIn, strideOut;
265 _cmsTRANSFORMCORE *core = p->core;
266
267 _cmsHandleExtraChannels(ContextID, p, in, out, PixelsPerLine, LineCount, Stride);
268
269 strideIn = 0;
270 strideOut = 0;
271 memset(fIn, 0, sizeof(fIn));
272 memset(fOut, 0, sizeof(fOut));
273
274 for (i = 0; i < LineCount; i++) {
275
276 accum = (cmsUInt8Number*)in + strideIn;
277 output = (cmsUInt8Number*)out + strideOut;
278
279 for (j = 0; j < PixelsPerLine; j++) {
280
281 accum = p->FromInputFloat(ContextID, p, fIn, accum, Stride->BytesPerPlaneIn);
282
283 // Any gamut chack to do?
284 if (core->GamutCheck != NULL) {
285
286 // Evaluate gamut marker.
287 cmsPipelineEvalFloat(ContextID, fIn, &OutOfGamut, core->GamutCheck);
288
289 // Is current color out of gamut?
290 if (OutOfGamut > 0.0) {
291
292 // Certainly, out of gamut
293 for (c = 0; c < cmsMAXCHANNELS; c++)
294 fOut[c] = -1.0;
295
296 }
297 else {
298 // No, proceed normally
299 cmsPipelineEvalFloat(ContextID, fIn, fOut, core->Lut);
300 }
301 }
302 else {
303
304 // No gamut check at all
305 cmsPipelineEvalFloat(ContextID, fIn, fOut, core->Lut);
306 }
307
308
309 output = p->ToOutputFloat(ContextID, p, fOut, output, Stride->BytesPerPlaneOut);
310 }
311
312 strideIn += Stride->BytesPerLineIn;
313 strideOut += Stride->BytesPerLineOut;
314 }
315
316 }
317
318
319 static
320 void NullFloatXFORM(cmsContext ContextID, _cmsTRANSFORM* p,
321 const void* in,
322 void* out,
323 cmsUInt32Number PixelsPerLine,
324 cmsUInt32Number LineCount,
325 const cmsStride* Stride)
326
327 {
328 cmsUInt8Number* accum;
329 cmsUInt8Number* output;
330 cmsFloat32Number fIn[cmsMAXCHANNELS];
331 cmsUInt32Number i, j, strideIn, strideOut;
332
333 _cmsHandleExtraChannels(ContextID, p, in, out, PixelsPerLine, LineCount, Stride);
334
335 strideIn = 0;
336 strideOut = 0;
337 memset(fIn, 0, sizeof(fIn));
338
339 for (i = 0; i < LineCount; i++) {
340
341 accum = (cmsUInt8Number*) in + strideIn;
342 output = (cmsUInt8Number*) out + strideOut;
343
344 for (j = 0; j < PixelsPerLine; j++) {
345
346 accum = p->FromInputFloat(ContextID, p, fIn, accum, Stride ->BytesPerPlaneIn);
347 output = p->ToOutputFloat(ContextID, p, fIn, output, Stride->BytesPerPlaneOut);
348 }
349
350 strideIn += Stride->BytesPerLineIn;
351 strideOut += Stride->BytesPerLineOut;
352 }
353 }
354
355 static inline int mul255(cmsUInt32Number a, cmsUInt32Number b)
356 {
357 /* see Jim Blinn's book "Dirty Pixels" for how this works */
358 cmsUInt32Number x = a * b + 128;
359 x += x >> 8;
360 return x >> 8;
361 }
362
363 static inline cmsUInt32Number mul65535(cmsUInt32Number a, cmsUInt32Number b)
364 {
365 /* see Jim Blinn's book "Dirty Pixels" for how this works */
366 cmsUInt32Number x = a * b + 0x8000;
367 x += x >> 16;
368 return x >> 16;
369 }
370
371 // 16 bit precision -----------------------------------------------------------------------------------------------------------
372
373 // Null transformation, only applies formatters. No cache
374 static
375 void NullXFORM(cmsContext ContextID,
376 _cmsTRANSFORM* p,
377 const void* in,
378 void* out,
379 cmsUInt32Number PixelsPerLine,
380 cmsUInt32Number LineCount,
381 const cmsStride* Stride)
382 {
383 cmsUInt8Number* accum;
384 cmsUInt8Number* output;
385 cmsUInt16Number wIn[cmsMAXCHANNELS];
386 cmsUInt32Number i, j, strideIn, strideOut;
387
388 _cmsHandleExtraChannels(ContextID, p, in, out, PixelsPerLine, LineCount, Stride);
389
390 strideIn = 0;
391 strideOut = 0;
392 memset(wIn, 0, sizeof(wIn));
393
394 for (i = 0; i < LineCount; i++) {
395
396 accum = (cmsUInt8Number*)in + strideIn;
397 output = (cmsUInt8Number*)out + strideOut;
398
399 for (j = 0; j < PixelsPerLine; j++) {
400
401 accum = p->FromInput(ContextID, p, wIn, accum, Stride->BytesPerPlaneIn);
402 output = p->ToOutput(ContextID, p, wIn, output, Stride->BytesPerPlaneOut);
403 }
404
405 strideIn += Stride->BytesPerLineIn;
406 strideOut += Stride->BytesPerLineOut;
407 }
408
409 }
410
411
412 // No gamut check, no cache, 16 bits
413 #define FUNCTION_NAME PrecalculatedXFORM
414 #include "extra_xform.h"
415
416 // No gamut check, no cache, 16 bits
417 #define PREALPHA
418 #define FUNCTION_NAME PrecalculatedXFORM_P
419 #include "extra_xform.h"
420
421 // No gamut check, no cache, Identity transform, including pack/unpack
422 static
423 void PrecalculatedXFORMIdentity(cmsContext ContextID,
424 _cmsTRANSFORM* p,
425 const void* in,
426 void* out,
427 cmsUInt32Number PixelsPerLine,
428 cmsUInt32Number LineCount,
429 const cmsStride* Stride)
430 {
431 cmsUInt32Number bpli = Stride->BytesPerLineIn;
432 cmsUInt32Number bplo = Stride->BytesPerLineOut;
433 int bpp;
434 cmsUNUSED_PARAMETER(ContextID);
435
436 /* Silence some warnings */
437 (void)bpli;
438 (void)bplo;
439
440 if ((in == out && bpli == bplo) || PixelsPerLine == 0)
441 return;
442
443 bpp = T_BYTES(p->InputFormat);
444 if (bpp == 0)
445 bpp = sizeof(double);
446 bpp *= T_CHANNELS(p->InputFormat) + T_EXTRA(p->InputFormat);
447 PixelsPerLine *= bpp; /* Convert to BytesPerLine */
448 while (LineCount-- > 0)
449 {
450 memmove(out, in, PixelsPerLine);
451 in = (void *)((cmsUInt8Number *)in + bpli);
452 out = (void *)((cmsUInt8Number *)out + bplo);
453 }
454 }
455
456 static
457 void PrecalculatedXFORMIdentityPlanar(cmsContext ContextID,
458 _cmsTRANSFORM* p,
459 const void* in,
460 void* out,
461 cmsUInt32Number PixelsPerLine,
462 cmsUInt32Number LineCount,
463 const cmsStride* Stride)
464 {
465 cmsUInt32Number bpli = Stride->BytesPerLineIn;
466 cmsUInt32Number bplo = Stride->BytesPerLineOut;
467 cmsUInt32Number bppi = Stride->BytesPerPlaneIn;
468 cmsUInt32Number bppo = Stride->BytesPerPlaneOut;
469 int bpp;
470 int planes;
471 const void *plane_in;
472 void *plane_out;
473 cmsUNUSED_PARAMETER(ContextID);
474
475 /* Silence some warnings */
476 (void)bpli;
477 (void)bplo;
478 (void)bppi;
479 (void)bppo;
480
481 if ((in == out && bpli == bplo && bppi == bppo) || PixelsPerLine == 0)
482 return;
483
484 bpp = T_BYTES(p->InputFormat);
485 if (bpp == 0)
486 bpp = sizeof(double);
487 PixelsPerLine *= bpp; /* Convert to BytesPerLine */
488 planes = T_CHANNELS(p->InputFormat) + T_EXTRA(p->InputFormat);
489 while (planes-- > 0)
490 {
491 plane_in = in;
492 plane_out = out;
493 while (LineCount-- > 0)
494 {
495 memmove(plane_out, plane_in, PixelsPerLine);
496 plane_in = (void *)((cmsUInt8Number *)plane_in + bpli);
497 plane_out = (void *)((cmsUInt8Number *)plane_out + bplo);
498 }
499 in = (void *)((cmsUInt8Number *)in + bppi);
500 out = (void *)((cmsUInt8Number *)out + bppo);
501 }
502 }
503
504 // Auxiliary: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical.
505 static
506 void TransformOnePixelWithGamutCheck(cmsContext ContextID, _cmsTRANSFORM* p,
507 const cmsUInt16Number wIn[],
508 cmsUInt16Number wOut[])
509 {
510 cmsUInt16Number wOutOfGamut;
511 _cmsTRANSFORMCORE *core = p->core;
512
513 core->GamutCheck->Eval16Fn(ContextID, wIn, &wOutOfGamut, core->GamutCheck->Data);
514 if (wOutOfGamut >= 1) {
515
516 cmsUInt32Number i;
517 cmsUInt32Number n = core->Lut->OutputChannels;
518 _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext);
519
520 for (i=0; i < n; i++) {
521
522 wOut[i] = ContextAlarmCodes ->AlarmCodes[i];
523 }
524 }
525 else
526 core->Lut->Eval16Fn(ContextID, wIn, wOut, core->Lut->Data);
527 }
528
529 // Gamut check, No cache, 16 bits.
530 #define FUNCTION_NAME PrecalculatedXFORMGamutCheck
531 #define GAMUTCHECK
532 #include "extra_xform.h"
533
534 // Gamut check, No cache, 16 bits.
535 #define FUNCTION_NAME PrecalculatedXFORMGamutCheck_P
536 #define PREALPHA
537 #define GAMUTCHECK
538 #include "extra_xform.h"
539
540 // No gamut check, Cache, 16 bits,
541 #define FUNCTION_NAME CachedXFORM
542 #define CACHED
543 #include "extra_xform.h"
544
545 // All those nice features together
546 #define FUNCTION_NAME CachedXFORMGamutCheck
547 #define CACHED
548 #define GAMUTCHECK
549 #include "extra_xform.h"
550
551 // All those nice features together
552 #define FUNCTION_NAME CachedXFORMGamutCheck_P
553 #define CACHED
554 #define PREALPHA
555 #define GAMUTCHECK
556 #include "extra_xform.h"
557
558 // No gamut check, Cache, 16 bits, <= 4 bytes
559 #define FUNCTION_NAME CachedXFORM4
560 #define CACHED
561 #define CMPBYTES 4
562 #define NUMEXTRAS 0
563 #include "extra_xform.h"
564
565 // No gamut check, Cache, 16 bits, <= 8 bytes total
566 #define FUNCTION_NAME CachedXFORM8
567 #define CACHED
568 #define CMPBYTES 8
569 #define NUMEXTRAS 0
570 #include "extra_xform.h"
571
572 // Special ones for common cases.
573 #define FUNCTION_NAME CachedXFORM1to1
574 #define CACHED
575 #define INPACKEDSAMPLESIZE 1
576 #define OUTPACKEDSAMPLESIZE 1
577 #define NUMINCHANNELS 1
578 #define NUMOUTCHANNELS 1
579 #define NUMEXTRAS 0
580 #define UNPACK(CTX,T,D,S,Z,A) \
581 do { \
582 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
583 } while (0)
584 #define PACK(CTX,T,S,D,Z,A) \
585 do { \
586 *(D)++ = FROM_16_TO_8((S)[0]); \
587 } while (0)
588 #include "extra_xform.h"
589
590 #define FUNCTION_NAME CachedXFORM1x2to1x2
591 #define CACHED
592 #define INPACKEDSAMPLESIZE 2
593 #define OUTPACKEDSAMPLESIZE 2
594 #define NUMINCHANNELS 1
595 #define NUMOUTCHANNELS 1
596 #define NUMEXTRAS 0
597 #define UNPACK(CTX,T,D,S,Z,A) \
598 do { \
599 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
600 } while (0)
601 #define PACK(CTX,T,S,D,Z,A) \
602 do { \
603 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
604 } while (0)
605 #include "extra_xform.h"
606
607 #define FUNCTION_NAME CachedXFORM1to3
608 #define CACHED
609 #define INPACKEDSAMPLESIZE 1
610 #define OUTPACKEDSAMPLESIZE 1
611 #define NUMINCHANNELS 1
612 #define NUMOUTCHANNELS 3
613 #define NUMEXTRAS 0
614 #define UNPACK(CTX,T,D,S,Z,A) \
615 do { \
616 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
617 } while (0)
618 #define PACK(CTX,T,S,D,Z,A) \
619 do { \
620 *(D)++ = FROM_16_TO_8((S)[0]); \
621 *(D)++ = FROM_16_TO_8((S)[1]); \
622 *(D)++ = FROM_16_TO_8((S)[2]); \
623 } while (0)
624 #include "extra_xform.h"
625
626 #define FUNCTION_NAME CachedXFORM1x2to3x2
627 #define CACHED
628 #define INPACKEDSAMPLESIZE 2
629 #define OUTPACKEDSAMPLESIZE 2
630 #define NUMINCHANNELS 1
631 #define NUMOUTCHANNELS 3
632 #define NUMEXTRAS 0
633 #define UNPACK(CTX,T,D,S,Z,A) \
634 do { \
635 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
636 } while (0)
637 #define PACK(CTX,T,S,D,Z,A) \
638 do { \
639 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
640 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
641 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
642 } while (0)
643 #include "extra_xform.h"
644
645 #define FUNCTION_NAME CachedXFORM1to4
646 #define CACHED
647 #define INPACKEDSAMPLESIZE 1
648 #define OUTPACKEDSAMPLESIZE 1
649 #define NUMINCHANNELS 1
650 #define NUMOUTCHANNELS 4
651 #define NUMEXTRAS 0
652 #define UNPACK(CTX,T,D,S,Z,A) \
653 do { \
654 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
655 } while (0)
656 #define PACK(CTX,T,S,D,Z,A) \
657 do { \
658 *(D)++ = FROM_16_TO_8((S)[0]); \
659 *(D)++ = FROM_16_TO_8((S)[1]); \
660 *(D)++ = FROM_16_TO_8((S)[2]); \
661 *(D)++ = FROM_16_TO_8((S)[3]); \
662 } while (0)
663 #include "extra_xform.h"
664
665 #define FUNCTION_NAME CachedXFORM1x2to4x2
666 #define CACHED
667 #define INPACKEDSAMPLESIZE 2
668 #define OUTPACKEDSAMPLESIZE 2
669 #define NUMINCHANNELS 1
670 #define NUMOUTCHANNELS 4
671 #define NUMEXTRAS 0
672 #define UNPACK(CTX,T,D,S,Z,A) \
673 do { \
674 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
675 } while (0)
676 #define PACK(CTX,T,S,D,Z,A) \
677 do { \
678 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
679 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
680 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
681 *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \
682 } while (0)
683 #include "extra_xform.h"
684
685 #define FUNCTION_NAME CachedXFORM3to1
686 #define CACHED
687 #define INPACKEDSAMPLESIZE 1
688 #define OUTPACKEDSAMPLESIZE 1
689 #define NUMINCHANNELS 3
690 #define NUMOUTCHANNELS 1
691 #define NUMEXTRAS 0
692 #define UNPACK(CTX,T,D,S,Z,A) \
693 do { \
694 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
695 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
696 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
697 } while (0)
698 #define PACK(CTX,T,S,D,Z,A) \
699 do { \
700 *(D)++ = FROM_16_TO_8((S)[0]); \
701 } while (0)
702 #include "extra_xform.h"
703
704 #define FUNCTION_NAME CachedXFORM3x2to1x2
705 #define CACHED
706 #define INPACKEDSAMPLESIZE 2
707 #define OUTPACKEDSAMPLESIZE 2
708 #define NUMINCHANNELS 3
709 #define NUMOUTCHANNELS 1
710 #define NUMEXTRAS 0
711 #define UNPACK(CTX,T,D,S,Z,A) \
712 do { \
713 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
714 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
715 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
716 } while (0)
717 #define PACK(CTX,T,S,D,Z,A) \
718 do { \
719 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
720 } while (0)
721 #include "extra_xform.h"
722
723 #define FUNCTION_NAME CachedXFORM3to3
724 #define CACHED
725 #define INPACKEDSAMPLESIZE 1
726 #define OUTPACKEDSAMPLESIZE 1
727 #define NUMINCHANNELS 3
728 #define NUMOUTCHANNELS 3
729 #define NUMEXTRAS 0
730 #define UNPACK(CTX,T,D,S,Z,A) \
731 do { \
732 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
733 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
734 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
735 } while (0)
736 #define PACK(CTX,T,S,D,Z,A) \
737 do { \
738 *(D)++ = FROM_16_TO_8((S)[0]); \
739 *(D)++ = FROM_16_TO_8((S)[1]); \
740 *(D)++ = FROM_16_TO_8((S)[2]); \
741 } while (0)
742 #include "extra_xform.h"
743
744 #define FUNCTION_NAME CachedXFORM3x2to3x2
745 #define CACHED
746 #define INPACKEDSAMPLESIZE 2
747 #define OUTPACKEDSAMPLESIZE 2
748 #define NUMINCHANNELS 3
749 #define NUMOUTCHANNELS 3
750 #define NUMEXTRAS 0
751 #define UNPACK(CTX,T,D,S,Z,A) \
752 do { \
753 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
754 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
755 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
756 } while (0)
757 #define PACK(CTX,T,S,D,Z,A) \
758 do { \
759 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
760 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
761 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
762 } while (0)
763 #include "extra_xform.h"
764
765 #define FUNCTION_NAME CachedXFORM3to4
766 #define CACHED
767 #define INPACKEDSAMPLESIZE 1
768 #define OUTPACKEDSAMPLESIZE 1
769 #define NUMINCHANNELS 3
770 #define NUMOUTCHANNELS 4
771 #define NUMEXTRAS 0
772 #define UNPACK(CTX,T,D,S,Z,A) \
773 do { \
774 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
775 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
776 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
777 } while (0)
778 #define PACK(CTX,T,S,D,Z,A) \
779 do { \
780 *(D)++ = FROM_16_TO_8((S)[0]); \
781 *(D)++ = FROM_16_TO_8((S)[1]); \
782 *(D)++ = FROM_16_TO_8((S)[2]); \
783 *(D)++ = FROM_16_TO_8((S)[3]); \
784 } while (0)
785 #include "extra_xform.h"
786
787 #define FUNCTION_NAME CachedXFORM3x2to4x2
788 #define CACHED
789 #define INPACKEDSAMPLESIZE 2
790 #define OUTPACKEDSAMPLESIZE 2
791 #define NUMINCHANNELS 3
792 #define NUMOUTCHANNELS 4
793 #define NUMEXTRAS 0
794 #define UNPACK(CTX,T,D,S,Z,A) \
795 do { \
796 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
797 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
798 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
799 } while (0)
800 #define PACK(CTX,T,S,D,Z,A) \
801 do { \
802 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
803 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
804 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
805 *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \
806 } while (0)
807 #include "extra_xform.h"
808
809 #define FUNCTION_NAME CachedXFORM4to1
810 #define CACHED
811 #define INPACKEDSAMPLESIZE 1
812 #define OUTPACKEDSAMPLESIZE 1
813 #define NUMINCHANNELS 4
814 #define NUMOUTCHANNELS 1
815 #define NUMEXTRAS 0
816 #define UNPACK(CTX,T,D,S,Z,A) \
817 do { \
818 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
819 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
820 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
821 (D)[3] = FROM_8_TO_16(*(S)); (S)++; \
822 } while (0)
823 #define PACK(CTX,T,S,D,Z,A) \
824 do { \
825 *(D)++ = FROM_16_TO_8((S)[0]); \
826 } while (0)
827 #include "extra_xform.h"
828
829 #define FUNCTION_NAME CachedXFORM4x2to1x2
830 #define CACHED
831 #define INPACKEDSAMPLESIZE 2
832 #define OUTPACKEDSAMPLESIZE 2
833 #define NUMINCHANNELS 4
834 #define NUMOUTCHANNELS 1
835 #define NUMEXTRAS 0
836 #define UNPACK(CTX,T,D,S,Z,A) \
837 do { \
838 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
839 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
840 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
841 (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \
842 } while (0)
843 #define PACK(CTX,T,S,D,Z,A) \
844 do { \
845 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
846 } while (0)
847 #include "extra_xform.h"
848
849 #define FUNCTION_NAME CachedXFORM4to3
850 #define CACHED
851 #define INPACKEDSAMPLESIZE 1
852 #define OUTPACKEDSAMPLESIZE 1
853 #define NUMINCHANNELS 4
854 #define NUMOUTCHANNELS 3
855 #define NUMEXTRAS 0
856 #define UNPACK(CTX,T,D,S,Z,A) \
857 do { \
858 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
859 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
860 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
861 (D)[3] = FROM_8_TO_16(*(S)); (S)++; \
862 } while (0)
863 #define PACK(CTX,T,S,D,Z,A) \
864 do { \
865 *(D)++ = FROM_16_TO_8((S)[0]); \
866 *(D)++ = FROM_16_TO_8((S)[1]); \
867 *(D)++ = FROM_16_TO_8((S)[2]); \
868 } while (0)
869 #include "extra_xform.h"
870
871 #define FUNCTION_NAME CachedXFORM4x2to3x2
872 #define CACHED
873 #define INPACKEDSAMPLESIZE 2
874 #define OUTPACKEDSAMPLESIZE 2
875 #define NUMINCHANNELS 4
876 #define NUMOUTCHANNELS 3
877 #define NUMEXTRAS 0
878 #define UNPACK(CTX,T,D,S,Z,A) \
879 do { \
880 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
881 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
882 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
883 (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \
884 } while (0)
885 #define PACK(CTX,T,S,D,Z,A) \
886 do { \
887 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
888 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
889 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
890 } while (0)
891 #include "extra_xform.h"
892
893 #define FUNCTION_NAME CachedXFORM4to4
894 #define CACHED
895 #define INPACKEDSAMPLESIZE 1
896 #define OUTPACKEDSAMPLESIZE 1
897 #define NUMINCHANNELS 4
898 #define NUMOUTCHANNELS 4
899 #define NUMEXTRAS 0
900 #define UNPACK(CTX,T,D,S,Z,A) \
901 do { \
902 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
903 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
904 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
905 (D)[3] = FROM_8_TO_16(*(S)); (S)++; \
906 } while (0)
907 #define PACK(CTX,T,S,D,Z,A) \
908 do { \
909 *(D)++ = FROM_16_TO_8((S)[0]); \
910 *(D)++ = FROM_16_TO_8((S)[1]); \
911 *(D)++ = FROM_16_TO_8((S)[2]); \
912 *(D)++ = FROM_16_TO_8((S)[3]); \
913 } while (0)
914 #include "extra_xform.h"
915
916 #define FUNCTION_NAME CachedXFORM4x2to4x2
917 #define CACHED
918 #define INPACKEDSAMPLESIZE 2
919 #define OUTPACKEDSAMPLESIZE 2
920 #define NUMINCHANNELS 4
921 #define NUMOUTCHANNELS 4
922 #define NUMEXTRAS 0
923 #define UNPACK(CTX,T,D,S,Z,A) \
924 do { \
925 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
926 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
927 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
928 (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \
929 } while (0)
930 #define PACK(CTX,T,S,D,Z,A) \
931 do { \
932 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
933 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
934 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
935 *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \
936 } while (0)
937 #include "extra_xform.h"
938
939 // Same again, but with alpha
940 // Special ones for common cases.
941 #define FUNCTION_NAME CachedXFORM1to1_1
942 #define CACHED
943 #define INPACKEDSAMPLESIZE 1
944 #define OUTPACKEDSAMPLESIZE 1
945 #define NUMINCHANNELS 1
946 #define NUMOUTCHANNELS 1
947 #define NUMEXTRAS 1
948 #define UNPACK(CTX,T,D,S,Z,A) \
949 do { \
950 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
951 } while (0)
952 #define PACK(CTX,T,S,D,Z,A) \
953 do { \
954 *(D)++ = FROM_16_TO_8((S)[0]); \
955 } while (0)
956 #include "extra_xform.h"
957
958 #define FUNCTION_NAME CachedXFORM1x2to1x2_2
959 #define CACHED
960 #define INPACKEDSAMPLESIZE 2
961 #define OUTPACKEDSAMPLESIZE 2
962 #define NUMINCHANNELS 1
963 #define NUMOUTCHANNELS 1
964 #define NUMEXTRAS 1
965 #define UNPACK(CTX,T,D,S,Z,A) \
966 do { \
967 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
968 } while (0)
969 #define PACK(CTX,T,S,D,Z,A) \
970 do { \
971 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
972 } while (0)
973 #include "extra_xform.h"
974
975 #define FUNCTION_NAME CachedXFORM1to3_1
976 #define CACHED
977 #define INPACKEDSAMPLESIZE 1
978 #define OUTPACKEDSAMPLESIZE 3
979 #define NUMINCHANNELS 1
980 #define NUMOUTCHANNELS 1
981 #define NUMEXTRAS 1
982 #define UNPACK(CTX,T,D,S,Z,A) \
983 do { \
984 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
985 } while (0)
986 #define PACK(CTX,T,S,D,Z,A) \
987 do { \
988 *(D)++ = FROM_16_TO_8((S)[0]); \
989 *(D)++ = FROM_16_TO_8((S)[1]); \
990 *(D)++ = FROM_16_TO_8((S)[2]); \
991 } while (0)
992 #include "extra_xform.h"
993
994 #define FUNCTION_NAME CachedXFORM1x2to3x2_2
995 #define CACHED
996 #define INPACKEDSAMPLESIZE 2
997 #define OUTPACKEDSAMPLESIZE 2
998 #define NUMINCHANNELS 1
999 #define NUMOUTCHANNELS 3
1000 #define NUMEXTRAS 1
1001 #define UNPACK(CTX,T,D,S,Z,A) \
1002 do { \
1003 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1004 } while (0)
1005 #define PACK(CTX,T,S,D,Z,A) \
1006 do { \
1007 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1008 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
1009 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
1010 } while (0)
1011 #include "extra_xform.h"
1012
1013 #define FUNCTION_NAME CachedXFORM1to4_1
1014 #define CACHED
1015 #define INPACKEDSAMPLESIZE 1
1016 #define OUTPACKEDSAMPLESIZE 1
1017 #define NUMINCHANNELS 1
1018 #define NUMOUTCHANNELS 4
1019 #define NUMEXTRAS 1
1020 #define UNPACK(CTX,T,D,S,Z,A) \
1021 do { \
1022 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1023 } while (0)
1024 #define PACK(CTX,T,S,D,Z,A) \
1025 do { \
1026 *(D)++ = FROM_16_TO_8((S)[0]); \
1027 *(D)++ = FROM_16_TO_8((S)[1]); \
1028 *(D)++ = FROM_16_TO_8((S)[2]); \
1029 *(D)++ = FROM_16_TO_8((S)[3]); \
1030 } while (0)
1031 #include "extra_xform.h"
1032
1033 #define FUNCTION_NAME CachedXFORM1x2to4x2_2
1034 #define CACHED
1035 #define INPACKEDSAMPLESIZE 2
1036 #define OUTPACKEDSAMPLESIZE 2
1037 #define NUMINCHANNELS 1
1038 #define NUMOUTCHANNELS 4
1039 #define NUMEXTRAS 1
1040 #define UNPACK(CTX,T,D,S,Z,A) \
1041 do { \
1042 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1043 } while (0)
1044 #define PACK(CTX,T,S,D,Z,A) \
1045 do { \
1046 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1047 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
1048 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
1049 *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \
1050 } while (0)
1051 #include "extra_xform.h"
1052
1053 #define FUNCTION_NAME CachedXFORM3to1_1
1054 #define CACHED
1055 #define INPACKEDSAMPLESIZE 1
1056 #define OUTPACKEDSAMPLESIZE 1
1057 #define NUMINCHANNELS 3
1058 #define NUMOUTCHANNELS 1
1059 #define NUMEXTRAS 1
1060 #define UNPACK(CTX,T,D,S,Z,A) \
1061 do { \
1062 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1063 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
1064 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
1065 } while (0)
1066 #define PACK(CTX,T,S,D,Z,A) \
1067 do { \
1068 *(D)++ = FROM_16_TO_8((S)[0]); \
1069 } while (0)
1070 #include "extra_xform.h"
1071
1072 #define FUNCTION_NAME CachedXFORM3x2to1x2_2
1073 #define CACHED
1074 #define INPACKEDSAMPLESIZE 2
1075 #define OUTPACKEDSAMPLESIZE 2
1076 #define NUMINCHANNELS 3
1077 #define NUMOUTCHANNELS 1
1078 #define NUMEXTRAS 1
1079 #define UNPACK(CTX,T,D,S,Z,A) \
1080 do { \
1081 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1082 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
1083 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
1084 } while (0)
1085 #define PACK(CTX,T,S,D,Z,A) \
1086 do { \
1087 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1088 } while (0)
1089 #include "extra_xform.h"
1090
1091 #define FUNCTION_NAME CachedXFORM3to3_1
1092 #define CACHED
1093 #define INPACKEDSAMPLESIZE 1
1094 #define OUTPACKEDSAMPLESIZE 1
1095 #define NUMINCHANNELS 3
1096 #define NUMOUTCHANNELS 3
1097 #define NUMEXTRAS 1
1098 #define UNPACK(CTX,T,D,S,Z,A) \
1099 do { \
1100 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1101 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
1102 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
1103 } while (0)
1104 #define PACK(CTX,T,S,D,Z,A) \
1105 do { \
1106 *(D)++ = FROM_16_TO_8((S)[0]); \
1107 *(D)++ = FROM_16_TO_8((S)[1]); \
1108 *(D)++ = FROM_16_TO_8((S)[2]); \
1109 } while (0)
1110 #include "extra_xform.h"
1111
1112 #define FUNCTION_NAME CachedXFORM3x2to3x2_2
1113 #define CACHED
1114 #define INPACKEDSAMPLESIZE 2
1115 #define OUTPACKEDSAMPLESIZE 2
1116 #define NUMINCHANNELS 3
1117 #define NUMOUTCHANNELS 3
1118 #define NUMEXTRAS 1
1119 #define UNPACK(CTX,T,D,S,Z,A) \
1120 do { \
1121 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1122 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
1123 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
1124 } while (0)
1125 #define PACK(CTX,T,S,D,Z,A) \
1126 do { \
1127 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1128 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
1129 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
1130 } while (0)
1131 #include "extra_xform.h"
1132
1133 #define FUNCTION_NAME CachedXFORM3to4_1
1134 #define CACHED
1135 #define INPACKEDSAMPLESIZE 1
1136 #define OUTPACKEDSAMPLESIZE 1
1137 #define NUMINCHANNELS 3
1138 #define NUMOUTCHANNELS 4
1139 #define NUMEXTRAS 1
1140 #define UNPACK(CTX,T,D,S,Z,A) \
1141 do { \
1142 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1143 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
1144 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
1145 } while (0)
1146 #define PACK(CTX,T,S,D,Z,A) \
1147 do { \
1148 *(D)++ = FROM_16_TO_8((S)[0]); \
1149 *(D)++ = FROM_16_TO_8((S)[1]); \
1150 *(D)++ = FROM_16_TO_8((S)[2]); \
1151 *(D)++ = FROM_16_TO_8((S)[3]); \
1152 } while (0)
1153 #include "extra_xform.h"
1154
1155 #define FUNCTION_NAME CachedXFORM3x2to4x2_2
1156 #define CACHED
1157 #define INPACKEDSAMPLESIZE 2
1158 #define OUTPACKEDSAMPLESIZE 2
1159 #define NUMINCHANNELS 3
1160 #define NUMOUTCHANNELS 4
1161 #define NUMEXTRAS 1
1162 #define UNPACK(CTX,T,D,S,Z,A) \
1163 do { \
1164 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1165 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
1166 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
1167 } while (0)
1168 #define PACK(CTX,T,S,D,Z,A) \
1169 do { \
1170 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1171 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
1172 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
1173 *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \
1174 } while (0)
1175 #include "extra_xform.h"
1176
1177 #define FUNCTION_NAME CachedXFORM4to1_1
1178 #define CACHED
1179 #define INPACKEDSAMPLESIZE 1
1180 #define OUTPACKEDSAMPLESIZE 1
1181 #define NUMINCHANNELS 4
1182 #define NUMOUTCHANNELS 1
1183 #define NUMEXTRAS 1
1184 #define UNPACK(CTX,T,D,S,Z,A) \
1185 do { \
1186 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1187 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
1188 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
1189 (D)[3] = FROM_8_TO_16(*(S)); (S)++; \
1190 } while (0)
1191 #define PACK(CTX,T,S,D,Z,A) \
1192 do { \
1193 *(D)++ = FROM_16_TO_8((S)[0]); \
1194 } while (0)
1195 #include "extra_xform.h"
1196
1197 #define FUNCTION_NAME CachedXFORM4x2to1x2_2
1198 #define CACHED
1199 #define INPACKEDSAMPLESIZE 2
1200 #define OUTPACKEDSAMPLESIZE 2
1201 #define NUMINCHANNELS 1
1202 #define NUMOUTCHANNELS 1
1203 #define NUMEXTRAS 1
1204 #define UNPACK(CTX,T,D,S,Z,A) \
1205 do { \
1206 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1207 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
1208 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
1209 (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \
1210 } while (0)
1211 #define PACK(CTX,T,S,D,Z,A) \
1212 do { \
1213 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1214 } while (0)
1215 #include "extra_xform.h"
1216
1217 #define FUNCTION_NAME CachedXFORM4to3_1
1218 #define CACHED
1219 #define INPACKEDSAMPLESIZE 1
1220 #define OUTPACKEDSAMPLESIZE 1
1221 #define NUMINCHANNELS 4
1222 #define NUMOUTCHANNELS 3
1223 #define NUMEXTRAS 1
1224 #define UNPACK(CTX,T,D,S,Z,A) \
1225 do { \
1226 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1227 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
1228 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
1229 (D)[3] = FROM_8_TO_16(*(S)); (S)++; \
1230 } while (0)
1231 #define PACK(CTX,T,S,D,Z,A) \
1232 do { \
1233 *(D)++ = FROM_16_TO_8((S)[0]); \
1234 *(D)++ = FROM_16_TO_8((S)[1]); \
1235 *(D)++ = FROM_16_TO_8((S)[2]); \
1236 } while (0)
1237 #include "extra_xform.h"
1238
1239 #define FUNCTION_NAME CachedXFORM4x2to3x2_2
1240 #define CACHED
1241 #define INPACKEDSAMPLESIZE 2
1242 #define OUTPACKEDSAMPLESIZE 2
1243 #define NUMINCHANNELS 4
1244 #define NUMOUTCHANNELS 3
1245 #define NUMEXTRAS 1
1246 #define UNPACK(CTX,T,D,S,Z,A) \
1247 do { \
1248 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1249 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
1250 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
1251 (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \
1252 } while (0)
1253 #define PACK(CTX,T,S,D,Z,A) \
1254 do { \
1255 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1256 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
1257 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
1258 } while (0)
1259 #include "extra_xform.h"
1260
1261 #define FUNCTION_NAME CachedXFORM4to4_1
1262 #define CACHED
1263 #define INPACKEDSAMPLESIZE 1
1264 #define OUTPACKEDSAMPLESIZE 1
1265 #define NUMINCHANNELS 4
1266 #define NUMOUTCHANNELS 4
1267 #define NUMEXTRAS 1
1268 #define UNPACK(CTX,T,D,S,Z,A) \
1269 do { \
1270 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \
1271 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \
1272 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \
1273 (D)[3] = FROM_8_TO_16(*(S)); (S)++; \
1274 } while (0)
1275 #define PACK(CTX,T,S,D,Z,A) \
1276 do { \
1277 *(D)++ = FROM_16_TO_8((S)[0]); \
1278 *(D)++ = FROM_16_TO_8((S)[1]); \
1279 *(D)++ = FROM_16_TO_8((S)[2]); \
1280 *(D)++ = FROM_16_TO_8((S)[3]); \
1281 } while (0)
1282 #include "extra_xform.h"
1283
1284 #define FUNCTION_NAME CachedXFORM4x2to4x2_2
1285 #define CACHED
1286 #define INPACKEDSAMPLESIZE 2
1287 #define OUTPACKEDSAMPLESIZE 2
1288 #define NUMINCHANNELS 4
1289 #define NUMOUTCHANNELS 4
1290 #define NUMEXTRAS 1
1291 #define UNPACK(CTX,T,D,S,Z,A) \
1292 do { \
1293 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \
1294 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \
1295 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \
1296 (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \
1297 } while (0)
1298 #define PACK(CTX,T,S,D,Z,A) \
1299 do { \
1300 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \
1301 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \
1302 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \
1303 *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \
1304 } while (0)
1305 #include "extra_xform.h"
1306
1307
1308 // Same again, but with premultiplied alpha
1309 //
1310 // No gamut check, Cache, 16 bits,
1311 #define FUNCTION_NAME CachedXFORM_P1
1312 #define CACHED
1313 #define INPACKEDSAMPLESIZE 1
1314 #define OUTPACKEDSAMPLESIZE 1
1315 #define PREALPHA
1316 #include "extra_xform.h"
1317
1318 // No gamut check, Cache, 16 bits,
1319 #define FUNCTION_NAME CachedXFORM_P2
1320 #define CACHED
1321 #define INPACKEDSAMPLESIZE 2
1322 #define OUTPACKEDSAMPLESIZE 2
1323 #define PREALPHA
1324 #include "extra_xform.h"
1325
1326 // Special ones for common cases.
1327 #define FUNCTION_NAME CachedXFORM1to1_P1
1328 #define CACHED
1329 #define INPACKEDSAMPLESIZE 1
1330 #define OUTPACKEDSAMPLESIZE 1
1331 #define NUMINCHANNELS 1
1332 #define NUMOUTCHANNELS 1
1333 #define NUMEXTRAS 1
1334 #define PREALPHA
1335 #define UNPACKINCLUDESPREALPHA
1336 #define PACKINCLUDESPREALPHA
1337 #define UNPACK(CTX,T,D,S,Z,A) \
1338 do { \
1339 cmsUInt32Number inva = 0xFFFFU / (A); \
1340 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1341 } while (0)
1342 #define PACK(CTX,T,S,D,Z,A) \
1343 do { \
1344 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1345 } while (0)
1346 #include "extra_xform.h"
1347
1348 #define FUNCTION_NAME CachedXFORM1x2to1x2_P2
1349 #define CACHED
1350 #define INPACKEDSAMPLESIZE 2
1351 #define OUTPACKEDSAMPLESIZE 2
1352 #define NUMINCHANNELS 1
1353 #define NUMOUTCHANNELS 1
1354 #define NUMEXTRAS 1
1355 #define PREALPHA
1356 #define UNPACKINCLUDESPREALPHA
1357 #define PACKINCLUDESPREALPHA
1358 #define UNPACK(CTX,T,D,S,Z,A) \
1359 do { \
1360 cmsUInt32Number inva = 0xffff0000U / (A); \
1361 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1362 } while (0)
1363 #define PACK(CTX,T,S,D,Z,A) \
1364 do { \
1365 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1366 } while (0)
1367 #include "extra_xform.h"
1368
1369 #define FUNCTION_NAME CachedXFORM1to3_P1
1370 #define CACHED
1371 #define INPACKEDSAMPLESIZE 1
1372 #define OUTPACKEDSAMPLESIZE 1
1373 #define NUMINCHANNELS 1
1374 #define NUMOUTCHANNELS 3
1375 #define NUMEXTRAS 1
1376 #define PREALPHA
1377 #define UNPACKINCLUDESPREALPHA
1378 #define PACKINCLUDESPREALPHA
1379 #define UNPACK(CTX,T,D,S,Z,A) \
1380 do { \
1381 cmsUInt32Number inva = 0xFFFFU / (A); \
1382 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1383 } while (0)
1384 #define PACK(CTX,T,S,D,Z,A) \
1385 do { \
1386 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1387 *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \
1388 *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \
1389 } while (0)
1390 #include "extra_xform.h"
1391
1392 #define FUNCTION_NAME CachedXFORM1x2to3x2_P2
1393 #define CACHED
1394 #define INPACKEDSAMPLESIZE 2
1395 #define OUTPACKEDSAMPLESIZE 2
1396 #define NUMINCHANNELS 1
1397 #define NUMOUTCHANNELS 3
1398 #define NUMEXTRAS 1
1399 #define PREALPHA
1400 #define UNPACKINCLUDESPREALPHA
1401 #define PACKINCLUDESPREALPHA
1402 #define UNPACK(CTX,T,D,S,Z,A) \
1403 do { \
1404 cmsUInt32Number inva = 0xffff0000U / (A); \
1405 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1406 } while (0)
1407 #define PACK(CTX,T,S,D,Z,A) \
1408 do { \
1409 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1410 *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \
1411 *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \
1412 } while (0)
1413 #include "extra_xform.h"
1414
1415 #define FUNCTION_NAME CachedXFORM1to4_P1
1416 #define CACHED
1417 #define INPACKEDSAMPLESIZE 1
1418 #define OUTPACKEDSAMPLESIZE 1
1419 #define NUMINCHANNELS 1
1420 #define NUMOUTCHANNELS 4
1421 #define NUMEXTRAS 1
1422 #define PREALPHA
1423 #define UNPACKINCLUDESPREALPHA
1424 #define PACKINCLUDESPREALPHA
1425 #define UNPACK(CTX,T,D,S,Z,A) \
1426 do { \
1427 cmsUInt32Number inva = 0xFFFFU / (A); \
1428 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1429 } while (0)
1430 #define PACK(CTX,T,S,D,Z,A) \
1431 do { \
1432 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1433 *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \
1434 *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \
1435 *(D)++ = mul255(FROM_16_TO_8((S)[3]),(A)); \
1436 } while (0)
1437 #include "extra_xform.h"
1438
1439 #define FUNCTION_NAME CachedXFORM1x2to4x2_P2
1440 #define CACHED
1441 #define INPACKEDSAMPLESIZE 2
1442 #define OUTPACKEDSAMPLESIZE 2
1443 #define NUMINCHANNELS 1
1444 #define NUMOUTCHANNELS 4
1445 #define NUMEXTRAS 1
1446 #define PREALPHA
1447 #define UNPACKINCLUDESPREALPHA
1448 #define PACKINCLUDESPREALPHA
1449 #define UNPACK(CTX,T,D,S,Z,A) \
1450 do { \
1451 cmsUInt32Number inva = 0xffff0000U / (A); \
1452 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1453 } while (0)
1454 #define PACK(CTX,T,S,D,Z,A) \
1455 do { \
1456 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1457 *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \
1458 *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \
1459 *(cmsUInt16Number *)(D) = mul65535((S)[3],A); (D) += 2; \
1460 } while (0)
1461 #include "extra_xform.h"
1462
1463 #define FUNCTION_NAME CachedXFORM3to1_P1
1464 #define CACHED
1465 #define INPACKEDSAMPLESIZE 1
1466 #define OUTPACKEDSAMPLESIZE 1
1467 #define NUMINCHANNELS 3
1468 #define NUMOUTCHANNELS 1
1469 #define NUMEXTRAS 1
1470 #define PREALPHA
1471 #define UNPACKINCLUDESPREALPHA
1472 #define PACKINCLUDESPREALPHA
1473 #define UNPACK(CTX,T,D,S,Z,A) \
1474 do { \
1475 cmsUInt32Number inva = 0xFFFFU / (A); \
1476 (D)[0] = (cmsUInt16Number)((*(S) * inva)); (S)++; \
1477 (D)[1] = (cmsUInt16Number)((*(S) * inva)); (S)++; \
1478 (D)[2] = (cmsUInt16Number)((*(S) * inva)); (S)++; \
1479 } while (0)
1480 #define PACK(CTX,T,S,D,Z,A) \
1481 do { \
1482 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1483 } while (0)
1484 #include "extra_xform.h"
1485
1486 #define FUNCTION_NAME CachedXFORM3x2to1x2_P2
1487 #define CACHED
1488 #define INPACKEDSAMPLESIZE 2
1489 #define OUTPACKEDSAMPLESIZE 2
1490 #define NUMINCHANNELS 3
1491 #define NUMOUTCHANNELS 1
1492 #define NUMEXTRAS 1
1493 #define PREALPHA
1494 #define UNPACKINCLUDESPREALPHA
1495 #define PACKINCLUDESPREALPHA
1496 #define UNPACK(CTX,T,D,S,Z,A) \
1497 do { \
1498 cmsUInt32Number inva = 0xffff0000U / (A); \
1499 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1500 (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1501 (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1502 } while (0)
1503 #define PACK(CTX,T,S,D,Z,A) \
1504 do { \
1505 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1506 } while (0)
1507 #include "extra_xform.h"
1508
1509 #define FUNCTION_NAME CachedXFORM3to3_P1
1510 #define CACHED
1511 #define INPACKEDSAMPLESIZE 1
1512 #define OUTPACKEDSAMPLESIZE 1
1513 #define NUMINCHANNELS 3
1514 #define NUMOUTCHANNELS 3
1515 #define NUMEXTRAS 1
1516 #define PREALPHA
1517 #define UNPACKINCLUDESPREALPHA
1518 #define PACKINCLUDESPREALPHA
1519 #define UNPACK(CTX,T,D,S,Z,A) \
1520 do { \
1521 cmsUInt32Number inva = 0xFFFFU / (A); \
1522 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1523 (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1524 (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1525 } while (0)
1526 #define PACK(CTX,T,S,D,Z,A) \
1527 do { \
1528 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1529 *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \
1530 *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \
1531 } while (0)
1532 #include "extra_xform.h"
1533
1534 #define FUNCTION_NAME CachedXFORM3x2to3x2_P2
1535 #define CACHED
1536 #define INPACKEDSAMPLESIZE 2
1537 #define OUTPACKEDSAMPLESIZE 2
1538 #define NUMINCHANNELS 3
1539 #define NUMOUTCHANNELS 3
1540 #define NUMEXTRAS 1
1541 #define PREALPHA
1542 #define UNPACKINCLUDESPREALPHA
1543 #define PACKINCLUDESPREALPHA
1544 #define UNPACK(CTX,T,D,S,Z,A) \
1545 do { \
1546 cmsUInt32Number inva = 0xffff0000U / (A); \
1547 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1548 (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1549 (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1550 } while (0)
1551 #define PACK(CTX,T,S,D,Z,A) \
1552 do { \
1553 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1554 *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \
1555 *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \
1556 } while (0)
1557 #include "extra_xform.h"
1558
1559 #define FUNCTION_NAME CachedXFORM3to4_P1
1560 #define CACHED
1561 #define INPACKEDSAMPLESIZE 1
1562 #define OUTPACKEDSAMPLESIZE 1
1563 #define NUMINCHANNELS 3
1564 #define NUMOUTCHANNELS 4
1565 #define NUMEXTRAS 1
1566 #define PREALPHA
1567 #define UNPACKINCLUDESPREALPHA
1568 #define PACKINCLUDESPREALPHA
1569 #define UNPACK(CTX,T,D,S,Z,A) \
1570 do { \
1571 cmsUInt32Number inva = 0xFFFFU / (A); \
1572 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1573 (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1574 (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1575 } while (0)
1576 #define PACK(CTX,T,S,D,Z,A) \
1577 do { \
1578 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1579 *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \
1580 *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \
1581 *(D)++ = mul255(FROM_16_TO_8((S)[3]),(A)); \
1582 } while (0)
1583 #include "extra_xform.h"
1584
1585 #define FUNCTION_NAME CachedXFORM3x2to4x2_P2
1586 #define CACHED
1587 #define INPACKEDSAMPLESIZE 2
1588 #define OUTPACKEDSAMPLESIZE 2
1589 #define NUMINCHANNELS 3
1590 #define NUMOUTCHANNELS 4
1591 #define NUMEXTRAS 1
1592 #define PREALPHA
1593 #define UNPACKINCLUDESPREALPHA
1594 #define PACKINCLUDESPREALPHA
1595 #define UNPACK(CTX,T,D,S,Z,A) \
1596 do { \
1597 cmsUInt32Number inva = 0xffff0000U / (A); \
1598 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1599 (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1600 (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1601 } while (0)
1602 #define PACK(CTX,T,S,D,Z,A) \
1603 do { \
1604 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1605 *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \
1606 *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \
1607 *(cmsUInt16Number *)(D) = mul65535((S)[3],A); (D) += 2; \
1608 } while (0)
1609 #include "extra_xform.h"
1610
1611 #define FUNCTION_NAME CachedXFORM4to1_P1
1612 #define CACHED
1613 #define INPACKEDSAMPLESIZE 1
1614 #define OUTPACKEDSAMPLESIZE 1
1615 #define NUMINCHANNELS 4
1616 #define NUMOUTCHANNELS 1
1617 #define NUMEXTRAS 1
1618 #define PREALPHA
1619 #define UNPACKINCLUDESPREALPHA
1620 #define PACKINCLUDESPREALPHA
1621 #define UNPACK(CTX,T,D,S,Z,A) \
1622 do { \
1623 cmsUInt32Number inva = 0xFFFFU / (A); \
1624 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1625 (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1626 (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1627 (D)[3] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1628 } while (0)
1629 #define PACK(CTX,T,S,D,Z,A) \
1630 do { \
1631 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1632 } while (0)
1633 #include "extra_xform.h"
1634
1635 #define FUNCTION_NAME CachedXFORM4x2to1x2_P2
1636 #define CACHED
1637 #define INPACKEDSAMPLESIZE 2
1638 #define OUTPACKEDSAMPLESIZE 2
1639 #define NUMINCHANNELS 4
1640 #define NUMOUTCHANNELS 1
1641 #define NUMEXTRAS 1
1642 #define PREALPHA
1643 #define UNPACKINCLUDESPREALPHA
1644 #define PACKINCLUDESPREALPHA
1645 #define UNPACK(CTX,T,D,S,Z,A) \
1646 do { \
1647 cmsUInt32Number inva = 0xffff0000U / (A); \
1648 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1649 (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1650 (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1651 (D)[3] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1652 } while (0)
1653 #define PACK(CTX,T,S,D,Z,A) \
1654 do { \
1655 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1656 } while (0)
1657 #include "extra_xform.h"
1658
1659 #define FUNCTION_NAME CachedXFORM4to3_P1
1660 #define CACHED
1661 #define INPACKEDSAMPLESIZE 1
1662 #define OUTPACKEDSAMPLESIZE 1
1663 #define NUMINCHANNELS 4
1664 #define NUMOUTCHANNELS 3
1665 #define NUMEXTRAS 1
1666 #define PREALPHA
1667 #define UNPACKINCLUDESPREALPHA
1668 #define PACKINCLUDESPREALPHA
1669 #define UNPACK(CTX,T,D,S,Z,A) \
1670 do { \
1671 cmsUInt32Number inva = 0xFFFFU / (A); \
1672 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1673 (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1674 (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1675 (D)[3] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1676 } while (0)
1677 #define PACK(CTX,T,S,D,Z,A) \
1678 do { \
1679 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1680 *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \
1681 *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \
1682 } while (0)
1683 #include "extra_xform.h"
1684
1685 #define FUNCTION_NAME CachedXFORM4x2to3x2_P2
1686 #define CACHED
1687 #define INPACKEDSAMPLESIZE 2
1688 #define OUTPACKEDSAMPLESIZE 2
1689 #define NUMINCHANNELS 4
1690 #define NUMOUTCHANNELS 3
1691 #define NUMEXTRAS 1
1692 #define PREALPHA
1693 #define UNPACKINCLUDESPREALPHA
1694 #define PACKINCLUDESPREALPHA
1695 #define UNPACK(CTX,T,D,S,Z,A) \
1696 do { \
1697 cmsUInt32Number inva = 0xffff0000U / (A); \
1698 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1699 (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1700 (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1701 (D)[3] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1702 } while (0)
1703 #define PACK(CTX,T,S,D,Z,A) \
1704 do { \
1705 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1706 *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \
1707 *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \
1708 } while (0)
1709 #include "extra_xform.h"
1710
1711 #define FUNCTION_NAME CachedXFORM4to4_P1
1712 #define CACHED
1713 #define INPACKEDSAMPLESIZE 1
1714 #define OUTPACKEDSAMPLESIZE 1
1715 #define NUMINCHANNELS 4
1716 #define NUMOUTCHANNELS 4
1717 #define NUMEXTRAS 1
1718 #define PREALPHA
1719 #define UNPACKINCLUDESPREALPHA
1720 #define PACKINCLUDESPREALPHA
1721 #define UNPACK(CTX,T,D,S,Z,A) \
1722 do { \
1723 cmsUInt32Number inva = 0xFFFFU / (A); \
1724 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1725 (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1726 (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1727 (D)[3] = (cmsUInt16Number)(*(S) * inva); (S)++; \
1728 } while (0)
1729 #define PACK(CTX,T,S,D,Z,A) \
1730 do { \
1731 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \
1732 *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \
1733 *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \
1734 *(D)++ = mul255(FROM_16_TO_8((S)[3]),(A)); \
1735 } while (0)
1736 #include "extra_xform.h"
1737
1738 #define FUNCTION_NAME CachedXFORM4x2to4x2_P2
1739 #define CACHED
1740 #define INPACKEDSAMPLESIZE 2
1741 #define OUTPACKEDSAMPLESIZE 2
1742 #define NUMINCHANNELS 4
1743 #define NUMOUTCHANNELS 4
1744 #define NUMEXTRAS 1
1745 #define PREALPHA
1746 #define UNPACKINCLUDESPREALPHA
1747 #define PACKINCLUDESPREALPHA
1748 #define UNPACK(CTX,T,D,S,Z,A) \
1749 do { \
1750 cmsUInt32Number inva = 0xffff0000U / (A); \
1751 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1752 (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1753 (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1754 (D)[3] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \
1755 } while (0)
1756 #define PACK(CTX,T,S,D,Z,A) \
1757 do { \
1758 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \
1759 *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \
1760 *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \
1761 *(cmsUInt16Number *)(D) = mul65535((S)[3],A); (D) += 2; \
1762 } while (0)
1763 #include "extra_xform.h"
1764
1765
1766 // Transform plug-ins ----------------------------------------------------------------------------------------------------
1767
1768 // List of used-defined transform factories
1769 typedef struct _cmsTransformCollection_st {
1770
1771 _cmsTransform2Factory Factory;
1772 cmsBool OldXform; // Factory returns xform function in the old style
1773
1774 struct _cmsTransformCollection_st *Next;
1775
1776 } _cmsTransformCollection;
1777
1778 // The linked list head
1779 _cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL };
1780
1781
1782 // Duplicates the zone of memory used by the plug-in in the new context
1783 static
1784 void DupPluginTransformList(struct _cmsContext_struct* ctx,
1785 const struct _cmsContext_struct* src)
1786 {
1787 _cmsTransformPluginChunkType newHead = { NULL };
1788 _cmsTransformCollection* entry;
1789 _cmsTransformCollection* Anterior = NULL;
1790 _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin];
1791
1792 // Walk the list copying all nodes
1793 for (entry = head->TransformCollection;
1794 entry != NULL;
1795 entry = entry ->Next) {
1796
1797 _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection));
1798
1799 if (newEntry == NULL)
1800 return;
1801
1802 // We want to keep the linked list order, so this is a little bit tricky
1803 newEntry -> Next = NULL;
1804 if (Anterior)
1805 Anterior -> Next = newEntry;
1806
1807 Anterior = newEntry;
1808
1809 if (newHead.TransformCollection == NULL)
1810 newHead.TransformCollection = newEntry;
1811 }
1812
1813 ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType));
1814 }
1815
1816 // Allocates memory for transform plugin factory
1817 void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx,
1818 const struct _cmsContext_struct* src)
1819 {
1820 if (src != NULL) {
1821
1822 // Copy all linked list
1823 DupPluginTransformList(ctx, src);
1824 }
1825 else {
1826 static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL };
1827 ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType));
1828 }
1829 }
1830
1831 // Adaptor for old versions of plug-in
1832 static
1833 void _cmsTransform2toTransformAdaptor(cmsContext ContextID, struct _cmstransform_struct *CMMcargo,
1834 const void* InputBuffer,
1835 void* OutputBuffer,
1836 cmsUInt32Number PixelsPerLine,
1837 cmsUInt32Number LineCount,
1838 const cmsStride* Stride)
1839 {
1840
1841 cmsUInt32Number i, strideIn, strideOut;
1842
1843 _cmsHandleExtraChannels(ContextID, CMMcargo, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, Stride);
1844
1845 strideIn = 0;
1846 strideOut = 0;
1847
1848 for (i = 0; i < LineCount; i++) {
1849
1850 void *accum = (cmsUInt8Number*)InputBuffer + strideIn;
1851 void *output = (cmsUInt8Number*)OutputBuffer + strideOut;
1852
1853 CMMcargo->OldXform(ContextID, CMMcargo, accum, output, PixelsPerLine, Stride->BytesPerPlaneIn);
1854
1855 strideIn += Stride->BytesPerLineIn;
1856 strideOut += Stride->BytesPerLineOut;
1857 }
1858 }
1859
1860
1861
1862 // Register new ways to transform
1863 cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data)
1864 {
1865 cmsPluginTransform* Plugin = (cmsPluginTransform*) Data;
1866 _cmsTransformCollection* fl;
1867 _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin);
1868
1869 if (Data == NULL) {
1870
1871 // Free the chain. Memory is safely freed at exit
1872 ctx->TransformCollection = NULL;
1873 return TRUE;
1874 }
1875
1876 // Factory callback is required
1877 if (Plugin->factories.xform == NULL) return FALSE;
1878
1879
1880 fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection));
1881 if (fl == NULL) return FALSE;
1882
1883 // Check for full xform plug-ins previous to 2.8, we would need an adapter in that case
1884 if (Plugin->base.ExpectedVersion < 2080) {
1885
1886 fl->OldXform = TRUE;
1887 }
1888 else
1889 fl->OldXform = FALSE;
1890
1891 // Copy the parameters
1892 fl->Factory = Plugin->factories.xform;
1893
1894 // Keep linked list
1895 fl ->Next = ctx->TransformCollection;
1896 ctx->TransformCollection = fl;
1897
1898 // All is ok
1899 return TRUE;
1900 }
1901
1902
1903 void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn)
1904 {
1905 _cmsAssert(CMMcargo != NULL && CMMcargo->core != NULL);
1906 CMMcargo->core->UserData = ptr;
1907 CMMcargo->core->FreeUserData = FreePrivateDataFn;
1908 }
1909
1910 // returns the pointer defined by the plug-in to store private data
1911 void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo)
1912 {
1913 _cmsAssert(CMMcargo != NULL && CMMcargo->core != NULL);
1914 return CMMcargo->core->UserData;
1915 }
1916
1917 // returns the current formatters
1918 void CMSEXPORT _cmsGetTransformFormatters16(struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput)
1919 {
1920 _cmsAssert(CMMcargo != NULL);
1921 if (FromInput) *FromInput = CMMcargo ->FromInput;
1922 if (ToOutput) *ToOutput = CMMcargo ->ToOutput;
1923 }
1924
1925 void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput)
1926 {
1927 _cmsAssert(CMMcargo != NULL);
1928 if (FromInput) *FromInput = CMMcargo ->FromInputFloat;
1929 if (ToOutput) *ToOutput = CMMcargo ->ToOutputFloat;
1930 }
1931
1932 // returns original flags
1933 cmsUInt32Number CMSEXPORT _cmsGetTransformFlags(struct _cmstransform_struct* CMMcargo)
1934 {
1935 _cmsAssert(CMMcargo != NULL);
1936 return CMMcargo->core->dwOriginalFlags;
1937 }
1938
1939 void
1940 _cmsFindFormatter(_cmsTRANSFORM* p, cmsUInt32Number InputFormat, cmsUInt32Number OutputFormat, cmsUInt32Number dwFlags)
1941 {
1942 if (dwFlags & cmsFLAGS_NULLTRANSFORM) {
1943 p ->xform = NullXFORM;
1944 return;
1945 }
1946 if (dwFlags & cmsFLAGS_PREMULT) {
1947 if (dwFlags & cmsFLAGS_NOCACHE) {
1948 if (dwFlags & cmsFLAGS_GAMUTCHECK)
1949 p ->xform = PrecalculatedXFORMGamutCheck_P; // Gamut check, no cache
1950 else if ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) &&
1951 _cmsLutIsIdentity(p->core->Lut)) {
1952 if (T_PLANAR(InputFormat))
1953 p ->xform = PrecalculatedXFORMIdentityPlanar;
1954 else
1955 p ->xform = PrecalculatedXFORMIdentity;
1956 } else
1957 p ->xform = PrecalculatedXFORM_P; // No cache, no gamut check
1958 return;
1959 }
1960 if (dwFlags & cmsFLAGS_GAMUTCHECK) {
1961 p ->xform = CachedXFORMGamutCheck_P; // Gamut check, cache
1962 return;
1963 }
1964 if ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) &&
1965 _cmsLutIsIdentity(p->core->Lut)) {
1966 /* No point in a cache here! */
1967 if (T_PLANAR(InputFormat))
1968 p ->xform = PrecalculatedXFORMIdentityPlanar;
1969 else
1970 p ->xform = PrecalculatedXFORMIdentity;
1971 return;
1972 }
1973 }
1974 if (dwFlags & cmsFLAGS_NOCACHE) {
1975 if (dwFlags & cmsFLAGS_GAMUTCHECK)
1976 p ->xform = PrecalculatedXFORMGamutCheck; // Gamut check, no cache
1977 else if ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) &&
1978 _cmsLutIsIdentity(p->core->Lut)) {
1979 if (T_PLANAR(InputFormat))
1980 p ->xform = PrecalculatedXFORMIdentityPlanar;
1981 else
1982 p ->xform = PrecalculatedXFORMIdentity;
1983 } else
1984 p ->xform = PrecalculatedXFORM; // No cache, no gamut check
1985 return;
1986 }
1987 if (dwFlags & cmsFLAGS_GAMUTCHECK) {
1988 p ->xform = CachedXFORMGamutCheck; // Gamut check, cache
1989 return;
1990 }
1991 if ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) &&
1992 _cmsLutIsIdentity(p->core->Lut)) {
1993 /* No point in a cache here! */
1994 if (T_PLANAR(InputFormat))
1995 p ->xform = PrecalculatedXFORMIdentityPlanar;
1996 else
1997 p ->xform = PrecalculatedXFORMIdentity;
1998 return;
1999 }
2000 if (T_EXTRA(InputFormat) == 1 && T_EXTRA(OutputFormat) == 1) {
2001 if (dwFlags & cmsFLAGS_PREMULT) {
2002 if ((InputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0 &&
2003 (OutputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0) {
2004 switch ((InputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))|
2005 ((OutputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))<<6)) {
2006 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2007 p->xform = CachedXFORM1to1_P1;
2008 return;
2009 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2010 p->xform = CachedXFORM1x2to1x2_P2;
2011 return;
2012 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2013 p->xform = CachedXFORM1to3_P1;
2014 return;
2015 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2016 p->xform = CachedXFORM1x2to3x2_P2;
2017 return;
2018 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2019 p->xform = CachedXFORM1to4_P1;
2020 return;
2021 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2022 p->xform = CachedXFORM1x2to4x2_P2;
2023 return;
2024 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2025 p ->xform = CachedXFORM3to1_P1;
2026 return;
2027 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2028 p ->xform = CachedXFORM3x2to1x2_P2;
2029 return;
2030 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2031 p->xform = CachedXFORM3to3_P1;
2032 return;
2033 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2034 p->xform = CachedXFORM3x2to3x2_P2;
2035 return;
2036 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2037 p->xform = CachedXFORM3to4_P1;
2038 return;
2039 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2040 p->xform = CachedXFORM3x2to4x2_P2;
2041 return;
2042 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2043 p->xform = CachedXFORM4to1_P1;
2044 return;
2045 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2046 p->xform = CachedXFORM4x2to1x2_P2;
2047 return;
2048 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2049 p->xform = CachedXFORM4to3_P1;
2050 return;
2051 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2052 p->xform = CachedXFORM4x2to3x2_P2;
2053 return;
2054 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2055 p->xform = CachedXFORM4to4_P1;
2056 return;
2057 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2058 p->xform = CachedXFORM4x2to4x2_P2;
2059 return;
2060 }
2061 }
2062 } else {
2063 if ((InputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0 &&
2064 (OutputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0) {
2065 switch ((InputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))|
2066 ((OutputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))<<6)) {
2067 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2068 p->xform = CachedXFORM1to1_1;
2069 return;
2070 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2071 p->xform = CachedXFORM1x2to1x2_2;
2072 return;
2073 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2074 p->xform = CachedXFORM1to3_1;
2075 return;
2076 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2077 p->xform = CachedXFORM1x2to3x2_2;
2078 return;
2079 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2080 p->xform = CachedXFORM1to4_1;
2081 return;
2082 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2083 p->xform = CachedXFORM1x2to4x2_2;
2084 return;
2085 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2086 p ->xform = CachedXFORM3to1_1;
2087 return;
2088 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2089 p ->xform = CachedXFORM3x2to1x2_2;
2090 return;
2091 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2092 p->xform = CachedXFORM3to3_1;
2093 return;
2094 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2095 p->xform = CachedXFORM3x2to3x2_2;
2096 return;
2097 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2098 p->xform = CachedXFORM3to4_1;
2099 return;
2100 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2101 p->xform = CachedXFORM3x2to4x2_2;
2102 return;
2103 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2104 p->xform = CachedXFORM4to1_1;
2105 return;
2106 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2107 p->xform = CachedXFORM4x2to1x2_2;
2108 return;
2109 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2110 p->xform = CachedXFORM4to3_1;
2111 return;
2112 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2113 p->xform = CachedXFORM4x2to3x2_2;
2114 return;
2115 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2116 p->xform = CachedXFORM4to4_1;
2117 return;
2118 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2119 p->xform = CachedXFORM4x2to4x2_2;
2120 return;
2121 }
2122 }
2123 }
2124 }
2125 if (T_EXTRA(InputFormat) != 0) {
2126 if (dwFlags & cmsFLAGS_PREMULT) {
2127 if (T_BYTES(InputFormat) == 1)
2128 p ->xform = CachedXFORM_P1;// No gamut check, cache
2129 else
2130 p ->xform = CachedXFORM_P2;// No gamut check, cache
2131 } else {
2132 p ->xform = CachedXFORM; // No gamut check, cache
2133 }
2134 return;
2135 }
2136 if ((InputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3))) == 0 &&
2137 (OutputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3))) == 0) {
2138 switch ((InputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))|
2139 ((OutputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))<<6)) {
2140 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2141 p->xform = CachedXFORM1to1;
2142 return;
2143 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2144 p->xform = CachedXFORM1x2to1x2;
2145 return;
2146 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2147 p->xform = CachedXFORM1to3;
2148 return;
2149 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2150 p->xform = CachedXFORM1x2to3x2;
2151 return;
2152 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2153 p->xform = CachedXFORM1to4;
2154 return;
2155 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2156 p->xform = CachedXFORM1x2to4x2;
2157 return;
2158 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2159 p ->xform = CachedXFORM3to1;
2160 return;
2161 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2162 p ->xform = CachedXFORM3x2to1x2;
2163 return;
2164 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2165 p->xform = CachedXFORM3to3;
2166 return;
2167 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2168 p->xform = CachedXFORM3x2to3x2;
2169 return;
2170 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2171 p->xform = CachedXFORM3to4;
2172 return;
2173 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2174 p->xform = CachedXFORM3x2to4x2;
2175 return;
2176 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6):
2177 p->xform = CachedXFORM4to1;
2178 return;
2179 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6):
2180 p->xform = CachedXFORM4x2to1x2;
2181 return;
2182 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6):
2183 p->xform = CachedXFORM4to3;
2184 return;
2185 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6):
2186 p->xform = CachedXFORM4x2to3x2;
2187 return;
2188 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6):
2189 p->xform = CachedXFORM4to4;
2190 return;
2191 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6):
2192 p->xform = CachedXFORM4x2to4x2;
2193 return;
2194 }
2195 }
2196 {
2197 int inwords = T_CHANNELS(InputFormat);
2198 if (inwords <= 2)
2199 p ->xform = CachedXFORM4;
2200 else if (inwords <= 4)
2201 p ->xform = CachedXFORM8;
2202 else
2203 p ->xform = CachedXFORM; // No gamut check, cache
2204 }
2205 }
2206
2207 // Returns the worker callback for parallelization plug-ins
2208 _cmsTransform2Fn CMSEXPORT _cmsGetTransformWorker(struct _cmstransform_struct* CMMcargo)
2209 {
2210 _cmsAssert(CMMcargo != NULL);
2211 return CMMcargo->Worker;
2212 }
2213
2214 // This field holds maximum number of workers or -1 to auto
2215 cmsInt32Number CMSEXPORT _cmsGetTransformMaxWorkers(struct _cmstransform_struct* CMMcargo)
2216 {
2217 _cmsAssert(CMMcargo != NULL);
2218 return CMMcargo->MaxWorkers;
2219 }
2220
2221 // This field is actually unused and reserved
2222 cmsUInt32Number CMSEXPORT _cmsGetTransformWorkerFlags(struct _cmstransform_struct* CMMcargo)
2223 {
2224 _cmsAssert(CMMcargo != NULL);
2225 return CMMcargo->WorkerFlags;
2226 }
2227
2228 // In the case there is a parallelization plug-in, let it to do its job
2229 static
2230 void ParalellizeIfSuitable(cmsContext ContextID, _cmsTRANSFORM* p)
2231 {
2232 _cmsParallelizationPluginChunkType* ctx = (_cmsParallelizationPluginChunkType*)_cmsContextGetClientChunk(ContextID, ParallelizationPlugin);
2233
2234 _cmsAssert(p != NULL);
2235 if (ctx != NULL && ctx->SchedulerFn != NULL) {
2236
2237 p->Worker = p->xform;
2238 p->xform = ctx->SchedulerFn;
2239 p->MaxWorkers = ctx->MaxWorkers;
2240 p->WorkerFlags = ctx->WorkerFlags;
2241 }
2242 }
2243
2244
2245 /**
2246 * An empty unroll to avoid a check with NULL on cmsDoTransform()
2247 */
2248 static
2249 cmsUInt8Number* UnrollNothing(cmsContext ContextID,
2250 CMSREGISTER _cmsTRANSFORM* info,
2251 CMSREGISTER cmsUInt16Number wIn[],
2252 CMSREGISTER cmsUInt8Number* accum,
2253 CMSREGISTER cmsUInt32Number Stride)
2254 {
2255 return accum;
2256
2257 cmsUNUSED_PARAMETER(ContextID);
2258 cmsUNUSED_PARAMETER(info);
2259 cmsUNUSED_PARAMETER(wIn);
2260 cmsUNUSED_PARAMETER(Stride);
2261 }
2262
2263 static
2264 cmsUInt8Number* PackNothing(cmsContext ContextID,
2265 CMSREGISTER _cmsTRANSFORM* info,
2266 CMSREGISTER cmsUInt16Number wOut[],
2267 CMSREGISTER cmsUInt8Number* output,
2268 CMSREGISTER cmsUInt32Number Stride)
2269 {
2270 return output;
2271
2272 cmsUNUSED_PARAMETER(ContextID);
2273 cmsUNUSED_PARAMETER(info);
2274 cmsUNUSED_PARAMETER(wOut);
2275 cmsUNUSED_PARAMETER(Stride);
2276 }
2277
2278 // Allocate transform struct and set it to defaults. Ask the optimization plug-in about if those formats are proper
2279 // for separated transforms. If this is the case,
2280 static
2281 _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
2282 cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
2283 {
2284 _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin);
2285 _cmsTransformCollection* Plugin;
2286 _cmsTRANSFORMCORE *core;
2287
2288 // Allocate needed memory
2289 _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
2290 if (!p) {
2291 cmsPipelineFree(ContextID, lut);
2292 return NULL;
2293 }
2294
2295 core = (_cmsTRANSFORMCORE*)_cmsMallocZero(ContextID, sizeof(*core));
2296 if (!core) {
2297 _cmsFree(ContextID, p);
2298 cmsPipelineFree(ContextID, lut);
2299 return NULL;
2300 }
2301
2302 p->core = core;
2303 core->refs = 1;
2304 // Store the proposed pipeline
2305 p->core->Lut = lut;
2306
2307 // Let's see if any plug-in want to do the transform by itself
2308 if (core->Lut != NULL) {
2309 if (!(*dwFlags & cmsFLAGS_NOOPTIMIZE)) {
2310
2311 for (Plugin = ctx->TransformCollection;
2312 Plugin != NULL;
2313 Plugin = Plugin->Next) {
2314
2315 if (Plugin->Factory(ContextID, &p->xform, &core->UserData, &core->FreeUserData, &core->Lut, InputFormat, OutputFormat, dwFlags)) {
2316
2317 // Last plugin in the declaration order takes control. We just keep
2318 // the original parameters as a logging.
2319 // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default
2320 // an optimized transform is not reusable. The plug-in can, however, change
2321 // the flags and make it suitable.
2322
2323 p->InputFormat = *InputFormat;
2324 p->OutputFormat = *OutputFormat;
2325 core->dwOriginalFlags = *dwFlags;
2326
2327 // Fill the formatters just in case the optimized routine is interested.
2328 // No error is thrown if the formatter doesn't exist. It is up to the optimization
2329 // factory to decide what to do in those cases.
2330 p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
2331 p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
2332 p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
2333 p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
2334
2335 // Save the day? (Ignore the warning)
2336 if (Plugin->OldXform) {
2337 p->OldXform = (_cmsTransformFn)(void*) p->xform;
2338 p->xform = _cmsTransform2toTransformAdaptor;
2339 }
2340
2341 ParalellizeIfSuitable(ContextID, p);
2342 return p;
2343 }
2344 }
2345 }
2346
2347 // Not suitable for the transform plug-in, let's check the pipeline plug-in
2348 _cmsOptimizePipeline(ContextID, &core->Lut, Intent, InputFormat, OutputFormat, dwFlags);
2349 }
2350
2351 // Check whatever this is a true floating point transform
2352 if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) {
2353
2354 // Get formatter function always return a valid union, but the contents of this union may be NULL.
2355 p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
2356 p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
2357 *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
2358
2359 if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
2360
2361 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
2362 cmsDeleteTransform(ContextID, p);
2363 return NULL;
2364 }
2365
2366 if (*dwFlags & cmsFLAGS_NULLTRANSFORM) {
2367
2368 p ->xform = NullFloatXFORM;
2369 }
2370 else {
2371 // Float transforms don't use cache, always are non-NULL
2372 p ->xform = FloatXFORM;
2373 }
2374
2375 }
2376 else {
2377
2378 // Formats are intended to be changed before use
2379 if (*InputFormat == 0 && *OutputFormat == 0) {
2380 p->FromInput = UnrollNothing;
2381 p->ToOutput = PackNothing;
2382 *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
2383 }
2384 else {
2385
2386 cmsUInt32Number BytesPerPixelInput;
2387
2388 p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
2389 p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
2390
2391 if (p ->FromInput == NULL || p ->ToOutput == NULL) {
2392
2393 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
2394 cmsDeleteTransform(ContextID, p);
2395 return NULL;
2396 }
2397
2398 BytesPerPixelInput = T_BYTES(*InputFormat);
2399 if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2)
2400 *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
2401
2402 }
2403
2404 _cmsFindFormatter(p, *InputFormat, *OutputFormat, *dwFlags);
2405 }
2406
2407 /**
2408 * Check consistency for alpha channel copy
2409 */
2410 if (*dwFlags & cmsFLAGS_COPY_ALPHA)
2411 {
2412 if (T_EXTRA(*InputFormat) != T_EXTRA(*OutputFormat))
2413 {
2414 cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Mismatched alpha channels");
2415 cmsDeleteTransform(ContextID, p);
2416 return NULL;
2417 }
2418 }
2419
2420 p ->InputFormat = *InputFormat;
2421 p ->OutputFormat = *OutputFormat;
2422 core->dwOriginalFlags = *dwFlags;
2423 core->UserData = NULL;
2424 ParalellizeIfSuitable(ContextID, p);
2425 return p;
2426 }
2427
2428 static
2429 cmsBool GetXFormColorSpaces(cmsContext ContextID, cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output)
2430 {
2431 cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut;
2432 cmsColorSpaceSignature PostColorSpace;
2433 cmsUInt32Number i;
2434
2435 if (nProfiles == 0) return FALSE;
2436 if (hProfiles[0] == NULL) return FALSE;
2437
2438 *Input = PostColorSpace = cmsGetColorSpace(ContextID, hProfiles[0]);
2439
2440 for (i=0; i < nProfiles; i++) {
2441
2442 cmsProfileClassSignature cls;
2443 cmsHPROFILE hProfile = hProfiles[i];
2444
2445 int lIsInput = (PostColorSpace != cmsSigXYZData) &&
2446 (PostColorSpace != cmsSigLabData);
2447
2448 if (hProfile == NULL) return FALSE;
2449
2450 cls = cmsGetDeviceClass(ContextID, hProfile);
2451
2452 if (cls == cmsSigNamedColorClass) {
2453
2454 ColorSpaceIn = cmsSig1colorData;
2455 ColorSpaceOut = (nProfiles > 1) ? cmsGetPCS(ContextID, hProfile) : cmsGetColorSpace(ContextID, hProfile);
2456 }
2457 else
2458 if (lIsInput || (cls == cmsSigLinkClass)) {
2459
2460 ColorSpaceIn = cmsGetColorSpace(ContextID, hProfile);
2461 ColorSpaceOut = cmsGetPCS(ContextID, hProfile);
2462 }
2463 else
2464 {
2465 ColorSpaceIn = cmsGetPCS(ContextID, hProfile);
2466 ColorSpaceOut = cmsGetColorSpace(ContextID, hProfile);
2467 }
2468
2469 if (i==0)
2470 *Input = ColorSpaceIn;
2471
2472 PostColorSpace = ColorSpaceOut;
2473 }
2474
2475 *Output = PostColorSpace;
2476
2477 return TRUE;
2478 }
2479
2480 // Check colorspace
2481 static
2482 cmsBool IsProperColorSpace(cmsContext ContextID, cmsColorSpaceSignature Check, cmsUInt32Number dwFormat)
2483 {
2484 int Space1 = (int) T_COLORSPACE(dwFormat);
2485 int Space2 = _cmsLCMScolorSpace(ContextID, Check);
2486
2487 if (Space1 == PT_ANY) return TRUE;
2488 if (Space1 == Space2) return TRUE;
2489
2490 if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE;
2491 if (Space1 == PT_Lab && Space2 == PT_LabV2) return TRUE;
2492
2493 return FALSE;
2494 }
2495
2496 // ----------------------------------------------------------------------------------------------------------------
2497
2498 // Jun-21-2000: Some profiles (those that comes with W2K) comes
2499 // with the media white (media black?) x 100. Add a sanity check
2500
2501 static
2502 void NormalizeXYZ(cmsCIEXYZ* Dest)
2503 {
2504 while (Dest -> X > 2. &&
2505 Dest -> Y > 2. &&
2506 Dest -> Z > 2.) {
2507
2508 Dest -> X /= 10.;
2509 Dest -> Y /= 10.;
2510 Dest -> Z /= 10.;
2511 }
2512 }
2513
2514 static
2515 void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src)
2516 {
2517 if (src == NULL) {
2518 wtPt ->X = cmsD50X;
2519 wtPt ->Y = cmsD50Y;
2520 wtPt ->Z = cmsD50Z;
2521 }
2522 else {
2523 wtPt ->X = src->X;
2524 wtPt ->Y = src->Y;
2525 wtPt ->Z = src->Z;
2526
2527 NormalizeXYZ(wtPt);
2528 }
2529
2530 }
2531
2532 // New to lcms 2.0 -- have all parameters available.
2533 cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
2534 cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[],
2535 cmsBool BPC[],
2536 cmsUInt32Number Intents[],
2537 cmsFloat64Number AdaptationStates[],
2538 cmsHPROFILE hGamutProfile,
2539 cmsUInt32Number nGamutPCSposition,
2540 cmsUInt32Number InputFormat,
2541 cmsUInt32Number OutputFormat,
2542 cmsUInt32Number dwFlags)
2543 {
2544 _cmsTRANSFORM* xform;
2545 cmsColorSpaceSignature EntryColorSpace;
2546 cmsColorSpaceSignature ExitColorSpace;
2547 cmsPipeline* Lut;
2548 cmsUInt32Number LastIntent = Intents[nProfiles-1];
2549
2550 // If it is a fake transform
2551 if (dwFlags & cmsFLAGS_NULLTRANSFORM)
2552 {
2553 return AllocEmptyTransform(ContextID, NULL, INTENT_PERCEPTUAL, &InputFormat, &OutputFormat, &dwFlags);
2554 }
2555
2556 // If gamut check is requested, make sure we have a gamut profile
2557 if (dwFlags & cmsFLAGS_GAMUTCHECK) {
2558 if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK;
2559 }
2560
2561 // On floating point transforms, inhibit cache
2562 if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat))
2563 dwFlags |= cmsFLAGS_NOCACHE;
2564
2565 // Mark entry/exit spaces
2566 if (!GetXFormColorSpaces(ContextID, nProfiles, hProfiles, &EntryColorSpace, &ExitColorSpace)) {
2567 cmsSignalError(ContextID, cmsERROR_NULL, "NULL input profiles on transform");
2568 return NULL;
2569 }
2570
2571 // Check if proper colorspaces
2572 if (!IsProperColorSpace(ContextID, EntryColorSpace, InputFormat)) {
2573 cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong input color space on transform");
2574 return NULL;
2575 }
2576
2577 if (!IsProperColorSpace(ContextID, ExitColorSpace, OutputFormat)) {
2578 cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong output color space on transform");
2579 return NULL;
2580 }
2581
2582 // Check whatever the transform is 16 bits and involves linear RGB in first profile. If so, disable optimizations
2583 if (EntryColorSpace == cmsSigRgbData && T_BYTES(InputFormat) == 2 && !(dwFlags & cmsFLAGS_NOOPTIMIZE))
2584 {
2585 cmsFloat64Number gamma = cmsDetectRGBProfileGamma(ContextID, hProfiles[0], 0.1);
2586
2587 if (gamma > 0 && gamma < 1.6)
2588 dwFlags |= cmsFLAGS_NOOPTIMIZE;
2589 }
2590
2591 // Create a pipeline with all transformations
2592 Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags);
2593 if (Lut == NULL) {
2594 cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Couldn't link the profiles");
2595 return NULL;
2596 }
2597
2598 // Check channel count
2599 if ((cmsChannelsOfColorSpace(ContextID, EntryColorSpace) != (cmsInt32Number) cmsPipelineInputChannels(ContextID, Lut)) ||
2600 (cmsChannelsOfColorSpace(ContextID, ExitColorSpace) != (cmsInt32Number) cmsPipelineOutputChannels(ContextID, Lut))) {
2601 cmsPipelineFree(ContextID, Lut);
2602 cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted");
2603 return NULL;
2604 }
2605
2606 // Check premultiplication requirements
2607 if (dwFlags & cmsFLAGS_PREMULT) {
2608 if (T_BYTES(InputFormat) != T_BYTES(OutputFormat)) {
2609 cmsPipelineFree(ContextID, Lut);
2610 cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Premultiplication requires input and output to be in the same format.");
2611 return NULL;
2612 }
2613
2614 if (T_EXTRA(InputFormat) < 1 || T_EXTRA(OutputFormat) < 1 || T_EXTRA(InputFormat) != T_EXTRA(OutputFormat) || (dwFlags & cmsFLAGS_COPY_ALPHA) == 0) {
2615 cmsPipelineFree(ContextID, Lut);
2616 cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Premultiplication must preserve the extra channels");
2617 return NULL;
2618 }
2619 }
2620
2621
2622 // All seems ok
2623 xform = AllocEmptyTransform(ContextID, Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags);
2624 if (xform == NULL) {
2625 return NULL;
2626 }
2627
2628 // Keep values
2629 xform->core->EntryColorSpace = EntryColorSpace;
2630 xform->core->ExitColorSpace = ExitColorSpace;
2631 xform->core->RenderingIntent = Intents[nProfiles-1];
2632
2633 // Take white points
2634 SetWhitePoint(&xform->core->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(ContextID, hProfiles[0], cmsSigMediaWhitePointTag));
2635 SetWhitePoint(&xform->core->ExitWhitePoint, (cmsCIEXYZ*) cmsReadTag(ContextID, hProfiles[nProfiles-1], cmsSigMediaWhitePointTag));
2636
2637
2638 // Create a gamut check LUT if requested
2639 if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK))
2640 xform->core->GamutCheck = _cmsCreateGamutCheckPipeline(ContextID, hProfiles,
2641 BPC, Intents,
2642 AdaptationStates,
2643 nGamutPCSposition,
2644 hGamutProfile);
2645
2646
2647 // Try to read input and output colorant table
2648 if (cmsIsTag(ContextID, hProfiles[0], cmsSigColorantTableTag)) {
2649
2650 // Input table can only come in this way.
2651 xform->core->InputColorant = cmsDupNamedColorList(ContextID, (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hProfiles[0], cmsSigColorantTableTag));
2652 }
2653
2654 // Output is a little bit more complex.
2655 if (cmsGetDeviceClass(ContextID, hProfiles[nProfiles-1]) == cmsSigLinkClass) {
2656
2657 // This tag may exist only on devicelink profiles.
2658 if (cmsIsTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableOutTag)) {
2659
2660 // It may be NULL if error
2661 xform->core->OutputColorant = cmsDupNamedColorList(ContextID, (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableOutTag));
2662 }
2663
2664 } else {
2665
2666 if (cmsIsTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableTag)) {
2667
2668 xform->core->OutputColorant = cmsDupNamedColorList(ContextID, (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableTag));
2669 }
2670 }
2671
2672 // Store the sequence of profiles
2673 if (dwFlags & cmsFLAGS_KEEP_SEQUENCE) {
2674 xform->core->Sequence = _cmsCompileProfileSequence(ContextID, nProfiles, hProfiles);
2675 }
2676 else
2677 xform->core->Sequence = NULL;
2678
2679 // If this is a cached transform, init first value, which is zero (16 bits only)
2680 if (!(dwFlags & cmsFLAGS_NOCACHE)) {
2681
2682 memset(&xform ->Cache.CacheIn, 0, sizeof(xform ->Cache.CacheIn));
2683
2684 if (xform->core->GamutCheck != NULL) {
2685 TransformOnePixelWithGamutCheck(ContextID, xform, xform->Cache.CacheIn, xform->Cache.CacheOut);
2686 }
2687 else {
2688
2689 xform->core->Lut->Eval16Fn(ContextID, xform ->Cache.CacheIn, xform->Cache.CacheOut, xform->core->Lut->Data);
2690 }
2691
2692 }
2693
2694 return (cmsHTRANSFORM) xform;
2695 }
2696
2697 // Multiprofile transforms: Gamut check is not available here, as it is unclear from which profile the gamut comes.
2698 cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransform(cmsContext ContextID,
2699 cmsHPROFILE hProfiles[],
2700 cmsUInt32Number nProfiles,
2701 cmsUInt32Number InputFormat,
2702 cmsUInt32Number OutputFormat,
2703 cmsUInt32Number Intent,
2704 cmsUInt32Number dwFlags)
2705 {
2706 cmsUInt32Number i;
2707 cmsBool BPC[256];
2708 cmsUInt32Number Intents[256];
2709 cmsFloat64Number AdaptationStates[256];
2710
2711 if (nProfiles <= 0 || nProfiles > 255) {
2712 cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles);
2713 return NULL;
2714 }
2715
2716 for (i=0; i < nProfiles; i++) {
2717 BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE;
2718 Intents[i] = Intent;
2719 AdaptationStates[i] = cmsSetAdaptationState(ContextID, -1);
2720 }
2721
2722
2723 return cmsCreateExtendedTransform(ContextID, nProfiles, hProfiles, BPC, Intents, AdaptationStates, NULL, 0, InputFormat, OutputFormat, dwFlags);
2724 }
2725
2726
2727
2728 cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsContext ContextID,
2729 cmsHPROFILE Input,
2730 cmsUInt32Number InputFormat,
2731 cmsHPROFILE Output,
2732 cmsUInt32Number OutputFormat,
2733 cmsUInt32Number Intent,
2734 cmsUInt32Number dwFlags)
2735 {
2736
2737 cmsHPROFILE hArray[2];
2738
2739 hArray[0] = Input;
2740 hArray[1] = Output;
2741
2742 return cmsCreateMultiprofileTransform(ContextID, hArray, Output == NULL ? 1U : 2U, InputFormat, OutputFormat, Intent, dwFlags);
2743 }
2744
2745
2746 cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransform(cmsContext ContextID,
2747 cmsHPROFILE InputProfile,
2748 cmsUInt32Number InputFormat,
2749 cmsHPROFILE OutputProfile,
2750 cmsUInt32Number OutputFormat,
2751 cmsHPROFILE ProofingProfile,
2752 cmsUInt32Number nIntent,
2753 cmsUInt32Number ProofingIntent,
2754 cmsUInt32Number dwFlags)
2755 {
2756 cmsHPROFILE hArray[4];
2757 cmsUInt32Number Intents[4];
2758 cmsBool BPC[4];
2759 cmsFloat64Number Adaptation[4];
2760 cmsBool DoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION) ? TRUE : FALSE;
2761
2762
2763 hArray[0] = InputProfile; hArray[1] = ProofingProfile; hArray[2] = ProofingProfile; hArray[3] = OutputProfile;
2764 Intents[0] = nIntent; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = ProofingIntent;
2765 BPC[0] = DoBPC; BPC[1] = DoBPC; BPC[2] = 0; BPC[3] = 0;
2766
2767 Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationState(ContextID, -1);
2768
2769 if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK)))
2770 return cmsCreateTransform(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags);
2771
2772 return cmsCreateExtendedTransform(ContextID, 4, hArray, BPC, Intents, Adaptation,
2773 ProofingProfile, 1, InputFormat, OutputFormat, dwFlags);
2774
2775 }
2776
2777
2778
2779 // Grab the input/output formats
2780 cmsUInt32Number CMSEXPORT cmsGetTransformInputFormat(cmsContext ContextID, cmsHTRANSFORM hTransform)
2781 {
2782 _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
2783 cmsUNUSED_PARAMETER(ContextID);
2784
2785 if (xform == NULL) return 0;
2786 return xform->InputFormat;
2787 }
2788
2789 cmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsContext ContextID, cmsHTRANSFORM hTransform)
2790 {
2791 _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
2792 cmsUNUSED_PARAMETER(ContextID);
2793
2794 if (xform == NULL) return 0;
2795 return xform->OutputFormat;
2796 }
2797
2798 cmsHTRANSFORM cmsCloneTransformChangingFormats(cmsContext ContextID,
2799 const cmsHTRANSFORM hTransform,
2800 cmsUInt32Number InputFormat,
2801 cmsUInt32Number OutputFormat)
2802 {
2803 const _cmsTRANSFORM *oldXform = (const _cmsTRANSFORM *)hTransform;
2804 _cmsTRANSFORM *xform;
2805 cmsFormatter16 FromInput, ToOutput;
2806
2807 _cmsAssert(oldXform != NULL && oldXform->core != NULL);
2808
2809 // We only can afford to change formatters if previous transform is at least 16 bits
2810 if (!(oldXform->core->dwOriginalFlags & cmsFLAGS_CAN_CHANGE_FORMATTER)) {
2811 cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "cmsCloneTransformChangingFormats works only on transforms created originally with at least 16 bits of precision");
2812 return NULL;
2813 }
2814
2815 xform = _cmsMalloc(ContextID, sizeof(*xform));
2816 if (xform == NULL)
2817 return NULL;
2818
2819 memcpy(xform, oldXform, sizeof(*xform));
2820
2821 FromInput = _cmsGetFormatter(ContextID, InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
2822 ToOutput = _cmsGetFormatter(ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
2823
2824 if (FromInput == NULL || ToOutput == NULL) {
2825
2826 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
2827 return NULL;
2828 }
2829
2830 xform ->InputFormat = InputFormat;
2831 xform ->OutputFormat = OutputFormat;
2832 xform ->FromInput = FromInput;
2833 xform ->ToOutput = ToOutput;
2834 _cmsFindFormatter(xform, InputFormat, OutputFormat, xform->core->dwOriginalFlags);
2835
2836 (void)_cmsAdjustReferenceCount(&xform->core->refs, 1);
2837
2838 return xform;
2839 }