Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
8260380: Upgrade to LittleCMS 2.12
Backport-of: 4caeb39f01b13b5472d8dacb268262fd418fd0c4
  • Loading branch information
Dmitry Cherepanov committed May 4, 2021
1 parent acf2eea commit 547c798
Show file tree
Hide file tree
Showing 20 changed files with 431 additions and 468 deletions.
2 changes: 1 addition & 1 deletion src/java.desktop/share/legal/lcms.md
@@ -1,4 +1,4 @@
## Little Color Management System (LCMS) v2.11
## Little Color Management System (LCMS) v2.12

### LCMS License
<pre>
Expand Down
10 changes: 5 additions & 5 deletions src/java.desktop/share/native/liblcms/cmsalpha.c
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
21 changes: 15 additions & 6 deletions src/java.desktop/share/native/liblcms/cmscgats.c
Expand Up @@ -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) {

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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++) {

Expand All @@ -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++) {

Expand Down
93 changes: 79 additions & 14 deletions src/java.desktop/share/native/liblcms/cmscnvrt.c
Expand Up @@ -759,6 +759,9 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
cmsUInt32Number ICCIntents[256];
cmsStage* CLUT;
cmsUInt32Number i, nGridPoints;
cmsUInt32Number lastProfilePos;
cmsUInt32Number preservationProfilesCount;
cmsHPROFILE hLastProfile;


// Sanity check
Expand All @@ -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,
Expand All @@ -793,7 +812,7 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
// Now, compute the tone curve
bp.KTone = _cmsBuildKToneCurve(ContextID,
4096,
nProfiles,
preservationProfilesCount,
ICCIntents,
hProfiles,
BPC,
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -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
Expand Down

1 comment on commit 547c798

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.