summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lcms2mt/src/cmscnvrt.c')
-rw-r--r--lcms2mt/src/cmscnvrt.c93
1 files changed, 79 insertions, 14 deletions
diff --git a/lcms2mt/src/cmscnvrt.c b/lcms2mt/src/cmscnvrt.c
index e3a2ddbc..64263696 100644
--- a/lcms2mt/src/cmscnvrt.c
+++ b/lcms2mt/src/cmscnvrt.c
@@ -731,6 +731,9 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
cmsUInt32Number ICCIntents[256];
cmsStage* CLUT;
cmsUInt32Number i, nGridPoints;
+ cmsUInt32Number lastProfilePos;
+ cmsUInt32Number preservationProfilesCount;
+ cmsHPROFILE hLastProfile;
// Sanity check
@@ -740,20 +743,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(ContextID, hLastProfile) != cmsSigCmykData ||
+ cmsGetDeviceClass(ContextID, hLastProfile) != cmsSigLinkClass)
+ break;
+ }
+
+ preservationProfilesCount = lastProfilePos + 1;
+
// Check for non-cmyk profiles
if (cmsGetColorSpace(ContextID, hProfiles[0]) != cmsSigCmykData ||
- cmsGetColorSpace(ContextID, hProfiles[nProfiles-1]) != cmsSigCmykData)
+ !(cmsGetColorSpace(ContextID, hLastProfile) == cmsSigCmykData ||
+ cmsGetDeviceClass(ContextID, 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,
@@ -765,7 +784,7 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
// Now, compute the tone curve
bp.KTone = _cmsBuildKToneCurve(ContextID,
4096,
- nProfiles,
+ preservationProfilesCount,
ICCIntents,
hProfiles,
BPC,
@@ -790,6 +809,19 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
if (!cmsStageSampleCLut16bit(ContextID, CLUT, BlackPreservingGrayOnlySampler, (void*) &bp, 0))
goto Error;
+
+ // Insert possible devicelinks at the end
+ for (i = lastProfilePos + 1; i < nProfiles; i++)
+ {
+ cmsPipeline* devlink = _cmsReadDevicelinkLUT(ContextID, hProfiles[i], ICCIntents[i]);
+ if (devlink == NULL)
+ goto Error;
+
+ if (!cmsPipelineCat(ContextID, Result, devlink))
+ goto Error;
+ }
+
+
// Get rid of xform and tone curve
cmsPipelineFree(ContextID, bp.cmyk2cmyk);
cmsFreeToneCurve(ContextID, bp.KTone);
@@ -908,6 +940,8 @@ int BlackPreservingSampler(cmsContext ContextID, CMSREGISTER const cmsUInt16Numb
return TRUE;
}
+
+
// This is the entry for black-plane preserving, which are non-ICC
static
cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
@@ -919,10 +953,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
@@ -932,32 +970,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(ContextID, hLastProfile) != cmsSigCmykData ||
+ cmsGetDeviceClass(ContextID, hLastProfile) != cmsSigLinkClass)
+ break;
+ }
+
+ preservationProfilesCount = lastProfilePos + 1;
+
// Check for non-cmyk profiles
if (cmsGetColorSpace(ContextID, hProfiles[0]) != cmsSigCmykData ||
- !(cmsGetColorSpace(ContextID, hProfiles[nProfiles-1]) == cmsSigCmykData ||
- cmsGetDeviceClass(ContextID, hProfiles[nProfiles-1]) == cmsSigOutputClass))
+ !(cmsGetColorSpace(ContextID, hLastProfile) == cmsSigCmykData ||
+ cmsGetDeviceClass(ContextID, 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(ContextID, hProfiles[nProfiles-1], INTENT_RELATIVE_COLORIMETRIC);
+ bp.LabK2cmyk = _cmsReadInputLUT(ContextID, hLastProfile, INTENT_RELATIVE_COLORIMETRIC);
if (bp.LabK2cmyk == NULL) goto Cleanup;
// Get total area coverage (in 0..1 domain)
- bp.MaxTAC = cmsDetectTAC(ContextID, hProfiles[nProfiles-1]) / 100.0;
+ bp.MaxTAC = cmsDetectTAC(ContextID, 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,
@@ -966,7 +1017,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,
@@ -976,14 +1027,14 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
// To measure the output, Last profile to Lab
hLab = cmsCreateLab4Profile(ContextID, NULL);
- bp.hProofOutput = cmsCreateTransform(ContextID, hProfiles[nProfiles-1],
+ bp.hProofOutput = cmsCreateTransform(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 = cmsCreateTransform(ContextID, hProfiles[nProfiles-1],
+ bp.cmyk2Lab = cmsCreateTransform(ContextID, hLastProfile,
FLOAT_SH(1)|CHANNELS_SH(4)|BYTES_SH(4), hLab,
FLOAT_SH(1)|CHANNELS_SH(3)|BYTES_SH(4),
INTENT_RELATIVE_COLORIMETRIC,
@@ -1006,6 +1057,18 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
cmsStageSampleCLut16bit(ContextID, CLUT, BlackPreservingSampler, (void*) &bp, 0);
+ // Insert possible devicelinks at the end
+ for (i = lastProfilePos + 1; i < nProfiles; i++)
+ {
+ cmsPipeline* devlink = _cmsReadDevicelinkLUT(ContextID, hProfiles[i], ICCIntents[i]);
+ if (devlink == NULL)
+ goto Cleanup;
+
+ if (!cmsPipelineCat(ContextID, Result, devlink))
+ goto Cleanup;
+ }
+
+
Cleanup:
if (bp.cmyk2cmyk) cmsPipelineFree(ContextID, bp.cmyk2cmyk);
@@ -1018,6 +1081,8 @@ Cleanup:
return Result;
}
+
+
// Link routines ------------------------------------------------------------------------------------------------------
// Chain several profiles into a single LUT. It just checks the parameters and then calls the handler