diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cmscgats.c | 33 | ||||
-rw-r--r-- | src/cmsgamma.c | 35 | ||||
-rw-r--r-- | src/cmslut.c | 15 | ||||
-rw-r--r-- | src/cmsopt.c | 10 | ||||
-rw-r--r-- | src/cmspack.c | 81 | ||||
-rw-r--r-- | src/cmsplugin.c | 5 | ||||
-rw-r--r-- | src/cmssamp.c | 4 | ||||
-rw-r--r-- | src/cmsvirt.c | 10 | ||||
-rw-r--r-- | src/cmsxform.c | 183 | ||||
-rw-r--r-- | src/lcms2.def | 10 | ||||
-rw-r--r-- | src/lcms2_internal.h | 53 |
11 files changed, 284 insertions, 155 deletions
diff --git a/src/cmscgats.c b/src/cmscgats.c index 487c2c3..5f482a1 100644 --- a/src/cmscgats.c +++ b/src/cmscgats.c @@ -603,6 +603,14 @@ static cmsFloat64Number ParseFloatNumber(const char *Buffer) { cmsFloat64Number dnum = 0.0; + int sign = 1; + + if (*Buffer == '-' || *Buffer == '+') { + + sign = (*Buffer == '-') ? -1 : 1; + Buffer++; + } + while (*Buffer && isdigit(*Buffer)) { @@ -661,8 +669,7 @@ cmsFloat64Number ParseFloatNumber(const char *Buffer) dnum = dnum * xpow10(e); } - - return dnum; + return sign * dnum; } @@ -1773,19 +1780,19 @@ cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number* sd.Max = *BytesNeeded; // Write to memory? else sd.Max = 0; // Just counting the needed bytes - + for (i=0; i < it8 ->TablesCount; i++) { - cmsIT8SetTable(hIT8, i); - WriteHeader(it8, &sd); - WriteDataFormat(&sd, it8); - WriteData(&sd, it8); + cmsIT8SetTable(hIT8, i); + WriteHeader(it8, &sd); + WriteDataFormat(&sd, it8); + WriteData(&sd, it8); } - + sd.Used++; // The \0 at the very end if (sd.Base) - sd.Ptr = 0; + *sd.Ptr = 0; *BytesNeeded = sd.Used; @@ -2198,11 +2205,11 @@ void CookPointers(cmsIT8* it8) // Try to infere if the file is a CGATS/IT8 file at all. Read first line // that should be something like some printable characters plus a \n -// returns 0 if this is not like a CGATS, or an integer otherwise +// returns 0 if this is not like a CGATS, or an integer otherwise. This integer is the number of words in first line? static int IsMyBlock(cmsUInt8Number* Buffer, int n) { - int cols = 1, space = 0, quot = 0; + int words = 1, space = 0, quot = 0; int i; if (n < 10) return 0; // Too small @@ -2216,7 +2223,7 @@ int IsMyBlock(cmsUInt8Number* Buffer, int n) { case '\n': case '\r': - return ((quot == 1) || (cols > 2)) ? 0 : cols; + return ((quot == 1) || (words > 2)) ? 0 : words; case '\t': case ' ': if(!quot && !space) @@ -2228,7 +2235,7 @@ int IsMyBlock(cmsUInt8Number* Buffer, int n) default: if (Buffer[i] < 32) return 0; if (Buffer[i] > 127) return 0; - cols += space; + words += space; space = 0; break; } diff --git a/src/cmsgamma.c b/src/cmsgamma.c index 02dc910..b546fd8 100644 --- a/src/cmsgamma.c +++ b/src/cmsgamma.c @@ -248,18 +248,28 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu switch (Type) { - // X = Y ^ Gamma - case 1: - if (R < 0) - Val = 0; + // X = Y ^ Gamma + case 1: + if (R < 0) { + + if (fabs(Params[0] - 1.0) < MATRIX_DET_TOLERANCE) + Val = R; + else + Val = 0; + } else Val = pow(R, Params[0]); break; // Type 1 Reversed: X = Y ^1/gamma case -1: - if (R < 0) - Val = 0; + if (R < 0) { + + if (fabs(Params[0] - 1.0) < MATRIX_DET_TOLERANCE) + Val = R; + else + Val = 0; + } else Val = pow(R, 1/Params[0]); break; @@ -523,6 +533,19 @@ cmsFloat64Number EvalSegmentedFn(const cmsToneCurve *g, cmsFloat64Number R) return MINUS_INF; } +// Access to estimated low-res table +cmsUInt32Number CMSEXPORT cmsGetToneCurveEstimatedTableEntries(const cmsToneCurve* t) +{ + _cmsAssert(t != NULL); + return t ->nEntries; +} + +const cmsUInt16Number* CMSEXPORT cmsGetToneCurveEstimatedTable(const cmsToneCurve* t) +{ + _cmsAssert(t != NULL); + return t ->Table16; +} + // Create an empty gamma curve, by using tables. This specifies only the limited-precision part, and leaves the // floating point description empty. diff --git a/src/cmslut.c b/src/cmslut.c index 52204be..8f1febf 100644 --- a/src/cmslut.c +++ b/src/cmslut.c @@ -1298,14 +1298,21 @@ cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number In return NewLUT; } +cmsContext CMSEXPORT cmsGetPipelineContextID(const cmsPipeline* lut) +{ + _cmsAssert(lut != NULL); + return lut ->ContextID; +} cmsUInt32Number CMSEXPORT cmsPipelineInputChannels(const cmsPipeline* lut) { + _cmsAssert(lut != NULL); return lut ->InputChannels; } cmsUInt32Number CMSEXPORT cmsPipelineOutputChannels(const cmsPipeline* lut) { + _cmsAssert(lut != NULL); return lut ->OutputChannels; } @@ -1333,6 +1340,7 @@ void CMSEXPORT cmsPipelineFree(cmsPipeline* lut) // Default to evaluate the LUT on 16 bit-basis. void CMSEXPORT cmsPipelineEval16(const cmsUInt16Number In[], cmsUInt16Number Out[], const cmsPipeline* lut) { + _cmsAssert(lut != NULL); lut ->Eval16Fn(In, Out, lut->Data); } @@ -1340,6 +1348,7 @@ void CMSEXPORT cmsPipelineEval16(const cmsUInt16Number In[], cmsUInt16Number Out // Does evaluate the LUT on cmsFloat32Number-basis. void CMSEXPORT cmsPipelineEvalFloat(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsPipeline* lut) { + _cmsAssert(lut != NULL); lut ->EvalFloatFn(In, Out, lut); } @@ -1377,8 +1386,10 @@ cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut) Anterior = NewMPE; } - NewLUT ->DupDataFn = lut ->DupDataFn; - NewLUT ->FreeDataFn = lut ->FreeDataFn; + NewLUT ->Eval16Fn = lut ->Eval16Fn; + NewLUT ->EvalFloatFn = lut ->EvalFloatFn; + NewLUT ->DupDataFn = lut ->DupDataFn; + NewLUT ->FreeDataFn = lut ->FreeDataFn; if (NewLUT ->DupDataFn != NULL) NewLUT ->Data = NewLUT ->DupDataFn(lut ->ContextID, lut->Data); diff --git a/src/cmsopt.c b/src/cmsopt.c index 554f832..7b99c5e 100644 --- a/src/cmsopt.c +++ b/src/cmsopt.c @@ -270,7 +270,7 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID, int nOutputs, cmsToneCurve** Out ) { int i; - Prelin16Data* p16 = (Prelin16Data*) _cmsMallocZero(ContextID, sizeof(Prelin16Data)); + Prelin16Data* p16 = _cmsMallocZero(ContextID, sizeof(Prelin16Data)); if (p16 == NULL) return NULL; p16 ->nInputs = nInputs; @@ -802,8 +802,8 @@ void PrelinEval8(register const cmsUInt16Number Input[], cmsUInt8Number r, g, b; cmsS15Fixed16Number rx, ry, rz; cmsS15Fixed16Number c0, c1, c2, c3, Rest; - int OutChan; - register cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1; + int OutChan; + register cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1; Prelin8Data* p8 = (Prelin8Data*) D; register const cmsInterpParams* p = p8 ->p; int TotalOut = p -> nOutputs; @@ -1430,12 +1430,12 @@ void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8Bi // first we compute the resulting byte and then we store the byte times // 257. This quantization allows to round very quick by doing a >> 8, but // since the low byte is always equal to msb, we can do a & 0xff and this works! - cmsUInt16Number w = _cmsQuickSaturateWord(Val * 65535.0 + 0.5); + cmsUInt16Number w = _cmsQuickSaturateWord(Val * 65535.0); cmsUInt8Number b = FROM_16_TO_8(w); Table[i] = FROM_8_TO_16(b); } - else Table[i] = _cmsQuickSaturateWord(Val * 65535.0 + 0.5); + else Table[i] = _cmsQuickSaturateWord(Val * 65535.0); } } diff --git a/src/cmspack.c b/src/cmspack.c index 16be43d..6056878 100644 --- a/src/cmspack.c +++ b/src/cmspack.c @@ -28,8 +28,8 @@ // This module handles all formats supported by lcms. There are two flavors, 16 bits and // floating point. Floating point is supported only in a subset, those formats holding -// cmsFloat32Number (4 bytes per component) and double (marked as 0 bytes per component as special -// case) +// cmsFloat32Number (4 bytes per component) and double (marked as 0 bytes per component +// as special case) // --------------------------------------------------------------------------- @@ -61,17 +61,18 @@ cmsINLINE cmsUInt16Number FomLabV4ToLabV2(cmsUInt16Number x) typedef struct { cmsUInt32Number Type; cmsUInt32Number Mask; - cmsFormatter16 Frm; + cmsFormatter16 Frm; } cmsFormatters16; typedef struct { cmsUInt32Number Type; cmsUInt32Number Mask; - cmsFormatterFloat Frm; + cmsFormatterFloat Frm; } cmsFormattersFloat; + #define ANYSPACE COLORSPACE_SH(31) #define ANYCHANNELS CHANNELS_SH(15) #define ANYEXTRA EXTRA_SH(7) @@ -144,13 +145,14 @@ cmsUInt8Number* UnrollPlanarBytes(register _cmsTRANSFORM* info, register cmsUInt8Number* accum, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> InputFormat); - int DoSwap= T_DOSWAP(info ->InputFormat); - int Reverse= T_FLAVOR(info ->InputFormat); + int nChan = T_CHANNELS(info -> InputFormat); + int DoSwap = T_DOSWAP(info ->InputFormat); + int SwapFirst = T_SWAPFIRST(info ->InputFormat); + int Reverse = T_FLAVOR(info ->InputFormat); int i; cmsUInt8Number* Init = accum; - if (DoSwap) { + if (DoSwap ^ SwapFirst) { accum += T_EXTRA(info -> InputFormat) * Stride; } @@ -1196,12 +1198,19 @@ cmsUInt8Number* PackPlanarBytes(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse= T_FLAVOR(info ->OutputFormat); + int nChan = T_CHANNELS(info -> OutputFormat); + int DoSwap = T_DOSWAP(info ->OutputFormat); + int SwapFirst = T_SWAPFIRST(info ->OutputFormat); + int Reverse = T_FLAVOR(info ->OutputFormat); int i; cmsUInt8Number* Init = output; + + if (DoSwap ^ SwapFirst) { + output += T_EXTRA(info -> OutputFormat) * Stride; + } + + for (i=0; i < nChan; i++) { int index = DoSwap ? (nChan - i - 1) : i; @@ -2475,6 +2484,8 @@ cmsUInt8Number* PackXYZDoubleFromFloat(_cmsTRANSFORM* Info, } + + // ---------------------------------------------------------------------------------------------------------------- @@ -2510,7 +2521,7 @@ static cmsFormatters16 InputFormatters16[] = { { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll4BytesSwap}, { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapSwapFirst}, - { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarBytes}, + { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarBytes}, { BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollChunkyBytes}, @@ -2531,7 +2542,7 @@ static cmsFormatters16 InputFormatters16[] = { { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4WordsSwapSwapFirst}, - { BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarWords }, + { BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarWords}, { BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollAnyWords}, }; @@ -2558,9 +2569,9 @@ cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number cmsUInt32Number i; cmsFormatter fr; + switch (dwFlags) { - if (!(dwFlags & CMS_PACK_FLAGS_FLOAT)) { - + case CMS_PACK_FLAGS_16BITS: { for (i=0; i < sizeof(InputFormatters16) / sizeof(cmsFormatters16); i++) { cmsFormatters16* f = InputFormatters16 + i; @@ -2570,7 +2581,9 @@ cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number } } } - else { + break; + + case CMS_PACK_FLAGS_FLOAT: { for (i=0; i < sizeof(InputFormattersFloat) / sizeof(cmsFormattersFloat); i++) { cmsFormattersFloat* f = InputFormattersFloat + i; @@ -2580,7 +2593,12 @@ cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number } } } + break; + default:; + + } + fr.Fmt16 = NULL; return fr; } @@ -2632,7 +2650,7 @@ static cmsFormatters16 OutputFormatters16[] = { { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapSwapFirst}, { BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyBytes}, - { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarBytes}, + { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarBytes}, { CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Pack1Word}, { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1), ANYSPACE, Pack1WordSkip1}, @@ -2689,28 +2707,37 @@ cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Numbe cmsFormatter fr; - if (dwFlags & CMS_PACK_FLAGS_FLOAT) { + switch (dwFlags) + { - for (i=0; i < sizeof(OutputFormattersFloat) / sizeof(cmsFormattersFloat); i++) { - cmsFormattersFloat* f = OutputFormattersFloat + i; + case CMS_PACK_FLAGS_16BITS: { + + for (i=0; i < sizeof(OutputFormatters16) / sizeof(cmsFormatters16); i++) { + cmsFormatters16* f = OutputFormatters16 + i; if ((dwInput & ~f ->Mask) == f ->Type) { - fr.FmtFloat = f ->Frm; + fr.Fmt16 = f ->Frm; return fr; } } + } + break; - } - else { + case CMS_PACK_FLAGS_FLOAT: { - for (i=0; i < sizeof(OutputFormatters16) / sizeof(cmsFormatters16); i++) { - cmsFormatters16* f = OutputFormatters16 + i; + for (i=0; i < sizeof(OutputFormattersFloat) / sizeof(cmsFormattersFloat); i++) { + cmsFormattersFloat* f = OutputFormattersFloat + i; if ((dwInput & ~f ->Mask) == f ->Type) { - fr.Fmt16 = f ->Frm; + fr.FmtFloat = f ->Frm; return fr; } } + } + break; + + default:; + } fr.Fmt16 = NULL; @@ -2754,7 +2781,7 @@ cmsBool _cmsRegisterFormattersPlugin(cmsPluginBase* Data) cmsFormatter _cmsGetFormatter(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 cmsFormatterDirection Dir, - cmsUInt32Number dwFlags) // Float or 16 bits + cmsUInt32Number dwFlags) { cmsFormattersFactoryList* f; diff --git a/src/cmsplugin.c b/src/cmsplugin.c index ca05ec0..58ce15d 100644 --- a/src/cmsplugin.c +++ b/src/cmsplugin.c @@ -581,6 +581,10 @@ cmsBool CMSEXPORT cmsPlugin(void* Plug_in) if (!_cmsRegisterOptimizationPlugin(Plugin)) return FALSE; break; + case cmsPluginTransformSig: + if (!_cmsRegisterTransformPlugin(Plugin)) return FALSE; + break; + default: cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type); return FALSE; @@ -604,6 +608,7 @@ void CMSEXPORT cmsUnregisterPlugins(void) _cmsRegisterParametricCurvesPlugin(NULL); _cmsRegisterMultiProcessElementPlugin(NULL); _cmsRegisterOptimizationPlugin(NULL); + _cmsRegisterTransformPlugin(NULL); if (PluginPool != NULL) _cmsSubAllocDestroy(PluginPool); diff --git a/src/cmssamp.c b/src/cmssamp.c index a918c66..420003e 100644 --- a/src/cmssamp.c +++ b/src/cmssamp.c @@ -270,7 +270,7 @@ cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfil // http://www.personal.psu.edu/jhm/f90/lectures/lsq2.html static -cmsFloat64Number VertexOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[], cmsFloat64Number y[]) +cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[], cmsFloat64Number y[]) { double sum_x = 0, sum_x2 = 0, sum_x3 = 0, sum_x4 = 0; double sum_y = 0, sum_yx = 0, sum_yx2 = 0; @@ -552,7 +552,7 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF Lab.L = x[NonMonoIndx]; // fit and get the vertex of quadratic curve - Lab.L = VertexOfLeastSquaresFitQuadraticCurve(n, x, y); + Lab.L = RootOfLeastSquaresFitQuadraticCurve(n, x, y); if (Lab.L < 0.0 || Lab.L > 50.0) { // clip to zero L* if the vertex is negative Lab.L = 0; diff --git a/src/cmsvirt.c b/src/cmsvirt.c index eafa58b..c8be58c 100644 --- a/src/cmsvirt.c +++ b/src/cmsvirt.c @@ -1106,12 +1106,12 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); // Put identity curves if needed - if (cmsPipelineStageCount(LUT) == 1) { - - cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn)); - cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, ChansOut)); - } + if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType) + cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn)); + if (cmsPipelineGetPtrToLastStage(LUT) ->Type != cmsSigCurveSetElemType) + cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, ChansOut)); + AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); } diff --git a/src/cmsxform.c b/src/cmsxform.c index eef54e4..aa6b41c 100644 --- a/src/cmsxform.c +++ b/src/cmsxform.c @@ -89,6 +89,9 @@ void CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform) if (p ->Sequence) cmsFreeProfileSequenceDescription(p ->Sequence); + if (p ->UserData) + p ->FreeUserData(p ->ContextID, p ->UserData); + _cmsFree(p ->ContextID, (void *) p); } @@ -101,7 +104,20 @@ void CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform, { _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; - p -> xform(p, InputBuffer, OutputBuffer, Size); + p -> xform(p, InputBuffer, OutputBuffer, Size, Size); +} + + +// Apply transform. +void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number Size, cmsUInt32Number Stride) + +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; + + p -> xform(p, InputBuffer, OutputBuffer, Size, Stride); } @@ -112,7 +128,7 @@ void CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform, static void FloatXFORM(_cmsTRANSFORM* p, const void* in, - void* out, cmsUInt32Number Size) + void* out, cmsUInt32Number Size, cmsUInt32Number Stride) { cmsUInt8Number* accum; cmsUInt8Number* output; @@ -125,7 +141,7 @@ void FloatXFORM(_cmsTRANSFORM* p, for (i=0; i < Size; i++) { - accum = p -> FromInputFloat(p, fIn, accum, Size); + accum = p -> FromInputFloat(p, fIn, accum, Stride); // Any gamut chack to do? if (p ->GamutCheck != NULL) { @@ -153,7 +169,7 @@ void FloatXFORM(_cmsTRANSFORM* p, } // Back to asked representation - output = p -> ToOutputFloat(p, fOut, output, Size); + output = p -> ToOutputFloat(p, fOut, output, Stride); } } @@ -163,7 +179,8 @@ void FloatXFORM(_cmsTRANSFORM* p, static void NullXFORM(_cmsTRANSFORM* p, const void* in, - void* out, cmsUInt32Number Size) + void* out, cmsUInt32Number Size, + cmsUInt32Number Stride) { cmsUInt8Number* accum; cmsUInt8Number* output; @@ -176,8 +193,8 @@ void NullXFORM(_cmsTRANSFORM* p, for (i=0; i < n; i++) { - accum = p -> FromInput(p, wIn, accum, Size); - output = p -> ToOutput(p, wIn, output, Size); + accum = p -> FromInput(p, wIn, accum, Stride); + output = p -> ToOutput(p, wIn, output, Stride); } } @@ -186,7 +203,7 @@ void NullXFORM(_cmsTRANSFORM* p, static void PrecalculatedXFORM(_cmsTRANSFORM* p, const void* in, - void* out, cmsUInt32Number Size) + void* out, cmsUInt32Number Size, cmsUInt32Number Stride) { register cmsUInt8Number* accum; register cmsUInt8Number* output; @@ -199,9 +216,9 @@ void PrecalculatedXFORM(_cmsTRANSFORM* p, for (i=0; i < n; i++) { - accum = p -> FromInput(p, wIn, accum, Size); + accum = p -> FromInput(p, wIn, accum, Stride); p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); - output = p -> ToOutput(p, wOut, output, Size); + output = p -> ToOutput(p, wOut, output, Stride); } } @@ -230,7 +247,7 @@ void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p, static void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, const void* in, - void* out, cmsUInt32Number Size) + void* out, cmsUInt32Number Size, cmsUInt32Number Stride) { cmsUInt8Number* accum; cmsUInt8Number* output; @@ -243,9 +260,9 @@ void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, for (i=0; i < n; i++) { - accum = p -> FromInput(p, wIn, accum, Size); + accum = p -> FromInput(p, wIn, accum, Stride); TransformOnePixelWithGamutCheck(p, wIn, wOut); - output = p -> ToOutput(p, wOut, output, Size); + output = p -> ToOutput(p, wOut, output, Stride); } } @@ -254,7 +271,7 @@ void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, static void CachedXFORM(_cmsTRANSFORM* p, const void* in, - void* out, cmsUInt32Number Size) + void* out, cmsUInt32Number Size, cmsUInt32Number Stride) { cmsUInt8Number* accum; cmsUInt8Number* output; @@ -275,7 +292,7 @@ void CachedXFORM(_cmsTRANSFORM* p, for (i=0; i < n; i++) { - accum = p -> FromInput(p, wIn, accum, Size); + accum = p -> FromInput(p, wIn, accum, Stride); if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { @@ -289,7 +306,7 @@ void CachedXFORM(_cmsTRANSFORM* p, memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); } - output = p -> ToOutput(p, wOut, output, Size); + output = p -> ToOutput(p, wOut, output, Stride); } } @@ -299,7 +316,7 @@ void CachedXFORM(_cmsTRANSFORM* p, static void CachedXFORMGamutCheck(_cmsTRANSFORM* p, const void* in, - void* out, cmsUInt32Number Size) + void* out, cmsUInt32Number Size, cmsUInt32Number Stride) { cmsUInt8Number* accum; cmsUInt8Number* output; @@ -320,7 +337,7 @@ void CachedXFORMGamutCheck(_cmsTRANSFORM* p, for (i=0; i < n; i++) { - accum = p -> FromInput(p, wIn, accum, Size); + accum = p -> FromInput(p, wIn, accum, Stride); if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); @@ -331,29 +348,106 @@ void CachedXFORMGamutCheck(_cmsTRANSFORM* p, memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); } - output = p -> ToOutput(p, wOut, output, Size); + output = p -> ToOutput(p, wOut, output, Stride); } } +// ------------------------------------------------------------------------------------------------------------- + +// List of used-defined transform factories +typedef struct _cmsTransformCollection_st { + + _cmsTranformFactory Factory; + struct _cmsTransformCollection_st *Next; + +} _cmsTransformCollection; + +// The linked list head +static _cmsTransformCollection* TransformCollection = NULL; +// Register new ways to transform +cmsBool _cmsRegisterTransformPlugin(cmsPluginBase* Data) +{ + cmsPluginTransform* Plugin = (cmsPluginTransform*) Data; + _cmsTransformCollection* fl; + + if (Data == NULL) { + + // Free the chain. Memory is safely freed at exit + TransformCollection = NULL; + return TRUE; + } + + // Factory callback is required + if (Plugin ->Factory == NULL) return FALSE; -// Allocate transform struct and set it to defaults + fl = (_cmsTransformCollection*) _cmsPluginMalloc(sizeof(_cmsTransformCollection)); + if (fl == NULL) return FALSE; + + // Copy the parameters + fl ->Factory = Plugin ->Factory; + + // Keep linked list + fl ->Next = TransformCollection; + TransformCollection = fl; + + // All is ok + return TRUE; +} + + +// returns the pointer defined by the plug-in to store private data +void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo) +{ + _cmsAssert(CMMcargo != NULL); + return CMMcargo ->UserData; +} + +// 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, cmsUInt32Number InputFormat, cmsUInt32Number OutputFormat, cmsUInt32Number dwFlags) +_cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, + cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) { + _cmsTransformCollection* Plugin; + // Allocate needed memory _cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); if (!p) return NULL; + // Store the proposed pipeline + p ->Lut = lut; + + // Let's see if any plug-in want to do the transform by itself + for (Plugin = TransformCollection; + Plugin != NULL; + Plugin = Plugin ->Next) { + + if (Plugin ->Factory(&p->xform, &p->UserData, &p ->FreeUserData, &p ->Lut, InputFormat, OutputFormat, dwFlags)) + { + // Last plugin in the declaration order takes control. We just keep + // the original parameters as a logging + p ->InputFormat = *InputFormat; + p ->OutputFormat = *OutputFormat; + p ->dwOriginalFlags = *dwFlags; + p ->ContextID = ContextID; + return p; + } + } + + // Not suitable for the transform plug-in, let's check the pipeline plug-in + if (p ->Lut != NULL) + _cmsOptimizePipeline(&p->Lut, Intent, InputFormat, OutputFormat, dwFlags); + // Check whatever this is a true floating point transform - if (_cmsFormatterIsFloat(InputFormat) && _cmsFormatterIsFloat(OutputFormat)) { + 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(InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - p ->ToOutputFloat = _cmsGetFormatter(OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; + p ->FromInputFloat = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->ToOutputFloat = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { @@ -367,17 +461,16 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsUInt32Number InputFo } else { - if (InputFormat == 0 && OutputFormat == 0) { + if (*InputFormat == 0 && *OutputFormat == 0) { p ->FromInput = p ->ToOutput = NULL; - dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; + *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; } else { int BytesPerPixelInput; - p ->FromInput = _cmsGetFormatter(InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->ToOutput = _cmsGetFormatter(OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; - + p ->FromInput = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->ToOutput = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; if (p ->FromInput == NULL || p ->ToOutput == NULL) { @@ -388,25 +481,25 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsUInt32Number InputFo BytesPerPixelInput = T_BYTES(p ->InputFormat); if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2) - dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; + *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; } - if (dwFlags & cmsFLAGS_NULLTRANSFORM) { + if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { p ->xform = NullXFORM; } else { - if (dwFlags & cmsFLAGS_NOCACHE) { + if (*dwFlags & cmsFLAGS_NOCACHE) { - if (dwFlags & cmsFLAGS_GAMUTCHECK) + if (*dwFlags & cmsFLAGS_GAMUTCHECK) p ->xform = PrecalculatedXFORMGamutCheck; // Gamut check, no caché else p ->xform = PrecalculatedXFORM; // No caché, no gamut check } else { - if (dwFlags & cmsFLAGS_GAMUTCHECK) + if (*dwFlags & cmsFLAGS_GAMUTCHECK) p ->xform = CachedXFORMGamutCheck; // Gamut check, caché else p ->xform = CachedXFORM; // No gamut check, caché @@ -414,12 +507,12 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsUInt32Number InputFo } } } - - p ->InputFormat = InputFormat; - p ->OutputFormat = OutputFormat; - p ->dwOriginalFlags = dwFlags; + p ->InputFormat = *InputFormat; + p ->OutputFormat = *OutputFormat; + p ->dwOriginalFlags = *dwFlags; p ->ContextID = ContextID; + p ->UserData = NULL; return p; } @@ -513,7 +606,7 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, // If it is a fake transform if (dwFlags & cmsFLAGS_NULLTRANSFORM) { - return AllocEmptyTransform(ContextID, InputFormat, OutputFormat, dwFlags); + return AllocEmptyTransform(ContextID, NULL, INTENT_PERCEPTUAL, &InputFormat, &OutputFormat, &dwFlags); } // If gamut check is requested, make sure we have a gamut profile @@ -551,14 +644,10 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, return NULL; } - // Optimize the LUT if possible - _cmsOptimizePipeline(&Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags); - - + // All seems ok - xform = AllocEmptyTransform(ContextID, InputFormat, OutputFormat, dwFlags); + xform = AllocEmptyTransform(ContextID, Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags); if (xform == NULL) { - cmsPipelineFree(Lut); return NULL; } @@ -566,7 +655,7 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, xform ->EntryColorSpace = EntryColorSpace; xform ->ExitColorSpace = ExitColorSpace; xform ->RenderingIntent = Intents[nProfiles-1]; - xform ->Lut = Lut; + // Create a gamut check LUT if requested if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK)) diff --git a/src/lcms2.def b/src/lcms2.def index 64240fe..828fcd2 100644 --- a/src/lcms2.def +++ b/src/lcms2.def @@ -62,11 +62,12 @@ _cmsDecodeDateTimeNumber = _cmsDecodeDateTimeNumber _cmsDefaultICCintents = _cmsDefaultICCintents cmsDeleteTransform = cmsDeleteTransform cmsDeltaE = cmsDeltaE -cmsDetectBlackPoint = cmsDetectBlackPoint +cmsDetectBlackPoint = cmsDetectBlackPoint cmsDetectDestinationBlackPoint = cmsDetectDestinationBlackPoint cmsDetectTAC = cmsDetectTAC cmsDesaturateLab = cmsDesaturateLab cmsDoTransform = cmsDoTransform +cmsDoTransformStride = cmsDoTransformStride _cmsDoubleTo15Fixed16 = _cmsDoubleTo15Fixed16 _cmsDoubleTo8Fixed8 = _cmsDoubleTo8Fixed8 _cmsDupMem = _cmsDupMem @@ -75,6 +76,8 @@ cmsDupProfileSequenceDescription = cmsDupProfileSequenceDescription cmsDupToneCurve = cmsDupToneCurve _cmsEncodeDateTimeNumber = _cmsEncodeDateTimeNumber cmsEstimateGamma = cmsEstimateGamma +cmsGetToneCurveEstimatedTableEntries = cmsGetToneCurveEstimatedTableEntries +cmsGetToneCurveEstimatedTable = cmsGetToneCurveEstimatedTable cmsEvalToneCurve16 = cmsEvalToneCurve16 cmsEvalToneCurveFloat = cmsEvalToneCurveFloat cmsfilelength = cmsfilelength @@ -111,12 +114,12 @@ cmsGetPostScriptCRD = cmsGetPostScriptCRD cmsGetPostScriptCSA = cmsGetPostScriptCSA cmsGetProfileInfo = cmsGetProfileInfo cmsGetProfileInfoASCII = cmsGetProfileInfoASCII -cmsGetProfileContextID = cmsGetProfileContextID +cmsGetProfileContextID = cmsGetProfileContextID cmsGetProfileVersion = cmsGetProfileVersion cmsGetSupportedIntents = cmsGetSupportedIntents cmsGetTagCount = cmsGetTagCount cmsGetTagSignature = cmsGetTagSignature -cmsGetTransformContextID = cmsGetTransformContextID +cmsGetTransformContextID = cmsGetTransformContextID _cmsICCcolorSpace = _cmsICCcolorSpace _cmsIOPrintf = _cmsIOPrintf cmsIsCLUT = cmsIsCLUT @@ -311,5 +314,6 @@ cmsDictDup = cmsDictDup cmsDictAddEntry = cmsDictAddEntry cmsDictGetEntryList = cmsDictGetEntryList cmsDictNextEntry = cmsDictNextEntry +_cmsGetTransformUserData = _cmsGetTransformUserData
\ No newline at end of file diff --git a/src/lcms2_internal.h b/src/lcms2_internal.h index 79dbc99..fb86d60 100644 --- a/src/lcms2_internal.h +++ b/src/lcms2_internal.h @@ -196,6 +196,8 @@ cmsBool _cmsRegisterMultiProcessElementPlugin(cmsPluginBase* Plugin); // Optimization cmsBool _cmsRegisterOptimizationPlugin(cmsPluginBase* Plugin); +// Transform +cmsBool _cmsRegisterTransformPlugin(cmsPluginBase* Plugin); // --------------------------------------------------------------------------------------------------------- @@ -387,37 +389,6 @@ struct _cmsStage_struct { struct _cmsStage_struct* Next; }; -// Data kept in "Element" member of cmsStage - -// Curves -typedef struct { - cmsUInt32Number nCurves; - cmsToneCurve** TheCurves; - -} _cmsStageToneCurvesData; - -// Matrix -typedef struct { - cmsFloat64Number* Double; // floating point for the matrix - cmsFloat64Number* Offset; // The offset - -} _cmsStageMatrixData; - -// CLUT -typedef struct { - - union { // Can have only one of both representations at same time - cmsUInt16Number* T; // Points to the table 16 bits table - cmsFloat32Number* TFloat; // Points to the cmsFloat32Number table - - } Tab; - - cmsInterpParams* Params; - cmsUInt32Number nEntries; - cmsBool HasFloatValues; - -} _cmsStageCLutData; - // Special Stages (cannot be saved) cmsStage* _cmsStageAllocLab2XYZ(cmsContext ContextID); @@ -544,18 +515,6 @@ typedef struct { } _cmsCACHE; -// Full xform -typedef void (* _cmsTransformFn)(struct _cmstransform_struct *Transform, - const void* InputBuffer, - void* OutputBuffer, - cmsUInt32Number Size); - -typedef struct { - - cmsUInt32Number InputFormat, OutputFormat; // Keep formats for further reference - cmsUInt32Number StrideIn, StrideOut; // Planar support - -} cmsFormatterInfo; // Transformation typedef struct _cmstransform_struct { @@ -575,10 +534,10 @@ typedef struct _cmstransform_struct { // 1-pixel cache seed for zero as input (16 bits, read only) _cmsCACHE Cache; - // A MPE LUT holding the full (optimized) transform + // A Pipeline holding the full (optimized) transform cmsPipeline* Lut; - // A MPE LUT holding the gamut check. It goes from the input space to bilevel + // A Pipeline holding the gamut check. It goes from the input space to bilevel cmsPipeline* GamutCheck; // Colorant tables @@ -601,6 +560,10 @@ typedef struct _cmstransform_struct { // An id that uniquely identifies the running context. May be null. cmsContext ContextID; + // A user-defined pointer that can be used to store data for transform plug-ins + void* UserData; + _cmsOPTfreeDataFn FreeUserData; + } _cmsTRANSFORM; // -------------------------------------------------------------------------------------------------- |