Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8260380: Upgrade to LittleCMS 2.12 #192

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter
Filter file types
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.

Always

Just for now

@@ -1,4 +1,4 @@
## Little Color Management System (LCMS) v2.11
## Little Color Management System (LCMS) v2.12

### LCMS License
<pre>
@@ -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
@@ -1525,21 +1525,30 @@ 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)
{
TABLE* t = GetTable(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++) {

@@ -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 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
return Result;
}



// Link routines ------------------------------------------------------------------------------------------------------

// Chain several profiles into a single LUT. It just checks the parameters and then calls the handler
ProTip! Use n and p to navigate between commits in a pull request.