diff options
Diffstat (limited to 'lcms2mt/src/cmscnvrt.c')
-rw-r--r-- | lcms2mt/src/cmscnvrt.c | 93 |
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 |