summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarti Maria <info@littlecms.com>2012-05-19 17:07:51 +0200
committerMarti Maria <info@littlecms.com>2012-05-19 17:07:51 +0200
commit9fc6a31f69d199fe57593927890ef0cb227d5e37 (patch)
tree91571ef58c54c7a7cc6922591f7cd4d3d6b1789a /src
parentb6153c3b5b35db07243625933203566eb0b243fd (diff)
downloadlcms2-9fc6a31f69d199fe57593927890ef0cb227d5e37.tar.gz
Sync with development sources, See Change Log
Diffstat (limited to 'src')
-rw-r--r--src/cmscgats.c33
-rw-r--r--src/cmsgamma.c35
-rw-r--r--src/cmslut.c15
-rw-r--r--src/cmsopt.c10
-rw-r--r--src/cmspack.c81
-rw-r--r--src/cmsplugin.c5
-rw-r--r--src/cmssamp.c4
-rw-r--r--src/cmsvirt.c10
-rw-r--r--src/cmsxform.c183
-rw-r--r--src/lcms2.def10
-rw-r--r--src/lcms2_internal.h53
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;
// --------------------------------------------------------------------------------------------------