Mercurial > hgrepos > Python2 > PyMuPDF
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/lcms2/src/cmsxform.c Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,2839 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2023 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// Transformations stuff +// ----------------------------------------------------------------------- + +#define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0 + +// The Context0 observer adaptation state. +_cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; + +// Init and duplicate observer adaptation state +void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; + void* from; + + if (src != NULL) { + from = src ->chunks[AdaptationStateContext]; + } + else { + from = &AdaptationStateChunk; + } + + ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType)); +} + + +// Sets adaptation state for absolute colorimetric intent in the given context. Adaptation state applies on all +// but cmsCreateExtendedTransform(). Little CMS can handle incomplete adaptation states. +// The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine +cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsContext ContextID, cmsFloat64Number d) +{ + cmsFloat64Number prev; + _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext); + + // Get previous value for return + prev = ptr ->AdaptationState; + + // Set the value if d is positive or zero + if (d >= 0.0) { + + ptr ->AdaptationState = d; + } + + // Always return previous value + return prev; +} + + +// ----------------------------------------------------------------------- + +// Alarm codes for 16-bit transformations, because the fixed range of containers there are +// no values left to mark out of gamut. + +#define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +_cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; + +// Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be +// encoded in 16 bits. +void CMSEXPORT cmsSetAlarmCodes(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) +{ + _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); + + _cmsAssert(ContextAlarmCodes != NULL); // Can't happen + + memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes)); +} + +// Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context. +// Values are meant to be encoded in 16 bits. +void CMSEXPORT cmsGetAlarmCodes(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) +{ + _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); + + _cmsAssert(ContextAlarmCodes != NULL); // Can't happen + + memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes)); +} + + +// Init and duplicate alarm codes +void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; + void* from; + + if (src != NULL) { + from = src ->chunks[AlarmCodesContext]; + } + else { + from = &AlarmCodesChunk; + } + + ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType)); +} + +// ----------------------------------------------------------------------- + +// Get rid of transform resources +void CMSEXPORT cmsDeleteTransform(cmsContext ContextID, cmsHTRANSFORM hTransform) +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) hTransform; + _cmsTRANSFORMCORE *core; + cmsUInt32Number refs; + + if (p == NULL) + return; + + core = p->core; + + _cmsAssert(core != NULL); + + refs = _cmsAdjustReferenceCount(&core->refs, -1); + _cmsFree(ContextID, (void *) p); + + if (refs != 0) + return; + + if (core->GamutCheck) + cmsPipelineFree(ContextID, core->GamutCheck); + + if (core->Lut) + cmsPipelineFree(ContextID, core->Lut); + + if (core->InputColorant) + cmsFreeNamedColorList(ContextID, core->InputColorant); + + if (core->OutputColorant) + cmsFreeNamedColorList(ContextID, core->OutputColorant); + + if (core->Sequence) + cmsFreeProfileSequenceDescription(ContextID, core->Sequence); + + if (core->UserData) + core->FreeUserData(ContextID, core->UserData); + + _cmsFree(ContextID, (void *)core); +} + + +static +cmsUInt32Number PixelSize(cmsUInt32Number Format) +{ + cmsUInt32Number fmt_bytes = T_BYTES(Format); + + // For double, the T_BYTES field is zero + if (fmt_bytes == 0) + return sizeof(cmsUInt64Number); + + // Otherwise, it is already correct for all formats + return fmt_bytes; +} + + + + +// Apply transform. +void CMSEXPORT cmsDoTransform(cmsContext ContextID, cmsHTRANSFORM Transform, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number Size) + +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; + cmsStride stride; + + stride.BytesPerLineIn = 0; // Not used + stride.BytesPerLineOut = 0; + stride.BytesPerPlaneIn = Size * PixelSize(p->InputFormat); + stride.BytesPerPlaneOut = Size * PixelSize(p->OutputFormat); + + p -> xform(ContextID, p, InputBuffer, OutputBuffer, Size, 1, &stride); +} + + +// This is a legacy stride for planar +void CMSEXPORT cmsDoTransformStride(cmsContext ContextID, cmsHTRANSFORM Transform, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number Size, cmsUInt32Number Stride) + +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; + cmsStride stride; + + stride.BytesPerLineIn = 0; + stride.BytesPerLineOut = 0; + stride.BytesPerPlaneIn = Stride; + stride.BytesPerPlaneOut = Stride; + + p -> xform(ContextID, p, InputBuffer, OutputBuffer, Size, 1, &stride); +} + +// This is the "fast" function for plugins +void CMSEXPORT cmsDoTransformLineStride(cmsContext ContextID, cmsHTRANSFORM Transform, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + cmsUInt32Number BytesPerLineIn, + cmsUInt32Number BytesPerLineOut, + cmsUInt32Number BytesPerPlaneIn, + cmsUInt32Number BytesPerPlaneOut) + +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; + cmsStride stride; + + stride.BytesPerLineIn = BytesPerLineIn; + stride.BytesPerLineOut = BytesPerLineOut; + stride.BytesPerPlaneIn = BytesPerPlaneIn; + stride.BytesPerPlaneOut = BytesPerPlaneOut; + + p->xform(ContextID, p, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, &stride); +} + + + +// Transform routines ---------------------------------------------------------------------------------------------------------- + +// Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check. +// Note that because extended range, we can use a -1.0 value for out of gamut in this case. +static +void FloatXFORM(cmsContext ContextID, _cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS]; + cmsFloat32Number OutOfGamut; + cmsUInt32Number i, j, c, strideIn, strideOut; + _cmsTRANSFORMCORE *core = p->core; + + _cmsHandleExtraChannels(ContextID, p, in, out, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + memset(fIn, 0, sizeof(fIn)); + memset(fOut, 0, sizeof(fOut)); + + for (i = 0; i < LineCount; i++) { + + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; + + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInputFloat(ContextID, p, fIn, accum, Stride->BytesPerPlaneIn); + + // Any gamut chack to do? + if (core->GamutCheck != NULL) { + + // Evaluate gamut marker. + cmsPipelineEvalFloat(ContextID, fIn, &OutOfGamut, core->GamutCheck); + + // Is current color out of gamut? + if (OutOfGamut > 0.0) { + + // Certainly, out of gamut + for (c = 0; c < cmsMAXCHANNELS; c++) + fOut[c] = -1.0; + + } + else { + // No, proceed normally + cmsPipelineEvalFloat(ContextID, fIn, fOut, core->Lut); + } + } + else { + + // No gamut check at all + cmsPipelineEvalFloat(ContextID, fIn, fOut, core->Lut); + } + + + output = p->ToOutputFloat(ContextID, p, fOut, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } + +} + + +static +void NullFloatXFORM(cmsContext ContextID, _cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) + +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsFloat32Number fIn[cmsMAXCHANNELS]; + cmsUInt32Number i, j, strideIn, strideOut; + + _cmsHandleExtraChannels(ContextID, p, in, out, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + memset(fIn, 0, sizeof(fIn)); + + for (i = 0; i < LineCount; i++) { + + accum = (cmsUInt8Number*) in + strideIn; + output = (cmsUInt8Number*) out + strideOut; + + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInputFloat(ContextID, p, fIn, accum, Stride ->BytesPerPlaneIn); + output = p->ToOutputFloat(ContextID, p, fIn, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } +} + +static inline int mul255(cmsUInt32Number a, cmsUInt32Number b) +{ + /* see Jim Blinn's book "Dirty Pixels" for how this works */ + cmsUInt32Number x = a * b + 128; + x += x >> 8; + return x >> 8; +} + +static inline cmsUInt32Number mul65535(cmsUInt32Number a, cmsUInt32Number b) +{ + /* see Jim Blinn's book "Dirty Pixels" for how this works */ + cmsUInt32Number x = a * b + 0x8000; + x += x >> 16; + return x >> 16; +} + +// 16 bit precision ----------------------------------------------------------------------------------------------------------- + +// Null transformation, only applies formatters. No cache +static +void NullXFORM(cmsContext ContextID, + _cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsUInt16Number wIn[cmsMAXCHANNELS]; + cmsUInt32Number i, j, strideIn, strideOut; + + _cmsHandleExtraChannels(ContextID, p, in, out, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + memset(wIn, 0, sizeof(wIn)); + + for (i = 0; i < LineCount; i++) { + + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; + + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInput(ContextID, p, wIn, accum, Stride->BytesPerPlaneIn); + output = p->ToOutput(ContextID, p, wIn, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } + +} + + +// No gamut check, no cache, 16 bits +#define FUNCTION_NAME PrecalculatedXFORM +#include "extra_xform.h" + +// No gamut check, no cache, 16 bits +#define PREALPHA +#define FUNCTION_NAME PrecalculatedXFORM_P +#include "extra_xform.h" + +// No gamut check, no cache, Identity transform, including pack/unpack +static +void PrecalculatedXFORMIdentity(cmsContext ContextID, + _cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + cmsUInt32Number bpli = Stride->BytesPerLineIn; + cmsUInt32Number bplo = Stride->BytesPerLineOut; + int bpp; + cmsUNUSED_PARAMETER(ContextID); + + /* Silence some warnings */ + (void)bpli; + (void)bplo; + + if ((in == out && bpli == bplo) || PixelsPerLine == 0) + return; + + bpp = T_BYTES(p->InputFormat); + if (bpp == 0) + bpp = sizeof(double); + bpp *= T_CHANNELS(p->InputFormat) + T_EXTRA(p->InputFormat); + PixelsPerLine *= bpp; /* Convert to BytesPerLine */ + while (LineCount-- > 0) + { + memmove(out, in, PixelsPerLine); + in = (void *)((cmsUInt8Number *)in + bpli); + out = (void *)((cmsUInt8Number *)out + bplo); + } +} + +static +void PrecalculatedXFORMIdentityPlanar(cmsContext ContextID, + _cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + cmsUInt32Number bpli = Stride->BytesPerLineIn; + cmsUInt32Number bplo = Stride->BytesPerLineOut; + cmsUInt32Number bppi = Stride->BytesPerPlaneIn; + cmsUInt32Number bppo = Stride->BytesPerPlaneOut; + int bpp; + int planes; + const void *plane_in; + void *plane_out; + cmsUNUSED_PARAMETER(ContextID); + + /* Silence some warnings */ + (void)bpli; + (void)bplo; + (void)bppi; + (void)bppo; + + if ((in == out && bpli == bplo && bppi == bppo) || PixelsPerLine == 0) + return; + + bpp = T_BYTES(p->InputFormat); + if (bpp == 0) + bpp = sizeof(double); + PixelsPerLine *= bpp; /* Convert to BytesPerLine */ + planes = T_CHANNELS(p->InputFormat) + T_EXTRA(p->InputFormat); + while (planes-- > 0) + { + plane_in = in; + plane_out = out; + while (LineCount-- > 0) + { + memmove(plane_out, plane_in, PixelsPerLine); + plane_in = (void *)((cmsUInt8Number *)plane_in + bpli); + plane_out = (void *)((cmsUInt8Number *)plane_out + bplo); + } + in = (void *)((cmsUInt8Number *)in + bppi); + out = (void *)((cmsUInt8Number *)out + bppo); + } +} + +// Auxiliary: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical. +static +void TransformOnePixelWithGamutCheck(cmsContext ContextID, _cmsTRANSFORM* p, + const cmsUInt16Number wIn[], + cmsUInt16Number wOut[]) +{ + cmsUInt16Number wOutOfGamut; + _cmsTRANSFORMCORE *core = p->core; + + core->GamutCheck->Eval16Fn(ContextID, wIn, &wOutOfGamut, core->GamutCheck->Data); + if (wOutOfGamut >= 1) { + + cmsUInt32Number i; + cmsUInt32Number n = core->Lut->OutputChannels; + _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); + + for (i=0; i < n; i++) { + + wOut[i] = ContextAlarmCodes ->AlarmCodes[i]; + } + } + else + core->Lut->Eval16Fn(ContextID, wIn, wOut, core->Lut->Data); +} + +// Gamut check, No cache, 16 bits. +#define FUNCTION_NAME PrecalculatedXFORMGamutCheck +#define GAMUTCHECK +#include "extra_xform.h" + +// Gamut check, No cache, 16 bits. +#define FUNCTION_NAME PrecalculatedXFORMGamutCheck_P +#define PREALPHA +#define GAMUTCHECK +#include "extra_xform.h" + +// No gamut check, Cache, 16 bits, +#define FUNCTION_NAME CachedXFORM +#define CACHED +#include "extra_xform.h" + +// All those nice features together +#define FUNCTION_NAME CachedXFORMGamutCheck +#define CACHED +#define GAMUTCHECK +#include "extra_xform.h" + +// All those nice features together +#define FUNCTION_NAME CachedXFORMGamutCheck_P +#define CACHED +#define PREALPHA +#define GAMUTCHECK +#include "extra_xform.h" + +// No gamut check, Cache, 16 bits, <= 4 bytes +#define FUNCTION_NAME CachedXFORM4 +#define CACHED +#define CMPBYTES 4 +#define NUMEXTRAS 0 +#include "extra_xform.h" + +// No gamut check, Cache, 16 bits, <= 8 bytes total +#define FUNCTION_NAME CachedXFORM8 +#define CACHED +#define CMPBYTES 8 +#define NUMEXTRAS 0 +#include "extra_xform.h" + +// Special ones for common cases. +#define FUNCTION_NAME CachedXFORM1to1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1x2to1x2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1to3 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ + *(D)++ = FROM_16_TO_8((S)[1]); \ + *(D)++ = FROM_16_TO_8((S)[2]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1x2to3x2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1to4 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ + *(D)++ = FROM_16_TO_8((S)[1]); \ + *(D)++ = FROM_16_TO_8((S)[2]); \ + *(D)++ = FROM_16_TO_8((S)[3]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1x2to4x2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3to1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3x2to1x2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3to3 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ + *(D)++ = FROM_16_TO_8((S)[1]); \ + *(D)++ = FROM_16_TO_8((S)[2]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3x2to3x2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3to4 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ + *(D)++ = FROM_16_TO_8((S)[1]); \ + *(D)++ = FROM_16_TO_8((S)[2]); \ + *(D)++ = FROM_16_TO_8((S)[3]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3x2to4x2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4to1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[3] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4x2to1x2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4to3 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[3] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ + *(D)++ = FROM_16_TO_8((S)[1]); \ + *(D)++ = FROM_16_TO_8((S)[2]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4x2to3x2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4to4 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[3] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ + *(D)++ = FROM_16_TO_8((S)[1]); \ + *(D)++ = FROM_16_TO_8((S)[2]); \ + *(D)++ = FROM_16_TO_8((S)[3]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4x2to4x2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 0 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +// Same again, but with alpha +// Special ones for common cases. +#define FUNCTION_NAME CachedXFORM1to1_1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1x2to1x2_2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1to3_1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 3 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ + *(D)++ = FROM_16_TO_8((S)[1]); \ + *(D)++ = FROM_16_TO_8((S)[2]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1x2to3x2_2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1to4_1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ + *(D)++ = FROM_16_TO_8((S)[1]); \ + *(D)++ = FROM_16_TO_8((S)[2]); \ + *(D)++ = FROM_16_TO_8((S)[3]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1x2to4x2_2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3to1_1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3x2to1x2_2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3to3_1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ + *(D)++ = FROM_16_TO_8((S)[1]); \ + *(D)++ = FROM_16_TO_8((S)[2]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3x2to3x2_2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3to4_1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ + *(D)++ = FROM_16_TO_8((S)[1]); \ + *(D)++ = FROM_16_TO_8((S)[2]); \ + *(D)++ = FROM_16_TO_8((S)[3]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3x2to4x2_2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4to1_1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[3] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4x2to1x2_2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4to3_1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[3] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ + *(D)++ = FROM_16_TO_8((S)[1]); \ + *(D)++ = FROM_16_TO_8((S)[2]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4x2to3x2_2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4to4_1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ + (D)[3] = FROM_8_TO_16(*(S)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = FROM_16_TO_8((S)[0]); \ + *(D)++ = FROM_16_TO_8((S)[1]); \ + *(D)++ = FROM_16_TO_8((S)[2]); \ + *(D)++ = FROM_16_TO_8((S)[3]); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4x2to4x2_2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 1 +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ + (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ + *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \ +} while (0) +#include "extra_xform.h" + + +// Same again, but with premultiplied alpha +// +// No gamut check, Cache, 16 bits, +#define FUNCTION_NAME CachedXFORM_P1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define PREALPHA +#include "extra_xform.h" + +// No gamut check, Cache, 16 bits, +#define FUNCTION_NAME CachedXFORM_P2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define PREALPHA +#include "extra_xform.h" + +// Special ones for common cases. +#define FUNCTION_NAME CachedXFORM1to1_P1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xFFFFU / (A); \ + (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1x2to1x2_P2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xffff0000U / (A); \ + (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1to3_P1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xFFFFU / (A); \ + (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1x2to3x2_P2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xffff0000U / (A); \ + (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1to4_P1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xFFFFU / (A); \ + (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[3]),(A)); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM1x2to4x2_P2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 1 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xffff0000U / (A); \ + (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[3],A); (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3to1_P1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xFFFFU / (A); \ + (D)[0] = (cmsUInt16Number)((*(S) * inva)); (S)++; \ + (D)[1] = (cmsUInt16Number)((*(S) * inva)); (S)++; \ + (D)[2] = (cmsUInt16Number)((*(S) * inva)); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3x2to1x2_P2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xffff0000U / (A); \ + (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3to3_P1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xFFFFU / (A); \ + (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3x2to3x2_P2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xffff0000U / (A); \ + (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3to4_P1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xFFFFU / (A); \ + (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[3]),(A)); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM3x2to4x2_P2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 3 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xffff0000U / (A); \ + (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[3],A); (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4to1_P1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xFFFFU / (A); \ + (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[3] = (cmsUInt16Number)(*(S) * inva); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4x2to1x2_P2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 1 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xffff0000U / (A); \ + (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[3] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4to3_P1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xFFFFU / (A); \ + (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[3] = (cmsUInt16Number)(*(S) * inva); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4x2to3x2_P2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 3 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xffff0000U / (A); \ + (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[3] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4to4_P1 +#define CACHED +#define INPACKEDSAMPLESIZE 1 +#define OUTPACKEDSAMPLESIZE 1 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xFFFFU / (A); \ + (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \ + (D)[3] = (cmsUInt16Number)(*(S) * inva); (S)++; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \ + *(D)++ = mul255(FROM_16_TO_8((S)[3]),(A)); \ +} while (0) +#include "extra_xform.h" + +#define FUNCTION_NAME CachedXFORM4x2to4x2_P2 +#define CACHED +#define INPACKEDSAMPLESIZE 2 +#define OUTPACKEDSAMPLESIZE 2 +#define NUMINCHANNELS 4 +#define NUMOUTCHANNELS 4 +#define NUMEXTRAS 1 +#define PREALPHA +#define UNPACKINCLUDESPREALPHA +#define PACKINCLUDESPREALPHA +#define UNPACK(CTX,T,D,S,Z,A) \ +do { \ + cmsUInt32Number inva = 0xffff0000U / (A); \ + (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ + (D)[3] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ +} while (0) +#define PACK(CTX,T,S,D,Z,A) \ +do { \ + *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \ + *(cmsUInt16Number *)(D) = mul65535((S)[3],A); (D) += 2; \ +} while (0) +#include "extra_xform.h" + + +// Transform plug-ins ---------------------------------------------------------------------------------------------------- + +// List of used-defined transform factories +typedef struct _cmsTransformCollection_st { + + _cmsTransform2Factory Factory; + cmsBool OldXform; // Factory returns xform function in the old style + + struct _cmsTransformCollection_st *Next; + +} _cmsTransformCollection; + +// The linked list head +_cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL }; + + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupPluginTransformList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsTransformPluginChunkType newHead = { NULL }; + _cmsTransformCollection* entry; + _cmsTransformCollection* Anterior = NULL; + _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin]; + + // Walk the list copying all nodes + for (entry = head->TransformCollection; + entry != NULL; + entry = entry ->Next) { + + _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.TransformCollection == NULL) + newHead.TransformCollection = newEntry; + } + + ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType)); +} + +// Allocates memory for transform plugin factory +void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + // Copy all linked list + DupPluginTransformList(ctx, src); + } + else { + static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL }; + ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType)); + } +} + +// Adaptor for old versions of plug-in +static +void _cmsTransform2toTransformAdaptor(cmsContext ContextID, struct _cmstransform_struct *CMMcargo, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + + cmsUInt32Number i, strideIn, strideOut; + + _cmsHandleExtraChannels(ContextID, CMMcargo, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + + for (i = 0; i < LineCount; i++) { + + void *accum = (cmsUInt8Number*)InputBuffer + strideIn; + void *output = (cmsUInt8Number*)OutputBuffer + strideOut; + + CMMcargo->OldXform(ContextID, CMMcargo, accum, output, PixelsPerLine, Stride->BytesPerPlaneIn); + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } +} + + + +// Register new ways to transform +cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data) +{ + cmsPluginTransform* Plugin = (cmsPluginTransform*) Data; + _cmsTransformCollection* fl; + _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin); + + if (Data == NULL) { + + // Free the chain. Memory is safely freed at exit + ctx->TransformCollection = NULL; + return TRUE; + } + + // Factory callback is required + if (Plugin->factories.xform == NULL) return FALSE; + + + fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection)); + if (fl == NULL) return FALSE; + + // Check for full xform plug-ins previous to 2.8, we would need an adapter in that case + if (Plugin->base.ExpectedVersion < 2080) { + + fl->OldXform = TRUE; + } + else + fl->OldXform = FALSE; + + // Copy the parameters + fl->Factory = Plugin->factories.xform; + + // Keep linked list + fl ->Next = ctx->TransformCollection; + ctx->TransformCollection = fl; + + // All is ok + return TRUE; +} + + +void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn) +{ + _cmsAssert(CMMcargo != NULL && CMMcargo->core != NULL); + CMMcargo->core->UserData = ptr; + CMMcargo->core->FreeUserData = FreePrivateDataFn; +} + +// returns the pointer defined by the plug-in to store private data +void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo) +{ + _cmsAssert(CMMcargo != NULL && CMMcargo->core != NULL); + return CMMcargo->core->UserData; +} + +// returns the current formatters +void CMSEXPORT _cmsGetTransformFormatters16(struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput) +{ + _cmsAssert(CMMcargo != NULL); + if (FromInput) *FromInput = CMMcargo ->FromInput; + if (ToOutput) *ToOutput = CMMcargo ->ToOutput; +} + +void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput) +{ + _cmsAssert(CMMcargo != NULL); + if (FromInput) *FromInput = CMMcargo ->FromInputFloat; + if (ToOutput) *ToOutput = CMMcargo ->ToOutputFloat; +} + +// returns original flags +cmsUInt32Number CMSEXPORT _cmsGetTransformFlags(struct _cmstransform_struct* CMMcargo) +{ + _cmsAssert(CMMcargo != NULL); + return CMMcargo->core->dwOriginalFlags; +} + +void +_cmsFindFormatter(_cmsTRANSFORM* p, cmsUInt32Number InputFormat, cmsUInt32Number OutputFormat, cmsUInt32Number dwFlags) +{ + if (dwFlags & cmsFLAGS_NULLTRANSFORM) { + p ->xform = NullXFORM; + return; + } + if (dwFlags & cmsFLAGS_PREMULT) { + if (dwFlags & cmsFLAGS_NOCACHE) { + if (dwFlags & cmsFLAGS_GAMUTCHECK) + p ->xform = PrecalculatedXFORMGamutCheck_P; // Gamut check, no cache + else if ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) && + _cmsLutIsIdentity(p->core->Lut)) { + if (T_PLANAR(InputFormat)) + p ->xform = PrecalculatedXFORMIdentityPlanar; + else + p ->xform = PrecalculatedXFORMIdentity; + } else + p ->xform = PrecalculatedXFORM_P; // No cache, no gamut check + return; + } + if (dwFlags & cmsFLAGS_GAMUTCHECK) { + p ->xform = CachedXFORMGamutCheck_P; // Gamut check, cache + return; + } + if ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) && + _cmsLutIsIdentity(p->core->Lut)) { + /* No point in a cache here! */ + if (T_PLANAR(InputFormat)) + p ->xform = PrecalculatedXFORMIdentityPlanar; + else + p ->xform = PrecalculatedXFORMIdentity; + return; + } + } + if (dwFlags & cmsFLAGS_NOCACHE) { + if (dwFlags & cmsFLAGS_GAMUTCHECK) + p ->xform = PrecalculatedXFORMGamutCheck; // Gamut check, no cache + else if ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) && + _cmsLutIsIdentity(p->core->Lut)) { + if (T_PLANAR(InputFormat)) + p ->xform = PrecalculatedXFORMIdentityPlanar; + else + p ->xform = PrecalculatedXFORMIdentity; + } else + p ->xform = PrecalculatedXFORM; // No cache, no gamut check + return; + } + if (dwFlags & cmsFLAGS_GAMUTCHECK) { + p ->xform = CachedXFORMGamutCheck; // Gamut check, cache + return; + } + if ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) && + _cmsLutIsIdentity(p->core->Lut)) { + /* No point in a cache here! */ + if (T_PLANAR(InputFormat)) + p ->xform = PrecalculatedXFORMIdentityPlanar; + else + p ->xform = PrecalculatedXFORMIdentity; + return; + } + if (T_EXTRA(InputFormat) == 1 && T_EXTRA(OutputFormat) == 1) { + if (dwFlags & cmsFLAGS_PREMULT) { + if ((InputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0 && + (OutputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0) { + switch ((InputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))| + ((OutputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))<<6)) { + case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): + p->xform = CachedXFORM1to1_P1; + return; + case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): + p->xform = CachedXFORM1x2to1x2_P2; + return; + case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): + p->xform = CachedXFORM1to3_P1; + return; + case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): + p->xform = CachedXFORM1x2to3x2_P2; + return; + case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): + p->xform = CachedXFORM1to4_P1; + return; + case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): + p->xform = CachedXFORM1x2to4x2_P2; + return; + case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): + p ->xform = CachedXFORM3to1_P1; + return; + case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): + p ->xform = CachedXFORM3x2to1x2_P2; + return; + case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): + p->xform = CachedXFORM3to3_P1; + return; + case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): + p->xform = CachedXFORM3x2to3x2_P2; + return; + case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): + p->xform = CachedXFORM3to4_P1; + return; + case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): + p->xform = CachedXFORM3x2to4x2_P2; + return; + case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): + p->xform = CachedXFORM4to1_P1; + return; + case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): + p->xform = CachedXFORM4x2to1x2_P2; + return; + case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): + p->xform = CachedXFORM4to3_P1; + return; + case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): + p->xform = CachedXFORM4x2to3x2_P2; + return; + case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): + p->xform = CachedXFORM4to4_P1; + return; + case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): + p->xform = CachedXFORM4x2to4x2_P2; + return; + } + } + } else { + if ((InputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0 && + (OutputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0) { + switch ((InputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))| + ((OutputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))<<6)) { + case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): + p->xform = CachedXFORM1to1_1; + return; + case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): + p->xform = CachedXFORM1x2to1x2_2; + return; + case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): + p->xform = CachedXFORM1to3_1; + return; + case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): + p->xform = CachedXFORM1x2to3x2_2; + return; + case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): + p->xform = CachedXFORM1to4_1; + return; + case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): + p->xform = CachedXFORM1x2to4x2_2; + return; + case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): + p ->xform = CachedXFORM3to1_1; + return; + case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): + p ->xform = CachedXFORM3x2to1x2_2; + return; + case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): + p->xform = CachedXFORM3to3_1; + return; + case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): + p->xform = CachedXFORM3x2to3x2_2; + return; + case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): + p->xform = CachedXFORM3to4_1; + return; + case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): + p->xform = CachedXFORM3x2to4x2_2; + return; + case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): + p->xform = CachedXFORM4to1_1; + return; + case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): + p->xform = CachedXFORM4x2to1x2_2; + return; + case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): + p->xform = CachedXFORM4to3_1; + return; + case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): + p->xform = CachedXFORM4x2to3x2_2; + return; + case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): + p->xform = CachedXFORM4to4_1; + return; + case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): + p->xform = CachedXFORM4x2to4x2_2; + return; + } + } + } + } + if (T_EXTRA(InputFormat) != 0) { + if (dwFlags & cmsFLAGS_PREMULT) { + if (T_BYTES(InputFormat) == 1) + p ->xform = CachedXFORM_P1;// No gamut check, cache + else + p ->xform = CachedXFORM_P2;// No gamut check, cache + } else { + p ->xform = CachedXFORM; // No gamut check, cache + } + return; + } + if ((InputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3))) == 0 && + (OutputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3))) == 0) { + switch ((InputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))| + ((OutputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))<<6)) { + case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): + p->xform = CachedXFORM1to1; + return; + case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): + p->xform = CachedXFORM1x2to1x2; + return; + case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): + p->xform = CachedXFORM1to3; + return; + case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): + p->xform = CachedXFORM1x2to3x2; + return; + case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): + p->xform = CachedXFORM1to4; + return; + case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): + p->xform = CachedXFORM1x2to4x2; + return; + case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): + p ->xform = CachedXFORM3to1; + return; + case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): + p ->xform = CachedXFORM3x2to1x2; + return; + case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): + p->xform = CachedXFORM3to3; + return; + case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): + p->xform = CachedXFORM3x2to3x2; + return; + case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): + p->xform = CachedXFORM3to4; + return; + case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): + p->xform = CachedXFORM3x2to4x2; + return; + case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): + p->xform = CachedXFORM4to1; + return; + case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): + p->xform = CachedXFORM4x2to1x2; + return; + case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): + p->xform = CachedXFORM4to3; + return; + case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): + p->xform = CachedXFORM4x2to3x2; + return; + case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): + p->xform = CachedXFORM4to4; + return; + case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): + p->xform = CachedXFORM4x2to4x2; + return; + } + } + { + int inwords = T_CHANNELS(InputFormat); + if (inwords <= 2) + p ->xform = CachedXFORM4; + else if (inwords <= 4) + p ->xform = CachedXFORM8; + else + p ->xform = CachedXFORM; // No gamut check, cache + } +} + +// Returns the worker callback for parallelization plug-ins +_cmsTransform2Fn CMSEXPORT _cmsGetTransformWorker(struct _cmstransform_struct* CMMcargo) +{ + _cmsAssert(CMMcargo != NULL); + return CMMcargo->Worker; +} + +// This field holds maximum number of workers or -1 to auto +cmsInt32Number CMSEXPORT _cmsGetTransformMaxWorkers(struct _cmstransform_struct* CMMcargo) +{ + _cmsAssert(CMMcargo != NULL); + return CMMcargo->MaxWorkers; +} + +// This field is actually unused and reserved +cmsUInt32Number CMSEXPORT _cmsGetTransformWorkerFlags(struct _cmstransform_struct* CMMcargo) +{ + _cmsAssert(CMMcargo != NULL); + return CMMcargo->WorkerFlags; +} + +// In the case there is a parallelization plug-in, let it to do its job +static +void ParalellizeIfSuitable(cmsContext ContextID, _cmsTRANSFORM* p) +{ + _cmsParallelizationPluginChunkType* ctx = (_cmsParallelizationPluginChunkType*)_cmsContextGetClientChunk(ContextID, ParallelizationPlugin); + + _cmsAssert(p != NULL); + if (ctx != NULL && ctx->SchedulerFn != NULL) { + + p->Worker = p->xform; + p->xform = ctx->SchedulerFn; + p->MaxWorkers = ctx->MaxWorkers; + p->WorkerFlags = ctx->WorkerFlags; + } +} + + +/** +* An empty unroll to avoid a check with NULL on cmsDoTransform() +*/ +static +cmsUInt8Number* UnrollNothing(cmsContext ContextID, + CMSREGISTER _cmsTRANSFORM* info, + CMSREGISTER cmsUInt16Number wIn[], + CMSREGISTER cmsUInt8Number* accum, + CMSREGISTER cmsUInt32Number Stride) +{ + return accum; + + cmsUNUSED_PARAMETER(ContextID); + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(wIn); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* PackNothing(cmsContext ContextID, + CMSREGISTER _cmsTRANSFORM* info, + CMSREGISTER cmsUInt16Number wOut[], + CMSREGISTER cmsUInt8Number* output, + CMSREGISTER cmsUInt32Number Stride) +{ + return output; + + cmsUNUSED_PARAMETER(ContextID); + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(wOut); + cmsUNUSED_PARAMETER(Stride); +} + +// Allocate transform struct and set it to defaults. Ask the optimization plug-in about if those formats are proper +// for separated transforms. If this is the case, +static +_cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, + cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) +{ + _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin); + _cmsTransformCollection* Plugin; + _cmsTRANSFORMCORE *core; + + // Allocate needed memory + _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); + if (!p) { + cmsPipelineFree(ContextID, lut); + return NULL; + } + + core = (_cmsTRANSFORMCORE*)_cmsMallocZero(ContextID, sizeof(*core)); + if (!core) { + _cmsFree(ContextID, p); + cmsPipelineFree(ContextID, lut); + return NULL; + } + + p->core = core; + core->refs = 1; + // Store the proposed pipeline + p->core->Lut = lut; + + // Let's see if any plug-in want to do the transform by itself + if (core->Lut != NULL) { + if (!(*dwFlags & cmsFLAGS_NOOPTIMIZE)) { + + for (Plugin = ctx->TransformCollection; + Plugin != NULL; + Plugin = Plugin->Next) { + + if (Plugin->Factory(ContextID, &p->xform, &core->UserData, &core->FreeUserData, &core->Lut, InputFormat, OutputFormat, dwFlags)) { + + // Last plugin in the declaration order takes control. We just keep + // the original parameters as a logging. + // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default + // an optimized transform is not reusable. The plug-in can, however, change + // the flags and make it suitable. + + p->InputFormat = *InputFormat; + p->OutputFormat = *OutputFormat; + core->dwOriginalFlags = *dwFlags; + + // Fill the formatters just in case the optimized routine is interested. + // No error is thrown if the formatter doesn't exist. It is up to the optimization + // factory to decide what to do in those cases. + p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + + // Save the day? (Ignore the warning) + if (Plugin->OldXform) { + p->OldXform = (_cmsTransformFn)(void*) p->xform; + p->xform = _cmsTransform2toTransformAdaptor; + } + + ParalellizeIfSuitable(ContextID, p); + return p; + } + } + } + + // Not suitable for the transform plug-in, let's check the pipeline plug-in + _cmsOptimizePipeline(ContextID, &core->Lut, Intent, InputFormat, OutputFormat, dwFlags); + } + + // Check whatever this is a true floating point transform + if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) { + + // Get formatter function always return a valid union, but the contents of this union may be NULL. + p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; + + if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { + + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); + cmsDeleteTransform(ContextID, p); + return NULL; + } + + if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { + + p ->xform = NullFloatXFORM; + } + else { + // Float transforms don't use cache, always are non-NULL + p ->xform = FloatXFORM; + } + + } + else { + + // Formats are intended to be changed before use + if (*InputFormat == 0 && *OutputFormat == 0) { + p->FromInput = UnrollNothing; + p->ToOutput = PackNothing; + *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; + } + else { + + cmsUInt32Number BytesPerPixelInput; + + p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + + if (p ->FromInput == NULL || p ->ToOutput == NULL) { + + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); + cmsDeleteTransform(ContextID, p); + return NULL; + } + + BytesPerPixelInput = T_BYTES(*InputFormat); + if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2) + *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; + + } + + _cmsFindFormatter(p, *InputFormat, *OutputFormat, *dwFlags); + } + + /** + * Check consistency for alpha channel copy + */ + if (*dwFlags & cmsFLAGS_COPY_ALPHA) + { + if (T_EXTRA(*InputFormat) != T_EXTRA(*OutputFormat)) + { + cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Mismatched alpha channels"); + cmsDeleteTransform(ContextID, p); + return NULL; + } + } + + p ->InputFormat = *InputFormat; + p ->OutputFormat = *OutputFormat; + core->dwOriginalFlags = *dwFlags; + core->UserData = NULL; + ParalellizeIfSuitable(ContextID, p); + return p; +} + +static +cmsBool GetXFormColorSpaces(cmsContext ContextID, cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output) +{ + cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut; + cmsColorSpaceSignature PostColorSpace; + cmsUInt32Number i; + + if (nProfiles == 0) return FALSE; + if (hProfiles[0] == NULL) return FALSE; + + *Input = PostColorSpace = cmsGetColorSpace(ContextID, hProfiles[0]); + + for (i=0; i < nProfiles; i++) { + + cmsProfileClassSignature cls; + cmsHPROFILE hProfile = hProfiles[i]; + + int lIsInput = (PostColorSpace != cmsSigXYZData) && + (PostColorSpace != cmsSigLabData); + + if (hProfile == NULL) return FALSE; + + cls = cmsGetDeviceClass(ContextID, hProfile); + + if (cls == cmsSigNamedColorClass) { + + ColorSpaceIn = cmsSig1colorData; + ColorSpaceOut = (nProfiles > 1) ? cmsGetPCS(ContextID, hProfile) : cmsGetColorSpace(ContextID, hProfile); + } + else + if (lIsInput || (cls == cmsSigLinkClass)) { + + ColorSpaceIn = cmsGetColorSpace(ContextID, hProfile); + ColorSpaceOut = cmsGetPCS(ContextID, hProfile); + } + else + { + ColorSpaceIn = cmsGetPCS(ContextID, hProfile); + ColorSpaceOut = cmsGetColorSpace(ContextID, hProfile); + } + + if (i==0) + *Input = ColorSpaceIn; + + PostColorSpace = ColorSpaceOut; + } + + *Output = PostColorSpace; + + return TRUE; +} + +// Check colorspace +static +cmsBool IsProperColorSpace(cmsContext ContextID, cmsColorSpaceSignature Check, cmsUInt32Number dwFormat) +{ + int Space1 = (int) T_COLORSPACE(dwFormat); + int Space2 = _cmsLCMScolorSpace(ContextID, Check); + + if (Space1 == PT_ANY) return TRUE; + if (Space1 == Space2) return TRUE; + + if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE; + if (Space1 == PT_Lab && Space2 == PT_LabV2) return TRUE; + + return FALSE; +} + +// ---------------------------------------------------------------------------------------------------------------- + +// Jun-21-2000: Some profiles (those that comes with W2K) comes +// with the media white (media black?) x 100. Add a sanity check + +static +void NormalizeXYZ(cmsCIEXYZ* Dest) +{ + while (Dest -> X > 2. && + Dest -> Y > 2. && + Dest -> Z > 2.) { + + Dest -> X /= 10.; + Dest -> Y /= 10.; + Dest -> Z /= 10.; + } +} + +static +void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src) +{ + if (src == NULL) { + wtPt ->X = cmsD50X; + wtPt ->Y = cmsD50Y; + wtPt ->Z = cmsD50Z; + } + else { + wtPt ->X = src->X; + wtPt ->Y = src->Y; + wtPt ->Z = src->Z; + + NormalizeXYZ(wtPt); + } + +} + +// New to lcms 2.0 -- have all parameters available. +cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, + cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsUInt32Number Intents[], + cmsFloat64Number AdaptationStates[], + cmsHPROFILE hGamutProfile, + cmsUInt32Number nGamutPCSposition, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + cmsUInt32Number dwFlags) +{ + _cmsTRANSFORM* xform; + cmsColorSpaceSignature EntryColorSpace; + cmsColorSpaceSignature ExitColorSpace; + cmsPipeline* Lut; + cmsUInt32Number LastIntent = Intents[nProfiles-1]; + + // If it is a fake transform + if (dwFlags & cmsFLAGS_NULLTRANSFORM) + { + return AllocEmptyTransform(ContextID, NULL, INTENT_PERCEPTUAL, &InputFormat, &OutputFormat, &dwFlags); + } + + // If gamut check is requested, make sure we have a gamut profile + if (dwFlags & cmsFLAGS_GAMUTCHECK) { + if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK; + } + + // On floating point transforms, inhibit cache + if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat)) + dwFlags |= cmsFLAGS_NOCACHE; + + // Mark entry/exit spaces + if (!GetXFormColorSpaces(ContextID, nProfiles, hProfiles, &EntryColorSpace, &ExitColorSpace)) { + cmsSignalError(ContextID, cmsERROR_NULL, "NULL input profiles on transform"); + return NULL; + } + + // Check if proper colorspaces + if (!IsProperColorSpace(ContextID, EntryColorSpace, InputFormat)) { + cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong input color space on transform"); + return NULL; + } + + if (!IsProperColorSpace(ContextID, ExitColorSpace, OutputFormat)) { + cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong output color space on transform"); + return NULL; + } + + // Check whatever the transform is 16 bits and involves linear RGB in first profile. If so, disable optimizations + if (EntryColorSpace == cmsSigRgbData && T_BYTES(InputFormat) == 2 && !(dwFlags & cmsFLAGS_NOOPTIMIZE)) + { + cmsFloat64Number gamma = cmsDetectRGBProfileGamma(ContextID, hProfiles[0], 0.1); + + if (gamma > 0 && gamma < 1.6) + dwFlags |= cmsFLAGS_NOOPTIMIZE; + } + + // Create a pipeline with all transformations + Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags); + if (Lut == NULL) { + cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Couldn't link the profiles"); + return NULL; + } + + // Check channel count + if ((cmsChannelsOfColorSpace(ContextID, EntryColorSpace) != (cmsInt32Number) cmsPipelineInputChannels(ContextID, Lut)) || + (cmsChannelsOfColorSpace(ContextID, ExitColorSpace) != (cmsInt32Number) cmsPipelineOutputChannels(ContextID, Lut))) { + cmsPipelineFree(ContextID, Lut); + cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted"); + return NULL; + } + + // Check premultiplication requirements + if (dwFlags & cmsFLAGS_PREMULT) { + if (T_BYTES(InputFormat) != T_BYTES(OutputFormat)) { + cmsPipelineFree(ContextID, Lut); + cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Premultiplication requires input and output to be in the same format."); + return NULL; + } + + if (T_EXTRA(InputFormat) < 1 || T_EXTRA(OutputFormat) < 1 || T_EXTRA(InputFormat) != T_EXTRA(OutputFormat) || (dwFlags & cmsFLAGS_COPY_ALPHA) == 0) { + cmsPipelineFree(ContextID, Lut); + cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Premultiplication must preserve the extra channels"); + return NULL; + } + } + + + // All seems ok + xform = AllocEmptyTransform(ContextID, Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags); + if (xform == NULL) { + return NULL; + } + + // Keep values + xform->core->EntryColorSpace = EntryColorSpace; + xform->core->ExitColorSpace = ExitColorSpace; + xform->core->RenderingIntent = Intents[nProfiles-1]; + + // Take white points + SetWhitePoint(&xform->core->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(ContextID, hProfiles[0], cmsSigMediaWhitePointTag)); + SetWhitePoint(&xform->core->ExitWhitePoint, (cmsCIEXYZ*) cmsReadTag(ContextID, hProfiles[nProfiles-1], cmsSigMediaWhitePointTag)); + + + // Create a gamut check LUT if requested + if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK)) + xform->core->GamutCheck = _cmsCreateGamutCheckPipeline(ContextID, hProfiles, + BPC, Intents, + AdaptationStates, + nGamutPCSposition, + hGamutProfile); + + + // Try to read input and output colorant table + if (cmsIsTag(ContextID, hProfiles[0], cmsSigColorantTableTag)) { + + // Input table can only come in this way. + xform->core->InputColorant = cmsDupNamedColorList(ContextID, (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hProfiles[0], cmsSigColorantTableTag)); + } + + // Output is a little bit more complex. + if (cmsGetDeviceClass(ContextID, hProfiles[nProfiles-1]) == cmsSigLinkClass) { + + // This tag may exist only on devicelink profiles. + if (cmsIsTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableOutTag)) { + + // It may be NULL if error + xform->core->OutputColorant = cmsDupNamedColorList(ContextID, (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableOutTag)); + } + + } else { + + if (cmsIsTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableTag)) { + + xform->core->OutputColorant = cmsDupNamedColorList(ContextID, (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableTag)); + } + } + + // Store the sequence of profiles + if (dwFlags & cmsFLAGS_KEEP_SEQUENCE) { + xform->core->Sequence = _cmsCompileProfileSequence(ContextID, nProfiles, hProfiles); + } + else + xform->core->Sequence = NULL; + + // If this is a cached transform, init first value, which is zero (16 bits only) + if (!(dwFlags & cmsFLAGS_NOCACHE)) { + + memset(&xform ->Cache.CacheIn, 0, sizeof(xform ->Cache.CacheIn)); + + if (xform->core->GamutCheck != NULL) { + TransformOnePixelWithGamutCheck(ContextID, xform, xform->Cache.CacheIn, xform->Cache.CacheOut); + } + else { + + xform->core->Lut->Eval16Fn(ContextID, xform ->Cache.CacheIn, xform->Cache.CacheOut, xform->core->Lut->Data); + } + + } + + return (cmsHTRANSFORM) xform; +} + +// Multiprofile transforms: Gamut check is not available here, as it is unclear from which profile the gamut comes. +cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransform(cmsContext ContextID, + cmsHPROFILE hProfiles[], + cmsUInt32Number nProfiles, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags) +{ + cmsUInt32Number i; + cmsBool BPC[256]; + cmsUInt32Number Intents[256]; + cmsFloat64Number AdaptationStates[256]; + + if (nProfiles <= 0 || nProfiles > 255) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles); + return NULL; + } + + for (i=0; i < nProfiles; i++) { + BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE; + Intents[i] = Intent; + AdaptationStates[i] = cmsSetAdaptationState(ContextID, -1); + } + + + return cmsCreateExtendedTransform(ContextID, nProfiles, hProfiles, BPC, Intents, AdaptationStates, NULL, 0, InputFormat, OutputFormat, dwFlags); +} + + + +cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsContext ContextID, + cmsHPROFILE Input, + cmsUInt32Number InputFormat, + cmsHPROFILE Output, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags) +{ + + cmsHPROFILE hArray[2]; + + hArray[0] = Input; + hArray[1] = Output; + + return cmsCreateMultiprofileTransform(ContextID, hArray, Output == NULL ? 1U : 2U, InputFormat, OutputFormat, Intent, dwFlags); +} + + +cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransform(cmsContext ContextID, + cmsHPROFILE InputProfile, + cmsUInt32Number InputFormat, + cmsHPROFILE OutputProfile, + cmsUInt32Number OutputFormat, + cmsHPROFILE ProofingProfile, + cmsUInt32Number nIntent, + cmsUInt32Number ProofingIntent, + cmsUInt32Number dwFlags) +{ + cmsHPROFILE hArray[4]; + cmsUInt32Number Intents[4]; + cmsBool BPC[4]; + cmsFloat64Number Adaptation[4]; + cmsBool DoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION) ? TRUE : FALSE; + + + hArray[0] = InputProfile; hArray[1] = ProofingProfile; hArray[2] = ProofingProfile; hArray[3] = OutputProfile; + Intents[0] = nIntent; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = ProofingIntent; + BPC[0] = DoBPC; BPC[1] = DoBPC; BPC[2] = 0; BPC[3] = 0; + + Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationState(ContextID, -1); + + if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK))) + return cmsCreateTransform(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags); + + return cmsCreateExtendedTransform(ContextID, 4, hArray, BPC, Intents, Adaptation, + ProofingProfile, 1, InputFormat, OutputFormat, dwFlags); + +} + + + +// Grab the input/output formats +cmsUInt32Number CMSEXPORT cmsGetTransformInputFormat(cmsContext ContextID, cmsHTRANSFORM hTransform) +{ + _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; + cmsUNUSED_PARAMETER(ContextID); + + if (xform == NULL) return 0; + return xform->InputFormat; +} + +cmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsContext ContextID, cmsHTRANSFORM hTransform) +{ + _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; + cmsUNUSED_PARAMETER(ContextID); + + if (xform == NULL) return 0; + return xform->OutputFormat; +} + +cmsHTRANSFORM cmsCloneTransformChangingFormats(cmsContext ContextID, + const cmsHTRANSFORM hTransform, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat) +{ + const _cmsTRANSFORM *oldXform = (const _cmsTRANSFORM *)hTransform; + _cmsTRANSFORM *xform; + cmsFormatter16 FromInput, ToOutput; + + _cmsAssert(oldXform != NULL && oldXform->core != NULL); + + // We only can afford to change formatters if previous transform is at least 16 bits + if (!(oldXform->core->dwOriginalFlags & cmsFLAGS_CAN_CHANGE_FORMATTER)) { + cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "cmsCloneTransformChangingFormats works only on transforms created originally with at least 16 bits of precision"); + return NULL; + } + + xform = _cmsMalloc(ContextID, sizeof(*xform)); + if (xform == NULL) + return NULL; + + memcpy(xform, oldXform, sizeof(*xform)); + + FromInput = _cmsGetFormatter(ContextID, InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + ToOutput = _cmsGetFormatter(ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + + if (FromInput == NULL || ToOutput == NULL) { + + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); + return NULL; + } + + xform ->InputFormat = InputFormat; + xform ->OutputFormat = OutputFormat; + xform ->FromInput = FromInput; + xform ->ToOutput = ToOutput; + _cmsFindFormatter(xform, InputFormat, OutputFormat, xform->core->dwOriginalFlags); + + (void)_cmsAdjustReferenceCount(&xform->core->refs, 1); + + return xform; +}
