// Does convert a transform into a device link profile cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags) { cmsHPROFILE hProfile = NULL; cmsUInt32Number FrmIn, FrmOut, ChansIn, ChansOut; cmsUInt32Number ColorSpaceBitsIn, ColorSpaceBitsOut; _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; cmsPipeline* LUT = NULL; cmsStage* mpe; cmsContext ContextID = cmsGetTransformContextID(hTransform); const cmsAllowedLUT* AllowedLUT; cmsTagSignature DestinationTag; cmsProfileClassSignature deviceClass; _cmsAssert(hTransform != NULL); // Get the first mpe to check for named color mpe = cmsPipelineGetPtrToFirstStage(xform ->Lut); // Check if is a named color transform if (mpe != NULL) { if (cmsStageType(mpe) == cmsSigNamedColorElemType) { return CreateNamedColorDevicelink(hTransform); } } // First thing to do is to get a copy of the transformation LUT = cmsPipelineDup(xform ->Lut); if (LUT == NULL) return NULL; // Time to fix the Lab2/Lab4 issue. if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) { if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID))) goto Error; } // On the output side too if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) { if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID))) goto Error; } hProfile = cmsCreateProfilePlaceholder(ContextID); if (!hProfile) goto Error; // can't allocate cmsSetProfileVersion(hProfile, Version); FixColorSpaces(hProfile, xform -> EntryColorSpace, xform -> ExitColorSpace, dwFlags); // Optimize the LUT and precalculate a devicelink ChansIn = cmsChannelsOf(xform -> EntryColorSpace); ChansOut = cmsChannelsOf(xform -> ExitColorSpace); ColorSpaceBitsIn = _cmsLCMScolorSpace(xform -> EntryColorSpace); ColorSpaceBitsOut = _cmsLCMScolorSpace(xform -> ExitColorSpace); FrmIn = COLORSPACE_SH(ColorSpaceBitsIn) | CHANNELS_SH(ChansIn)|BYTES_SH(2); FrmOut = COLORSPACE_SH(ColorSpaceBitsOut) | CHANNELS_SH(ChansOut)|BYTES_SH(2); deviceClass = cmsGetDeviceClass(hProfile); if (deviceClass == cmsSigOutputClass) DestinationTag = cmsSigBToA0Tag; else DestinationTag = cmsSigAToB0Tag; // Check if the profile/version can store the result if (dwFlags & cmsFLAGS_FORCE_CLUT) AllowedLUT = NULL; else AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); if (AllowedLUT == NULL) { // Try to optimize _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); } // If no way, then force CLUT that for sure can be written if (AllowedLUT == NULL) { dwFlags |= cmsFLAGS_FORCE_CLUT; _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); // Put identity curves if needed if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType) if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn))) goto Error; if (cmsPipelineGetPtrToLastStage(LUT) ->Type != cmsSigCurveSetElemType) if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, ChansOut))) goto Error; AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); } // Somethings is wrong... if (AllowedLUT == NULL) { goto Error; } if (dwFlags & cmsFLAGS_8BITS_DEVICELINK) cmsPipelineSetSaveAs8bitsFlag(LUT, TRUE); // Tag profile with information if (!SetTextTags(hProfile, L"devicelink")) goto Error; // Store result if (!cmsWriteTag(hProfile, DestinationTag, LUT)) goto Error; if (xform -> InputColorant != NULL) { if (!cmsWriteTag(hProfile, cmsSigColorantTableTag, xform->InputColorant)) goto Error; } if (xform -> OutputColorant != NULL) { if (!cmsWriteTag(hProfile, cmsSigColorantTableOutTag, xform->OutputColorant)) goto Error; } if ((deviceClass == cmsSigLinkClass) && (xform ->Sequence != NULL)) { if (!_cmsWriteProfileSequence(hProfile, xform ->Sequence)) goto Error; } // Set the white point if (deviceClass == cmsSigInputClass) { if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->EntryWhitePoint)) goto Error; } else { if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->ExitWhitePoint)) goto Error; } // Per 7.2.15 in spec 4.3 cmsSetHeaderRenderingIntent(hProfile, xform ->RenderingIntent); cmsPipelineFree(LUT); return hProfile; Error: if (LUT != NULL) cmsPipelineFree(LUT); cmsCloseProfile(hProfile); return NULL; }
cmsHPROFILE LCMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, DWORD dwFlags) { cmsHPROFILE hICC; _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) hTransform; LPLUT Lut; LCMSBOOL MustFreeLUT; LPcmsNAMEDCOLORLIST InputColorant = NULL; LPcmsNAMEDCOLORLIST OutputColorant = NULL; // Check if is a named color transform if (cmsGetDeviceClass(v ->InputProfile) == icSigNamedColorClass) { return CreateNamedColorDevicelink(hTransform); } if (v ->DeviceLink) { Lut = v -> DeviceLink; MustFreeLUT = FALSE; } else { Lut = _cmsPrecalculateDeviceLink(hTransform, dwFlags); if (!Lut) return NULL; MustFreeLUT = TRUE; } hICC = _cmsCreateProfilePlaceholder(); if (!hICC) { // can't allocate if (MustFreeLUT) cmsFreeLUT(Lut); return NULL; } FixColorSpaces(hICC, v -> EntryColorSpace, v -> ExitColorSpace, dwFlags); cmsSetRenderingIntent(hICC, v -> Intent); // Implement devicelink profile using following tags: // // 1 icSigProfileDescriptionTag // 2 icSigMediaWhitePointTag // 3 icSigAToB0Tag cmsAddTag(hICC, icSigDeviceMfgDescTag, (LPVOID) "LittleCMS"); cmsAddTag(hICC, icSigProfileDescriptionTag, (LPVOID) "Device link"); cmsAddTag(hICC, icSigDeviceModelDescTag, (LPVOID) "Device link"); cmsAddTag(hICC, icSigMediaWhitePointTag, (LPVOID) cmsD50_XYZ()); if (cmsGetDeviceClass(hICC) == icSigOutputClass) { cmsAddTag(hICC, icSigBToA0Tag, (LPVOID) Lut); } else cmsAddTag(hICC, icSigAToB0Tag, (LPVOID) Lut); // Try to read input and output colorant table if (cmsIsTag(v ->InputProfile, icSigColorantTableTag)) { // Input table can only come in this way. InputColorant = cmsReadColorantTable(v ->InputProfile, icSigColorantTableTag); } // Output is a little bit more complex. if (cmsGetDeviceClass(v ->OutputProfile) == icSigLinkClass) { // This tag may exist only on devicelink profiles. if (cmsIsTag(v ->OutputProfile, icSigColorantTableOutTag)) { OutputColorant = cmsReadColorantTable(v ->OutputProfile, icSigColorantTableOutTag); } } else { if (cmsIsTag(v ->OutputProfile, icSigColorantTableTag)) { OutputColorant = cmsReadColorantTable(v ->OutputProfile, icSigColorantTableTag); } } if (InputColorant) cmsAddTag(hICC, icSigColorantTableTag, InputColorant); if (OutputColorant) cmsAddTag(hICC, icSigColorantTableOutTag, OutputColorant); if (MustFreeLUT) cmsFreeLUT(Lut); if (InputColorant) cmsFreeNamedColorList(InputColorant); if (OutputColorant) cmsFreeNamedColorList(OutputColorant); return hICC; }