8260380: Upgrade to LittleCMS 2.12

Reviewed-by: phh, andrew
Backport-of: 4caeb39f01b13b5472d8dacb268262fd418fd0c4
This commit is contained in:
Sergey Bylokhov 2024-09-09 21:03:33 +00:00
parent 503ae0b063
commit cb95a72ec9
20 changed files with 431 additions and 468 deletions

View File

@ -1725,7 +1725,7 @@ THE SOFTWARE.
-------------------------------------------------------------------------------
%% This notice is provided with respect to Little CMS 2.11, which may be
%% This notice is provided with respect to Little CMS 2.12, which may be
included with JRE 8, JDK 8, and OpenJDK 8.
--- begin of LICENSE ---

View File

@ -104,7 +104,7 @@ static
void from8to16(void* dst, const void* src)
{
cmsUInt8Number n = *(cmsUInt8Number*)src;
*(cmsUInt16Number*) dst = FROM_8_TO_16(n);
*(cmsUInt16Number*) dst = (cmsUInt16Number) FROM_8_TO_16(n);
}
static
@ -117,13 +117,13 @@ void from8to16SE(void* dst, const void* src)
static
void from8toFLT(void* dst, const void* src)
{
*(cmsFloat32Number*)dst = (*(cmsUInt8Number*)src) / 255.0f;
*(cmsFloat32Number*)dst = (cmsFloat32Number) (*(cmsUInt8Number*)src) / 255.0f;
}
static
void from8toDBL(void* dst, const void* src)
{
*(cmsFloat64Number*)dst = (*(cmsUInt8Number*)src) / 255.0;
*(cmsFloat64Number*)dst = (cmsFloat64Number) (*(cmsUInt8Number*)src) / 255.0;
}
static
@ -182,13 +182,13 @@ void from16SEtoFLT(void* dst, const void* src)
static
void from16toDBL(void* dst, const void* src)
{
*(cmsFloat64Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f;
*(cmsFloat64Number*)dst = (cmsFloat64Number) (*(cmsUInt16Number*)src) / 65535.0;
}
static
void from16SEtoDBL(void* dst, const void* src)
{
*(cmsFloat64Number*)dst = (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0f;
*(cmsFloat64Number*)dst = (cmsFloat64Number) (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0;
}
static

View File

@ -1525,6 +1525,14 @@ cmsBool CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE h, int n, const char *Sample)
return SetDataFormat(it8, n, Sample);
}
// A safe atoi that returns 0 when NULL input is given
static
cmsInt32Number satoi(const char* b)
{
if (b == NULL) return 0;
return atoi(b);
}
static
void AllocateDataSet(cmsIT8* it8)
{
@ -1532,14 +1540,15 @@ void AllocateDataSet(cmsIT8* it8)
if (t -> Data) return; // Already allocated
t-> nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
t-> nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
t-> nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
t-> nPatches = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
if (t -> nSamples < 0 || t->nSamples > 0x7ffe || t->nPatches < 0 || t->nPatches > 0x7ffe)
{
SynError(it8, "AllocateDataSet: too much data");
}
else {
// Some dumb analizers warns of possible overflow here, just take a look couple of lines above.
t->Data = (char**)AllocChunk(it8, ((cmsUInt32Number)t->nSamples + 1) * ((cmsUInt32Number)t->nPatches + 1) * sizeof(char*));
if (t->Data == NULL) {
@ -1705,11 +1714,11 @@ void WriteHeader(cmsIT8* it8, SAVESTREAM* fp)
break;
case WRITE_HEXADECIMAL:
Writef(fp, "\t0x%X", atoi(p ->Value));
Writef(fp, "\t0x%X", satoi(p ->Value));
break;
case WRITE_BINARY:
Writef(fp, "\t0x%B", atoi(p ->Value));
Writef(fp, "\t0x%B", satoi(p ->Value));
break;
case WRITE_PAIR:
@ -1738,7 +1747,7 @@ void WriteDataFormat(SAVESTREAM* fp, cmsIT8* it8)
WriteStr(fp, "BEGIN_DATA_FORMAT\n");
WriteStr(fp, " ");
nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
for (i = 0; i < nSamples; i++) {
@ -1761,7 +1770,7 @@ void WriteData(SAVESTREAM* fp, cmsIT8* it8)
WriteStr (fp, "BEGIN_DATA\n");
t->nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
t->nPatches = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
for (i = 0; i < t-> nPatches; i++) {

View File

@ -759,6 +759,9 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
cmsUInt32Number ICCIntents[256];
cmsStage* CLUT;
cmsUInt32Number i, nGridPoints;
cmsUInt32Number lastProfilePos;
cmsUInt32Number preservationProfilesCount;
cmsHPROFILE hLastProfile;
// Sanity check
@ -768,20 +771,36 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
for (i=0; i < nProfiles; i++)
ICCIntents[i] = TranslateNonICCIntents(TheIntents[i]);
// Trim all CMYK devicelinks at the end
lastProfilePos = nProfiles - 1;
hLastProfile = hProfiles[lastProfilePos];
while (lastProfilePos > 1)
{
hLastProfile = hProfiles[--lastProfilePos];
if (cmsGetColorSpace(hLastProfile) != cmsSigCmykData ||
cmsGetDeviceClass(hLastProfile) != cmsSigLinkClass)
break;
}
preservationProfilesCount = lastProfilePos + 1;
// Check for non-cmyk profiles
if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData ||
cmsGetColorSpace(hProfiles[nProfiles-1]) != cmsSigCmykData)
!(cmsGetColorSpace(hLastProfile) == cmsSigCmykData ||
cmsGetDeviceClass(hLastProfile) == cmsSigOutputClass))
return DefaultICCintents(ContextID, nProfiles, ICCIntents, hProfiles, BPC, AdaptationStates, dwFlags);
memset(&bp, 0, sizeof(bp));
// Allocate an empty LUT for holding the result
Result = cmsPipelineAlloc(ContextID, 4, 4);
if (Result == NULL) return NULL;
memset(&bp, 0, sizeof(bp));
// Create a LUT holding normal ICC transform
bp.cmyk2cmyk = DefaultICCintents(ContextID,
nProfiles,
preservationProfilesCount,
ICCIntents,
hProfiles,
BPC,
@ -793,7 +812,7 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
// Now, compute the tone curve
bp.KTone = _cmsBuildKToneCurve(ContextID,
4096,
nProfiles,
preservationProfilesCount,
ICCIntents,
hProfiles,
BPC,
@ -818,6 +837,19 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
if (!cmsStageSampleCLut16bit(CLUT, BlackPreservingGrayOnlySampler, (void*) &bp, 0))
goto Error;
// Insert possible devicelinks at the end
for (i = lastProfilePos + 1; i < nProfiles; i++)
{
cmsPipeline* devlink = _cmsReadDevicelinkLUT(hProfiles[i], ICCIntents[i]);
if (devlink == NULL)
goto Error;
if (!cmsPipelineCat(Result, devlink))
goto Error;
}
// Get rid of xform and tone curve
cmsPipelineFree(bp.cmyk2cmyk);
cmsFreeToneCurve(bp.KTone);
@ -936,6 +968,8 @@ int BlackPreservingSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER c
return TRUE;
}
// This is the entry for black-plane preserving, which are non-ICC
static
cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
@ -947,10 +981,14 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
cmsUInt32Number dwFlags)
{
PreserveKPlaneParams bp;
cmsPipeline* Result = NULL;
cmsUInt32Number ICCIntents[256];
cmsStage* CLUT;
cmsUInt32Number i, nGridPoints;
cmsUInt32Number lastProfilePos;
cmsUInt32Number preservationProfilesCount;
cmsHPROFILE hLastProfile;
cmsHPROFILE hLab;
// Sanity check
@ -960,32 +998,45 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
for (i=0; i < nProfiles; i++)
ICCIntents[i] = TranslateNonICCIntents(TheIntents[i]);
// Trim all CMYK devicelinks at the end
lastProfilePos = nProfiles - 1;
hLastProfile = hProfiles[lastProfilePos];
while (lastProfilePos > 1)
{
hLastProfile = hProfiles[--lastProfilePos];
if (cmsGetColorSpace(hLastProfile) != cmsSigCmykData ||
cmsGetDeviceClass(hLastProfile) != cmsSigLinkClass)
break;
}
preservationProfilesCount = lastProfilePos + 1;
// Check for non-cmyk profiles
if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData ||
!(cmsGetColorSpace(hProfiles[nProfiles-1]) == cmsSigCmykData ||
cmsGetDeviceClass(hProfiles[nProfiles-1]) == cmsSigOutputClass))
!(cmsGetColorSpace(hLastProfile) == cmsSigCmykData ||
cmsGetDeviceClass(hLastProfile) == cmsSigOutputClass))
return DefaultICCintents(ContextID, nProfiles, ICCIntents, hProfiles, BPC, AdaptationStates, dwFlags);
// Allocate an empty LUT for holding the result
Result = cmsPipelineAlloc(ContextID, 4, 4);
if (Result == NULL) return NULL;
memset(&bp, 0, sizeof(bp));
// We need the input LUT of the last profile, assuming this one is responsible of
// black generation. This LUT will be searched in inverse order.
bp.LabK2cmyk = _cmsReadInputLUT(hProfiles[nProfiles-1], INTENT_RELATIVE_COLORIMETRIC);
bp.LabK2cmyk = _cmsReadInputLUT(hLastProfile, INTENT_RELATIVE_COLORIMETRIC);
if (bp.LabK2cmyk == NULL) goto Cleanup;
// Get total area coverage (in 0..1 domain)
bp.MaxTAC = cmsDetectTAC(hProfiles[nProfiles-1]) / 100.0;
bp.MaxTAC = cmsDetectTAC(hLastProfile) / 100.0;
if (bp.MaxTAC <= 0) goto Cleanup;
// Create a LUT holding normal ICC transform
bp.cmyk2cmyk = DefaultICCintents(ContextID,
nProfiles,
preservationProfilesCount,
ICCIntents,
hProfiles,
BPC,
@ -994,7 +1045,7 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
if (bp.cmyk2cmyk == NULL) goto Cleanup;
// Now the tone curve
bp.KTone = _cmsBuildKToneCurve(ContextID, 4096, nProfiles,
bp.KTone = _cmsBuildKToneCurve(ContextID, 4096, preservationProfilesCount,
ICCIntents,
hProfiles,
BPC,
@ -1004,14 +1055,14 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
// To measure the output, Last profile to Lab
hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
bp.hProofOutput = cmsCreateTransformTHR(ContextID, hProfiles[nProfiles-1],
bp.hProofOutput = cmsCreateTransformTHR(ContextID, hLastProfile,
CHANNELS_SH(4)|BYTES_SH(2), hLab, TYPE_Lab_DBL,
INTENT_RELATIVE_COLORIMETRIC,
cmsFLAGS_NOCACHE|cmsFLAGS_NOOPTIMIZE);
if ( bp.hProofOutput == NULL) goto Cleanup;
// Same as anterior, but lab in the 0..1 range
bp.cmyk2Lab = cmsCreateTransformTHR(ContextID, hProfiles[nProfiles-1],
bp.cmyk2Lab = cmsCreateTransformTHR(ContextID, hLastProfile,
FLOAT_SH(1)|CHANNELS_SH(4)|BYTES_SH(4), hLab,
FLOAT_SH(1)|CHANNELS_SH(3)|BYTES_SH(4),
INTENT_RELATIVE_COLORIMETRIC,
@ -1034,6 +1085,18 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
cmsStageSampleCLut16bit(CLUT, BlackPreservingSampler, (void*) &bp, 0);
// Insert possible devicelinks at the end
for (i = lastProfilePos + 1; i < nProfiles; i++)
{
cmsPipeline* devlink = _cmsReadDevicelinkLUT(hProfiles[i], ICCIntents[i]);
if (devlink == NULL)
goto Cleanup;
if (!cmsPipelineCat(Result, devlink))
goto Cleanup;
}
Cleanup:
if (bp.cmyk2cmyk) cmsPipelineFree(bp.cmyk2cmyk);
@ -1046,6 +1109,8 @@ Cleanup:
return Result;
}
// Link routines ------------------------------------------------------------------------------------------------------
// Chain several profiles into a single LUT. It just checks the parameters and then calls the handler

View File

@ -88,11 +88,11 @@ static cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFl
// The built-in list
static _cmsParametricCurvesCollection DefaultCurves = {
9, // # of curve types
{ 1, 2, 3, 4, 5, 6, 7, 8, 108 }, // Parametric curve ID
{ 1, 3, 4, 5, 7, 4, 5, 5, 1 }, // Parameters by type
DefaultEvalParametricFn, // Evaluator
NULL // Next in chain
10, // # of curve types
{ 1, 2, 3, 4, 5, 6, 7, 8, 108, 109 }, // Parametric curve ID
{ 1, 3, 4, 5, 7, 4, 5, 5, 1, 1 }, // Parameters by type
DefaultEvalParametricFn, // Evaluator
NULL // Next in chain
};
// Duplicates the zone of memory used by the plug-in in the new context
@ -338,6 +338,32 @@ Error:
}
// Generates a sigmoidal function with desired steepness.
cmsINLINE double sigmoid_base(double k, double t)
{
return (1.0 / (1.0 + exp(-k * t))) - 0.5;
}
cmsINLINE double inverted_sigmoid_base(double k, double t)
{
return -log((1.0 / (t + 0.5)) - 1.0) / k;
}
cmsINLINE double sigmoid_factory(double k, double t)
{
double correction = 0.5 / sigmoid_base(k, 1);
return correction * sigmoid_base(k, 2.0 * t - 1.0) + 0.5;
}
cmsINLINE double inverse_sigmoid_factory(double k, double t)
{
double correction = 0.5 / sigmoid_base(k, 1);
return (inverted_sigmoid_base(k, (t - 0.5) / correction) + 1.0) / 2.0;
}
// Parametric Fn using floating point
static
cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R)
@ -669,6 +695,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
}
break;
// S-Shaped: (1 - (1-x)^1/g)^1/g
case 108:
if (fabs(Params[0]) < MATRIX_DET_TOLERANCE)
@ -686,6 +713,15 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
Val = 1 - pow(1 - pow(R, Params[0]), Params[0]);
break;
// Sigmoidals
case 109:
Val = sigmoid_factory(Params[0], R);
break;
case -109:
Val = inverse_sigmoid_factory(Params[0], R);
break;
default:
// Unsupported parametric curve. Should never reach here
return 0;
@ -971,7 +1007,7 @@ cmsToneCurve* CMSEXPORT cmsJoinToneCurve(cmsContext ContextID,
//Iterate
for (i=0; i < nResultingPoints; i++) {
t = (cmsFloat32Number) i / (nResultingPoints-1);
t = (cmsFloat32Number) i / (cmsFloat32Number)(nResultingPoints-1);
x = cmsEvalToneCurveFloat(X, t);
Res[i] = cmsEvalToneCurveFloat(Yreversed, x);
}
@ -1185,6 +1221,7 @@ cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda
cmsBool SuccessStatus = TRUE;
cmsFloat32Number *w, *y, *z;
cmsUInt32Number i, nItems, Zeros, Poles;
cmsBool notCheck = FALSE;
if (Tab != NULL && Tab->InterpParams != NULL)
{
@ -1212,6 +1249,12 @@ cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda
w[i + 1] = 1.0;
}
if (lambda < 0)
{
notCheck = TRUE;
lambda = -lambda;
}
if (smooth2(ContextID, w, y, z, (cmsFloat32Number)lambda, (int)nItems))
{
// Do some reality - checking...
@ -1224,7 +1267,7 @@ cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda
if (z[i] < z[i - 1])
{
cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Non-Monotonic.");
SuccessStatus = FALSE;
SuccessStatus = notCheck;
break;
}
}
@ -1232,13 +1275,13 @@ cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda
if (SuccessStatus && Zeros > (nItems / 3))
{
cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly zeros.");
SuccessStatus = FALSE;
SuccessStatus = notCheck;
}
if (SuccessStatus && Poles > (nItems / 3))
{
cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly poles.");
SuccessStatus = FALSE;
SuccessStatus = notCheck;
}
if (SuccessStatus) // Seems ok

View File

@ -434,12 +434,13 @@ void BilinearInterp16(CMSREGISTER const cmsUInt16Number Input[],
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
int OutChan, TotalOut;
cmsS15Fixed16Number fx, fy;
CMSREGISTER int rx, ry;
int x0, y0;
CMSREGISTER int X0, X1, Y0, Y1;
int d00, d01, d10, d11,
dx0, dx1,
dxy;
CMSREGISTER int rx, ry;
int x0, y0;
CMSREGISTER int X0, X1, Y0, Y1;
int d00, d01, d10, d11,
dx0, dx1,
dxy;
TotalOut = p -> nOutputs;
@ -495,11 +496,12 @@ void TrilinearInterpFloat(const cmsFloat32Number Input[],
int x0, y0, z0,
X0, Y0, Z0, X1, Y1, Z1;
int TotalOut, OutChan;
cmsFloat32Number fx, fy, fz,
d000, d001, d010, d011,
d100, d101, d110, d111,
dx00, dx01, dx10, dx11,
dxy0, dxy1, dxyz;
d000, d001, d010, d011,
d100, d101, d110, d111,
dx00, dx01, dx10, dx11,
dxy0, dxy1, dxyz;
TotalOut = p -> nOutputs;
@ -565,13 +567,13 @@ void TrilinearInterp16(CMSREGISTER const cmsUInt16Number Input[],
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
int OutChan, TotalOut;
cmsS15Fixed16Number fx, fy, fz;
CMSREGISTER int rx, ry, rz;
int x0, y0, z0;
CMSREGISTER int X0, X1, Y0, Y1, Z0, Z1;
int d000, d001, d010, d011,
d100, d101, d110, d111,
dx00, dx01, dx10, dx11,
dxy0, dxy1, dxyz;
CMSREGISTER int rx, ry, rz;
int x0, y0, z0;
CMSREGISTER int X0, X1, Y0, Y1, Z0, Z1;
int d000, d001, d010, d011,
d100, d101, d110, d111,
dx00, dx01, dx10, dx11,
dxy0, dxy1, dxyz;
TotalOut = p -> nOutputs;
@ -639,8 +641,8 @@ void TetrahedralInterpFloat(const cmsFloat32Number Input[],
{
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
cmsFloat32Number px, py, pz;
int x0, y0, z0,
X0, Y0, Z0, X1, Y1, Z1;
int x0, y0, z0,
X0, Y0, Z0, X1, Y1, Z1;
cmsFloat32Number rx, ry, rz;
cmsFloat32Number c0, c1=0, c2=0, c3=0;
int OutChan, TotalOut;
@ -730,9 +732,6 @@ void TetrahedralInterpFloat(const cmsFloat32Number Input[],
#undef DENS
static CMS_NO_SANITIZE
void TetrahedralInterp16(CMSREGISTER const cmsUInt16Number Input[],
CMSREGISTER cmsUInt16Number Output[],
@ -743,7 +742,7 @@ void TetrahedralInterp16(CMSREGISTER const cmsUInt16Number Input[],
cmsS15Fixed16Number rx, ry, rz;
int x0, y0, z0;
cmsS15Fixed16Number c0, c1, c2, c3, Rest;
cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
cmsUInt32Number X0, X1, Y0, Y1, Z0, Z1;
cmsUInt32Number TotalOut = p -> nOutputs;
fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
@ -767,7 +766,7 @@ void TetrahedralInterp16(CMSREGISTER const cmsUInt16Number Input[],
Z0 = p -> opta[0] * z0;
Z1 = (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
LutTable = &LutTable[X0+Y0+Z0];
LutTable += X0+Y0+Z0;
// Output should be computed as x = ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))
// which expands as: x = (Rest + ((Rest+0x7fff)/0xFFFF) + 0x8000)>>16
@ -1051,8 +1050,6 @@ void Eval4Inputs(CMSREGISTER const cmsUInt16Number Input[],
// For more that 3 inputs (i.e., CMYK)
// evaluate two 3-dimensional interpolations and then linearly interpolate between them.
static
void Eval4InputsFloat(const cmsFloat32Number Input[],
cmsFloat32Number Output[],
@ -1095,351 +1092,102 @@ void Eval4InputsFloat(const cmsFloat32Number Input[],
}
}
static CMS_NO_SANITIZE
void Eval5Inputs(CMSREGISTER const cmsUInt16Number Input[],
CMSREGISTER cmsUInt16Number Output[],
CMSREGISTER const cmsInterpParams* p16)
{
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
cmsS15Fixed16Number fk;
cmsS15Fixed16Number k0, rk;
int K0, K1;
const cmsUInt16Number* T;
cmsUInt32Number i;
cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1;
fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
k0 = FIXED_TO_INT(fk);
rk = FIXED_REST_TO_INT(fk);
K0 = p16 -> opta[4] * k0;
K1 = p16 -> opta[4] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
p1 = *p16;
memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number));
T = LutTable + K0;
p1.Table = T;
Eval4Inputs(Input + 1, Tmp1, &p1);
T = LutTable + K1;
p1.Table = T;
Eval4Inputs(Input + 1, Tmp2, &p1);
for (i=0; i < p16 -> nOutputs; i++) {
Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
}
#define EVAL_FNS(N,NM) static CMS_NO_SANITIZE \
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
{\
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
cmsS15Fixed16Number fk;\
cmsS15Fixed16Number k0, rk;\
int K0, K1;\
const cmsUInt16Number* T;\
cmsUInt32Number i;\
cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
cmsInterpParams p1;\
\
fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
k0 = FIXED_TO_INT(fk);\
rk = FIXED_REST_TO_INT(fk);\
\
K0 = p16 -> opta[NM] * k0;\
K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
\
p1 = *p16;\
memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
\
T = LutTable + K0;\
p1.Table = T;\
\
Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
\
T = LutTable + K1;\
p1.Table = T;\
\
Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
\
for (i=0; i < p16 -> nOutputs; i++) {\
\
Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
}\
}\
\
static void Eval##N##InputsFloat(const cmsFloat32Number Input[], \
cmsFloat32Number Output[],\
const cmsInterpParams * p)\
{\
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;\
cmsFloat32Number rest;\
cmsFloat32Number pk;\
int k0, K0, K1;\
const cmsFloat32Number* T;\
cmsUInt32Number i;\
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
cmsInterpParams p1;\
\
pk = fclamp(Input[0]) * p->Domain[0];\
k0 = _cmsQuickFloor(pk);\
rest = pk - (cmsFloat32Number) k0;\
\
K0 = p -> opta[NM] * k0;\
K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[NM]);\
\
p1 = *p;\
memmove(&p1.Domain[0], &p ->Domain[1], NM*sizeof(cmsUInt32Number));\
\
T = LutTable + K0;\
p1.Table = T;\
\
Eval##NM##InputsFloat(Input + 1, Tmp1, &p1);\
\
T = LutTable + K1;\
p1.Table = T;\
\
Eval##NM##InputsFloat(Input + 1, Tmp2, &p1);\
\
for (i=0; i < p -> nOutputs; i++) {\
\
cmsFloat32Number y0 = Tmp1[i];\
cmsFloat32Number y1 = Tmp2[i];\
\
Output[i] = y0 + (y1 - y0) * rest;\
}\
}
static
void Eval5InputsFloat(const cmsFloat32Number Input[],
cmsFloat32Number Output[],
const cmsInterpParams* p)
{
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
cmsFloat32Number rest;
cmsFloat32Number pk;
int k0, K0, K1;
const cmsFloat32Number* T;
cmsUInt32Number i;
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1;
/**
* Thanks to Carles Llopis for the templating idea
*/
EVAL_FNS(5, 4)
EVAL_FNS(6, 5)
EVAL_FNS(7, 6)
EVAL_FNS(8, 7)
EVAL_FNS(9, 8)
EVAL_FNS(10, 9)
EVAL_FNS(11, 10)
EVAL_FNS(12, 11)
EVAL_FNS(13, 12)
EVAL_FNS(14, 13)
EVAL_FNS(15, 14)
pk = fclamp(Input[0]) * p->Domain[0];
k0 = _cmsQuickFloor(pk);
rest = pk - (cmsFloat32Number) k0;
K0 = p -> opta[4] * k0;
K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[4]);
p1 = *p;
memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
T = LutTable + K0;
p1.Table = T;
Eval4InputsFloat(Input + 1, Tmp1, &p1);
T = LutTable + K1;
p1.Table = T;
Eval4InputsFloat(Input + 1, Tmp2, &p1);
for (i=0; i < p -> nOutputs; i++) {
cmsFloat32Number y0 = Tmp1[i];
cmsFloat32Number y1 = Tmp2[i];
Output[i] = y0 + (y1 - y0) * rest;
}
}
static CMS_NO_SANITIZE
void Eval6Inputs(CMSREGISTER const cmsUInt16Number Input[],
CMSREGISTER cmsUInt16Number Output[],
CMSREGISTER const cmsInterpParams* p16)
{
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
cmsS15Fixed16Number fk;
cmsS15Fixed16Number k0, rk;
int K0, K1;
const cmsUInt16Number* T;
cmsUInt32Number i;
cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1;
fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
k0 = FIXED_TO_INT(fk);
rk = FIXED_REST_TO_INT(fk);
K0 = p16 -> opta[5] * k0;
K1 = p16 -> opta[5] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
p1 = *p16;
memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
T = LutTable + K0;
p1.Table = T;
Eval5Inputs(Input + 1, Tmp1, &p1);
T = LutTable + K1;
p1.Table = T;
Eval5Inputs(Input + 1, Tmp2, &p1);
for (i=0; i < p16 -> nOutputs; i++) {
Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
}
}
static
void Eval6InputsFloat(const cmsFloat32Number Input[],
cmsFloat32Number Output[],
const cmsInterpParams* p)
{
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
cmsFloat32Number rest;
cmsFloat32Number pk;
int k0, K0, K1;
const cmsFloat32Number* T;
cmsUInt32Number i;
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1;
pk = fclamp(Input[0]) * p->Domain[0];
k0 = _cmsQuickFloor(pk);
rest = pk - (cmsFloat32Number) k0;
K0 = p -> opta[5] * k0;
K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[5]);
p1 = *p;
memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
T = LutTable + K0;
p1.Table = T;
Eval5InputsFloat(Input + 1, Tmp1, &p1);
T = LutTable + K1;
p1.Table = T;
Eval5InputsFloat(Input + 1, Tmp2, &p1);
for (i=0; i < p -> nOutputs; i++) {
cmsFloat32Number y0 = Tmp1[i];
cmsFloat32Number y1 = Tmp2[i];
Output[i] = y0 + (y1 - y0) * rest;
}
}
static CMS_NO_SANITIZE
void Eval7Inputs(CMSREGISTER const cmsUInt16Number Input[],
CMSREGISTER cmsUInt16Number Output[],
CMSREGISTER const cmsInterpParams* p16)
{
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
cmsS15Fixed16Number fk;
cmsS15Fixed16Number k0, rk;
int K0, K1;
const cmsUInt16Number* T;
cmsUInt32Number i;
cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1;
fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
k0 = FIXED_TO_INT(fk);
rk = FIXED_REST_TO_INT(fk);
K0 = p16 -> opta[6] * k0;
K1 = p16 -> opta[6] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
p1 = *p16;
memmove(&p1.Domain[0], &p16 ->Domain[1], 6*sizeof(cmsUInt32Number));
T = LutTable + K0;
p1.Table = T;
Eval6Inputs(Input + 1, Tmp1, &p1);
T = LutTable + K1;
p1.Table = T;
Eval6Inputs(Input + 1, Tmp2, &p1);
for (i=0; i < p16 -> nOutputs; i++) {
Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
}
}
static
void Eval7InputsFloat(const cmsFloat32Number Input[],
cmsFloat32Number Output[],
const cmsInterpParams* p)
{
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
cmsFloat32Number rest;
cmsFloat32Number pk;
int k0, K0, K1;
const cmsFloat32Number* T;
cmsUInt32Number i;
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1;
pk = fclamp(Input[0]) * p->Domain[0];
k0 = _cmsQuickFloor(pk);
rest = pk - (cmsFloat32Number) k0;
K0 = p -> opta[6] * k0;
K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[6]);
p1 = *p;
memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
T = LutTable + K0;
p1.Table = T;
Eval6InputsFloat(Input + 1, Tmp1, &p1);
T = LutTable + K1;
p1.Table = T;
Eval6InputsFloat(Input + 1, Tmp2, &p1);
for (i=0; i < p -> nOutputs; i++) {
cmsFloat32Number y0 = Tmp1[i];
cmsFloat32Number y1 = Tmp2[i];
Output[i] = y0 + (y1 - y0) * rest;
}
}
static CMS_NO_SANITIZE
void Eval8Inputs(CMSREGISTER const cmsUInt16Number Input[],
CMSREGISTER cmsUInt16Number Output[],
CMSREGISTER const cmsInterpParams* p16)
{
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
cmsS15Fixed16Number fk;
cmsS15Fixed16Number k0, rk;
int K0, K1;
const cmsUInt16Number* T;
cmsUInt32Number i;
cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1;
fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
k0 = FIXED_TO_INT(fk);
rk = FIXED_REST_TO_INT(fk);
K0 = p16 -> opta[7] * k0;
K1 = p16 -> opta[7] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
p1 = *p16;
memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number));
T = LutTable + K0;
p1.Table = T;
Eval7Inputs(Input + 1, Tmp1, &p1);
T = LutTable + K1;
p1.Table = T;
Eval7Inputs(Input + 1, Tmp2, &p1);
for (i=0; i < p16 -> nOutputs; i++) {
Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
}
}
static
void Eval8InputsFloat(const cmsFloat32Number Input[],
cmsFloat32Number Output[],
const cmsInterpParams* p)
{
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
cmsFloat32Number rest;
cmsFloat32Number pk;
int k0, K0, K1;
const cmsFloat32Number* T;
cmsUInt32Number i;
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1;
pk = fclamp(Input[0]) * p->Domain[0];
k0 = _cmsQuickFloor(pk);
rest = pk - (cmsFloat32Number) k0;
K0 = p -> opta[7] * k0;
K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[7]);
p1 = *p;
memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
T = LutTable + K0;
p1.Table = T;
Eval7InputsFloat(Input + 1, Tmp1, &p1);
T = LutTable + K1;
p1.Table = T;
Eval7InputsFloat(Input + 1, Tmp2, &p1);
for (i=0; i < p -> nOutputs; i++) {
cmsFloat32Number y0 = Tmp1[i];
cmsFloat32Number y1 = Tmp2[i];
Output[i] = y0 + (y1 - y0) * rest;
}
}
// The default factory
static
@ -1540,6 +1288,53 @@ cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cm
Interpolation.Lerp16 = Eval8Inputs;
break;
case 9:
if (IsFloat)
Interpolation.LerpFloat = Eval9InputsFloat;
else
Interpolation.Lerp16 = Eval9Inputs;
break;
case 10:
if (IsFloat)
Interpolation.LerpFloat = Eval10InputsFloat;
else
Interpolation.Lerp16 = Eval10Inputs;
break;
case 11:
if (IsFloat)
Interpolation.LerpFloat = Eval11InputsFloat;
else
Interpolation.Lerp16 = Eval11Inputs;
break;
case 12:
if (IsFloat)
Interpolation.LerpFloat = Eval12InputsFloat;
else
Interpolation.Lerp16 = Eval12Inputs;
break;
case 13:
if (IsFloat)
Interpolation.LerpFloat = Eval13InputsFloat;
else
Interpolation.Lerp16 = Eval13Inputs;
break;
case 14:
if (IsFloat)
Interpolation.LerpFloat = Eval14InputsFloat;
else
Interpolation.Lerp16 = Eval14Inputs;
break;
case 15:
if (IsFloat)
Interpolation.LerpFloat = Eval15InputsFloat;
else
Interpolation.Lerp16 = Eval15Inputs;
break;
default:

View File

@ -290,7 +290,7 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buff
_cmsFree(ContextID, fm);
_cmsFree(ContextID, iohandler);
cmsSignalError(ContextID, cmsERROR_READ, "Couldn't allocate %ld bytes for profile", size);
cmsSignalError(ContextID, cmsERROR_READ, "Couldn't allocate %ld bytes for profile", (long) size);
return NULL;
}
@ -1232,25 +1232,28 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig)
// In this case a blind copy of the block data is performed
if (FileOrig != NULL && Icc -> TagOffsets[i]) {
cmsUInt32Number TagSize = FileOrig -> TagSizes[i];
cmsUInt32Number TagOffset = FileOrig -> TagOffsets[i];
void* Mem;
if (FileOrig->IOhandler != NULL)
{
cmsUInt32Number TagSize = FileOrig->TagSizes[i];
cmsUInt32Number TagOffset = FileOrig->TagOffsets[i];
void* Mem;
if (!FileOrig ->IOhandler->Seek(FileOrig ->IOhandler, TagOffset)) return FALSE;
if (!FileOrig->IOhandler->Seek(FileOrig->IOhandler, TagOffset)) return FALSE;
Mem = _cmsMalloc(Icc ->ContextID, TagSize);
if (Mem == NULL) return FALSE;
Mem = _cmsMalloc(Icc->ContextID, TagSize);
if (Mem == NULL) return FALSE;
if (FileOrig ->IOhandler->Read(FileOrig->IOhandler, Mem, TagSize, 1) != 1) return FALSE;
if (!io ->Write(io, TagSize, Mem)) return FALSE;
_cmsFree(Icc ->ContextID, Mem);
if (FileOrig->IOhandler->Read(FileOrig->IOhandler, Mem, TagSize, 1) != 1) return FALSE;
if (!io->Write(io, TagSize, Mem)) return FALSE;
_cmsFree(Icc->ContextID, Mem);
Icc -> TagSizes[i] = (io ->UsedSpace - Begin);
Icc->TagSizes[i] = (io->UsedSpace - Begin);
// Align to 32 bit boundary.
if (! _cmsWriteAlignment(io))
return FALSE;
// Align to 32 bit boundary.
if (!_cmsWriteAlignment(io))
return FALSE;
}
}
continue;

View File

@ -1366,7 +1366,7 @@ void _LUTeval16(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Num
// Does evaluate the LUT on cmsFloat32Number-basis.
static
void _LUTevalFloat(CMSREGISTER const cmsFloat32Number In[], CMSREGISTER cmsFloat32Number Out[], const void* D)
void _LUTevalFloat(const cmsFloat32Number In[], cmsFloat32Number Out[], const void* D)
{
cmsPipeline* lut = (cmsPipeline*) D;
cmsStage *mpe;
@ -1687,7 +1687,7 @@ cmsUInt32Number CMSEXPORT cmsPipelineStageCount(const cmsPipeline* lut)
// This function may be used to set the optional evaluator and a block of private data. If private data is being used, an optional
// duplicator and free functions should also be specified in order to duplicate the LUT construct. Use NULL to inhibit such functionality.
void CMSEXPORT _cmsPipelineSetOptimizationParameters(cmsPipeline* Lut,
_cmsOPTeval16Fn Eval16,
_cmsPipelineEval16Fn Eval16,
void* PrivateData,
_cmsFreeUserDataFn FreePrivateDataFn,
_cmsDupUserDataFn DupPrivateDataFn)

View File

@ -209,12 +209,16 @@ cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block,
// Convert from a 3-char code to a cmsUInt16Number. It is done in this way because some
// compilers don't properly align beginning of strings
static
cmsUInt16Number strTo16(const char str[3])
{
const cmsUInt8Number* ptr8 = (const cmsUInt8Number*)str;
cmsUInt16Number n = (cmsUInt16Number)(((cmsUInt16Number)ptr8[0] << 8) | ptr8[1]);
const cmsUInt8Number* ptr8;
cmsUInt16Number n;
// For non-existent strings
if (str == NULL) return 0;
ptr8 = (const cmsUInt8Number*)str;
n = (cmsUInt16Number)(((cmsUInt16Number)ptr8[0] << 8) | ptr8[1]);
return n;
}
@ -229,6 +233,7 @@ void strFrom16(char str[3], cmsUInt16Number n)
}
// Add an ASCII entry. Do not add any \0 termination (ICC1v43_2010-12.pdf page 61)
// In the case the user explicitely sets an empty string, we force a \0
cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* ASCIIString)
{
cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString);
@ -239,6 +244,12 @@ cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const
if (mlu == NULL) return FALSE;
// len == 0 would prevent operation, so we set a empty string pointing to zero
if (len == 0)
{
len = 1;
}
WStr = (wchar_t*) _cmsCalloc(mlu ->ContextID, len, sizeof(wchar_t));
if (WStr == NULL) return FALSE;
@ -276,6 +287,9 @@ cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char
if (WideString == NULL) return FALSE;
len = (cmsUInt32Number) (mywcslen(WideString)) * sizeof(wchar_t);
if (len == 0)
len = sizeof(wchar_t);
return AddMLUBlock(mlu, len, WideString, Lang, Cntry);
}

View File

@ -408,7 +408,20 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID,
p16 -> EvalCurveOut16 = (_cmsInterpFn16*) _cmsCalloc(ContextID, nOutputs, sizeof(_cmsInterpFn16));
if (p16->EvalCurveOut16 == NULL)
{
_cmsFree(ContextID, p16);
return NULL;
}
p16 -> ParamsCurveOut16 = (cmsInterpParams**) _cmsCalloc(ContextID, nOutputs, sizeof(cmsInterpParams* ));
if (p16->ParamsCurveOut16 == NULL)
{
_cmsFree(ContextID, p16->EvalCurveOut16);
_cmsFree(ContextID, p16);
return NULL;
}
for (i=0; i < nOutputs; i++) {
@ -435,7 +448,9 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID,
// Sampler implemented by another LUT. This is a clean way to precalculate the devicelink 3D CLUT for
// almost any transform. We use floating point precision and then convert from floating point to 16 bits.
static
cmsInt32Number XFormSampler16(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Number Out[], CMSREGISTER void* Cargo)
cmsInt32Number XFormSampler16(CMSREGISTER const cmsUInt16Number In[],
CMSREGISTER cmsUInt16Number Out[],
CMSREGISTER void* Cargo)
{
cmsPipeline* Lut = (cmsPipeline*) Cargo;
cmsFloat32Number InFloat[cmsMAXCHANNELS], OutFloat[cmsMAXCHANNELS];
@ -794,7 +809,7 @@ Error:
if (DataSetIn == NULL && DataSetOut == NULL) {
_cmsPipelineSetOptimizationParameters(Dest, (_cmsOPTeval16Fn) DataCLUT->Params->Interpolation.Lerp16, DataCLUT->Params, NULL, NULL);
_cmsPipelineSetOptimizationParameters(Dest, (_cmsPipelineEval16Fn) DataCLUT->Params->Interpolation.Lerp16, DataCLUT->Params, NULL, NULL);
}
else {
@ -939,8 +954,8 @@ void* Prelin8dup(cmsContext ContextID, const void* ptr)
#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
static CMS_NO_SANITIZE
void PrelinEval8(CMSREGISTER const cmsUInt16Number Input[],
CMSREGISTER cmsUInt16Number Output[],
CMSREGISTER const void* D)
CMSREGISTER cmsUInt16Number Output[],
CMSREGISTER const void* D)
{
cmsUInt8Number r, g, b;
@ -957,9 +972,9 @@ void PrelinEval8(CMSREGISTER const cmsUInt16Number Input[],
g = (cmsUInt8Number) (Input[1] >> 8);
b = (cmsUInt8Number) (Input[2] >> 8);
X0 = X1 = (cmsS15Fixed16Number) p8->X0[r];
Y0 = Y1 = (cmsS15Fixed16Number) p8->Y0[g];
Z0 = Z1 = (cmsS15Fixed16Number) p8->Z0[b];
X0 = (cmsS15Fixed16Number) p8->X0[r];
Y0 = (cmsS15Fixed16Number) p8->Y0[g];
Z0 = (cmsS15Fixed16Number) p8->Z0[b];
rx = p8 ->rx[r];
ry = p8 ->ry[g];
@ -1361,8 +1376,8 @@ Curves16Data* CurvesAlloc(cmsContext ContextID, cmsUInt32Number nCurves, cmsUInt
static
void FastEvaluateCurves8(CMSREGISTER const cmsUInt16Number In[],
CMSREGISTER cmsUInt16Number Out[],
CMSREGISTER const void* D)
CMSREGISTER cmsUInt16Number Out[],
CMSREGISTER const void* D)
{
Curves16Data* Data = (Curves16Data*) D;
int x;
@ -1922,7 +1937,7 @@ cmsBool _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Dat
}
// The entry point for LUT optimization
cmsBool _cmsOptimizePipeline(cmsContext ContextID,
cmsBool CMSEXPORT _cmsOptimizePipeline(cmsContext ContextID,
cmsPipeline** PtrLut,
cmsUInt32Number Intent,
cmsUInt32Number* InputFormat,

View File

@ -2836,7 +2836,7 @@ cmsUInt8Number* UnrollHalfTo16(CMSREGISTER _cmsTRANSFORM* info,
if (Reverse) v = maximum - v;
wIn[index] = _cmsQuickSaturateWord(v * maximum);
wIn[index] = _cmsQuickSaturateWord((cmsFloat64Number) v * maximum);
}

View File

@ -685,7 +685,7 @@ cmsFloat64Number CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIEL
// This function returns a number of gridpoints to be used as LUT table. It assumes same number
// of gripdpoints in all dimensions. Flags may override the choice.
cmsUInt32Number _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags)
cmsUInt32Number CMSEXPORT _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags)
{
cmsUInt32Number nChannels;

View File

@ -527,6 +527,7 @@ cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...)
int len;
cmsUInt8Number Buffer[2048];
cmsBool rc;
cmsUInt8Number* ptr;
_cmsAssert(io != NULL);
_cmsAssert(frm != NULL);
@ -539,6 +540,13 @@ cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...)
return FALSE; // Truncated, which is a fatal error for us
}
// setlocale may be active, no commas are needed in PS generator
// and PS generator is our only client
for (ptr = Buffer; *ptr; ptr++)
{
if (*ptr == ',') *ptr = '.';
}
rc = io ->Write(io, (cmsUInt32Number) len, Buffer);
va_end(args);

View File

@ -558,9 +558,10 @@ void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table, const char* name)
// Compare gamma table
static
cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, cmsUInt32Number nEntries)
cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, cmsUInt32Number nG1, cmsUInt32Number nG2)
{
return memcmp(g1, g2, nEntries* sizeof(cmsUInt16Number)) == 0;
if (nG1 != nG2) return FALSE;
return memcmp(g1, g2, nG1 * sizeof(cmsUInt16Number)) == 0;
}
@ -576,12 +577,12 @@ void EmitNGamma(cmsIOHANDLER* m, cmsUInt32Number n, cmsToneCurve* g[], const cha
{
if (g[i] == NULL) return; // Error
if (i > 0 && GammaTableEquals(g[i-1]->Table16, g[i]->Table16, g[i]->nEntries)) {
if (i > 0 && GammaTableEquals(g[i-1]->Table16, g[i]->Table16, g[i-1]->nEntries, g[i]->nEntries)) {
_cmsIOPrintf(m, "/%s%d /%s%d load def\n", nameprefix, i, nameprefix, i-1);
}
else {
snprintf(buffer, sizeof(buffer), "%s%d", nameprefix, i);
snprintf(buffer, sizeof(buffer), "%s%d", nameprefix, (int) i);
buffer[sizeof(buffer)-1] = '\0';
Emit1Gamma(m, g[i], buffer);
}
@ -836,7 +837,7 @@ int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, cmsUInt32Number Inte
if (cmsStageType(mpe) == cmsSigCurveSetElemType) {
numchans = cmsStageOutputChannels(mpe);
numchans = (int) cmsStageOutputChannels(mpe);
for (i = 0; i < numchans; ++i) {
snprintf(buffer, sizeof(buffer), "lcms2gammaproc%d", i);
buffer[sizeof(buffer) - 1] = '\0';

View File

@ -112,10 +112,10 @@ cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput,
return FALSE;
}
// Create a formatter which has n channels and floating point
// Create a formatter which has n channels and no floating point
dwFormat = cmsFormatterForColorspaceOfProfile(hInput, 2, FALSE);
// Try to get black by using black colorant
// Try to get black by using black colorant
Space = cmsGetColorSpace(hInput);
// This function returns darker colorant in 16 bits for several spaces

View File

@ -1895,6 +1895,7 @@ cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
mpe = NewLUT -> Elements;
if (mpe ->Type == cmsSigMatrixElemType) {
if (mpe->InputChannels != 3 || mpe->OutputChannels != 3) return FALSE;
MatMPE = (_cmsStageMatrixData*) mpe ->Data;
mpe = mpe -> Next;
}
@ -1920,7 +1921,6 @@ cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
return FALSE;
}
if (clut == NULL)
clutPoints = 0;
else
@ -1935,15 +1935,13 @@ cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
if (MatMPE != NULL) {
for (i = 0; i < n; i++)
for (i = 0; i < 9; i++)
{
if (!_cmsWrite15Fixed16Number(io, MatMPE->Double[i])) return FALSE;
}
}
else {
if (n != 9) return FALSE;
if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
@ -3029,6 +3027,9 @@ void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER
}
List = cmsAllocNamedColorList(self ->ContextID, Count, 0, "", "");
if (List == NULL)
return NULL;
for (i=0; i < Count; i++) {
if (io ->Read(io, Name, 32, 1) != 1) goto Error;

View File

@ -302,7 +302,7 @@ void FloatXFORM(_cmsTRANSFORM* p,
strideIn = 0;
strideOut = 0;
memset(fIn, 0, sizeof(fIn));
memset(fOut, 0, sizeof(fIn));
memset(fOut, 0, sizeof(fOut));
for (i = 0; i < LineCount; i++) {
@ -476,7 +476,7 @@ void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p,
p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data);
if (wOutOfGamut >= 1) {
cmsUInt16Number i;
cmsUInt32Number i;
_cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext);
for (i=0; i < p ->Lut->OutputChannels; i++) {
@ -803,6 +803,12 @@ void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMc
if (ToOutput) *ToOutput = CMMcargo ->ToOutputFloat;
}
// returns original flags
cmsUInt32Number CMSEXPORT _cmsGetTransformFlags(struct _cmstransform_struct* CMMcargo)
{
_cmsAssert(CMMcargo != NULL);
return CMMcargo->dwOriginalFlags;
}
// 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,

View File

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2020 Marti Maria Saguer
// Copyright (c) 1998-2021 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"),
@ -52,7 +52,7 @@
//
//---------------------------------------------------------------------------------
//
// Version 2.11
// Version 2.12
//
#ifndef _lcms2_H
@ -110,7 +110,7 @@ extern "C" {
#endif
// Version/release
#define LCMS_VERSION 2100
#define LCMS_VERSION 2120
// I will give the chance of redefining basic types for compilers that are not fully C99 compliant
#ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
@ -1299,7 +1299,7 @@ typedef cmsInt32Number (* cmsSAMPLERFLOAT)(CMSREGISTER const cmsFloat32Number In
#define SAMPLER_INSPECT 0x01000000
// For CLUT only
CMSAPI cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, void* Cargo, cmsUInt32Number dwFlags);
CMSAPI cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, void* Cargo, cmsUInt32Number dwFlags);
CMSAPI cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler, void* Cargo, cmsUInt32Number dwFlags);
// Slicers

View File

@ -27,7 +27,7 @@
// However, the following notice accompanied the original version of this
// file:
//
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2020 Marti Maria Saguer
@ -937,13 +937,7 @@ cmsStage* _cmsStageClipNegatives(cmsContext ContextID,
// For curve set only
cmsToneCurve** _cmsStageGetPtrToCurveSet(const cmsStage* mpe);
// Pipeline Evaluator (in floating point)
typedef void (* _cmsPipelineEvalFloatFn)(const cmsFloat32Number In[],
cmsFloat32Number Out[],
const void* Data);
cmsToneCurve** _cmsStageGetPtrToCurveSet(const cmsStage* mpe);
struct _cmsPipeline_struct {
@ -953,7 +947,7 @@ struct _cmsPipeline_struct {
// Data & evaluators
void *Data;
_cmsOPTeval16Fn Eval16Fn;
_cmsPipelineEval16Fn Eval16Fn;
_cmsPipelineEvalFloatFn EvalFloatFn;
_cmsFreeUserDataFn FreeDataFn;
_cmsDupUserDataFn DupDataFn;
@ -1000,14 +994,14 @@ cmsSEQ* _cmsCompileProfileSequence(cmsContext ContextID, cmsUInt32Number nProfil
CMSCHECKPOINT cmsUInt16Number CMSEXPORT _cmsQuantizeVal(cmsFloat64Number i, cmsUInt32Number MaxSamples);
cmsUInt32Number _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags);
CMSAPI cmsUInt32Number CMSEXPORT _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags);
cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
cmsUInt16Number **White,
cmsUInt16Number **Black,
cmsUInt32Number *nOutputs);
cmsBool _cmsOptimizePipeline(cmsContext ContextID,
CMSAPI cmsBool CMSEXPORT _cmsOptimizePipeline(cmsContext ContextID,
cmsPipeline** Lut,
cmsUInt32Number Intent,
cmsUInt32Number* InputFormat,

View File

@ -315,7 +315,7 @@ typedef union {
#define CMS_LERP_FLAGS_TRILINEAR 0x0100 // Hint only
#define MAX_INPUT_DIMENSIONS 8
#define MAX_INPUT_DIMENSIONS 15
typedef struct _cms_interp_struc { // Used on all interpolations. Supplied by lcms2 when calling the interpolation function
@ -576,22 +576,28 @@ typedef struct {
// the optimization search. Or FALSE if it is unable to optimize and want to give a chance
// to the rest of optimizers.
typedef void (* _cmsOPTeval16Fn)(CMSREGISTER const cmsUInt16Number In[],
CMSREGISTER cmsUInt16Number Out[],
CMSREGISTER const void* Data);
typedef cmsBool (* _cmsOPToptimizeFn)(cmsPipeline** Lut,
cmsUInt32Number Intent,
cmsUInt32Number* InputFormat,
cmsUInt32Number* OutputFormat,
cmsUInt32Number* dwFlags);
// Pipeline Evaluator (in 16 bits)
typedef void (* _cmsPipelineEval16Fn)(CMSREGISTER const cmsUInt16Number In[],
CMSREGISTER cmsUInt16Number Out[],
const void* Data);
// Pipeline Evaluator (in floating point)
typedef void (* _cmsPipelineEvalFloatFn)(const cmsFloat32Number In[],
cmsFloat32Number Out[],
const void* Data);
// This function may be used to set the optional evaluator and a block of private data. If private data is being used, an optional
// duplicator and free functions should also be specified in order to duplicate the LUT construct. Use NULL to inhibit such functionality.
CMSAPI void CMSEXPORT _cmsPipelineSetOptimizationParameters(cmsPipeline* Lut,
_cmsOPTeval16Fn Eval16,
_cmsPipelineEval16Fn Eval16,
void* PrivateData,
_cmsFreeUserDataFn FreePrivateDataFn,
_cmsDupUserDataFn DupPrivateDataFn);
@ -655,6 +661,9 @@ CMSAPI void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CM
CMSAPI void CMSEXPORT _cmsGetTransformFormatters16 (struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput);
CMSAPI void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput);
// Retrieve original flags
CMSAPI cmsUInt32Number CMSEXPORT _cmsGetTransformFlags(struct _cmstransform_struct* CMMcargo);
typedef struct {
cmsPluginBase base;