static void* DupNamedColorList(cmsStage* mpe) { cmsNAMEDCOLORLIST* List = (cmsNAMEDCOLORLIST*) mpe ->Data; return cmsDupNamedColorList(List); }
// New to lcms 2.0 -- have all parameters available. cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], cmsBool BPC[], cmsUInt32Number Intents[], cmsFloat64Number AdaptationStates[], cmsHPROFILE hGamutProfile, cmsUInt32Number nGamutPCSposition, cmsUInt32Number InputFormat, cmsUInt32Number OutputFormat, cmsUInt32Number dwFlags) { _cmsTRANSFORM* xform; cmsBool FloatTransform; cmsColorSpaceSignature EntryColorSpace; cmsColorSpaceSignature ExitColorSpace; cmsPipeline* Lut; cmsUInt32Number LastIntent = Intents[nProfiles-1]; // If it is a fake transform if (dwFlags & cmsFLAGS_NULLTRANSFORM) { return AllocEmptyTransform(ContextID, NULL, INTENT_PERCEPTUAL, &InputFormat, &OutputFormat, &dwFlags); } // If gamut check is requested, make sure we have a gamut profile if (dwFlags & cmsFLAGS_GAMUTCHECK) { if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK; } // On floating point transforms, inhibit optimizations FloatTransform = (_cmsFormatterIsFloat(InputFormat) && _cmsFormatterIsFloat(OutputFormat)); if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat)) dwFlags |= cmsFLAGS_NOCACHE; // Mark entry/exit spaces if (!GetXFormColorSpaces(nProfiles, hProfiles, &EntryColorSpace, &ExitColorSpace)) { cmsSignalError(ContextID, cmsERROR_NULL, "NULL input profiles on transform"); return NULL; } // Check if proper colorspaces if (!IsProperColorSpace(EntryColorSpace, InputFormat)) { cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong input color space on transform"); return NULL; } if (!IsProperColorSpace(ExitColorSpace, OutputFormat)) { cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong output color space on transform"); return NULL; } // Create a pipeline with all transformations Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags); if (Lut == NULL) { cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Couldn't link the profiles"); return NULL; } // Check channel count if ((cmsChannelsOf(EntryColorSpace) != cmsPipelineInputChannels(Lut)) || (cmsChannelsOf(ExitColorSpace) != cmsPipelineOutputChannels(Lut))) { cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted"); return NULL; } // All seems ok xform = AllocEmptyTransform(ContextID, Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags); if (xform == NULL) { return NULL; } // Keep values xform ->EntryColorSpace = EntryColorSpace; xform ->ExitColorSpace = ExitColorSpace; xform ->RenderingIntent = Intents[nProfiles-1]; // Create a gamut check LUT if requested if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK)) xform ->GamutCheck = _cmsCreateGamutCheckPipeline(ContextID, hProfiles, BPC, Intents, AdaptationStates, nGamutPCSposition, hGamutProfile); // Try to read input and output colorant table if (cmsIsTag(hProfiles[0], cmsSigColorantTableTag)) { // Input table can only come in this way. xform ->InputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[0], cmsSigColorantTableTag)); } // Output is a little bit more complex. if (cmsGetDeviceClass(hProfiles[nProfiles-1]) == cmsSigLinkClass) { // This tag may exist only on devicelink profiles. if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)) { // It may be NULL if error xform ->OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)); } } else { if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)) { xform -> OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)); } } // Store the sequence of profiles if (dwFlags & cmsFLAGS_KEEP_SEQUENCE) { xform ->Sequence = _cmsCompileProfileSequence(ContextID, nProfiles, hProfiles); } else xform ->Sequence = NULL; // If this is a cached transform, init first value, which is zero (16 bits only) if (!(dwFlags & cmsFLAGS_NOCACHE)) { memset(&xform ->Cache.CacheIn, 0, sizeof(xform ->Cache.CacheIn)); if (xform ->GamutCheck != NULL) { TransformOnePixelWithGamutCheck(xform, xform ->Cache.CacheIn, xform->Cache.CacheOut); } else { xform ->Lut ->Eval16Fn(xform ->Cache.CacheIn, xform->Cache.CacheOut, xform -> Lut->Data); } } return (cmsHTRANSFORM) xform; }
// Creates all needed color transforms static cmsBool OpenTransforms(void) { cmsHPROFILE hInput, hOutput, hProof; cmsUInt32Number dwIn, dwOut, dwFlags; cmsNAMEDCOLORLIST* List; int i; // We don't need cache dwFlags = cmsFLAGS_NOCACHE; if (lIsDeviceLink) { hInput = OpenStockProfile(0, cInProf); if (hInput == NULL) return FALSE; hOutput = NULL; hProof = NULL; if (cmsGetDeviceClass(hInput) == cmsSigNamedColorClass) { OutputColorSpace = cmsGetColorSpace(hInput); InputColorSpace = cmsGetPCS(hInput); } else { InputColorSpace = cmsGetColorSpace(hInput); OutputColorSpace = cmsGetPCS(hInput); } // Read colorant tables if present if (cmsIsTag(hInput, cmsSigColorantTableTag)) { List = cmsReadTag(hInput, cmsSigColorantTableTag); InputColorant = cmsDupNamedColorList(List); InputRange = 1; } else InputColorant = ComponentNames(InputColorSpace, TRUE); if (cmsIsTag(hInput, cmsSigColorantTableOutTag)){ List = cmsReadTag(hInput, cmsSigColorantTableOutTag); OutputColorant = cmsDupNamedColorList(List); OutputRange = 1; } else OutputColorant = ComponentNames(OutputColorSpace, FALSE); } else { hInput = OpenStockProfile(0, cInProf); if (hInput == NULL) return FALSE; hOutput = OpenStockProfile(0, cOutProf); if (hOutput == NULL) return FALSE; hProof = NULL; if (cmsGetDeviceClass(hInput) == cmsSigLinkClass || cmsGetDeviceClass(hOutput) == cmsSigLinkClass) FatalError("Use %cl flag for devicelink profiles!\n", SW); InputColorSpace = cmsGetColorSpace(hInput); OutputColorSpace = cmsGetColorSpace(hOutput); // Read colorant tables if present if (cmsIsTag(hInput, cmsSigColorantTableTag)) { List = cmsReadTag(hInput, cmsSigColorantTableTag); InputColorant = cmsDupNamedColorList(List); if (cmsNamedColorCount(InputColorant) <= 3) SetRange(255, TRUE); else SetRange(1, TRUE); // Inks are already divided by 100 in the formatter } else InputColorant = ComponentNames(InputColorSpace, TRUE); if (cmsIsTag(hOutput, cmsSigColorantTableTag)){ List = cmsReadTag(hOutput, cmsSigColorantTableTag); OutputColorant = cmsDupNamedColorList(List); if (cmsNamedColorCount(OutputColorant) <= 3) SetRange(255, FALSE); else SetRange(1, FALSE); // Inks are already divided by 100 in the formatter } else OutputColorant = ComponentNames(OutputColorSpace, FALSE); if (cProofing != NULL) { hProof = OpenStockProfile(0, cProofing); if (hProof == NULL) return FALSE; dwFlags |= cmsFLAGS_SOFTPROOFING; } } // Print information on profiles if (Verbose > 2) { printf("Profile:\n"); PrintProfileInformation(hInput); if (hOutput) { printf("Output profile:\n"); PrintProfileInformation(hOutput); } if (hProof != NULL) { printf("Proofing profile:\n"); PrintProfileInformation(hProof); } } // Input is always in floating point dwIn = cmsFormatterForColorspaceOfProfile(hInput, 0, TRUE); if (lIsDeviceLink) { dwOut = cmsFormatterForPCSOfProfile(hInput, lIsFloat ? 0 : 2, lIsFloat); } else { // 16 bits or floating point (only on output) dwOut = cmsFormatterForColorspaceOfProfile(hOutput, lIsFloat ? 0 : 2, lIsFloat); } // For named color, there is a specialized formatter if (cmsGetDeviceClass(hInput) == cmsSigNamedColorClass) { dwOut = dwIn; dwIn = TYPE_NAMED_COLOR_INDEX; InputNamedColor = TRUE; } // Precision mode switch (PrecalcMode) { case 0: dwFlags |= cmsFLAGS_NOOPTIMIZE; break; case 2: dwFlags |= cmsFLAGS_HIGHRESPRECALC; break; case 3: dwFlags |= cmsFLAGS_LOWRESPRECALC; break; case 1: break; default: FatalError("Unknown precalculation mode '%d'", PrecalcMode); } if (BlackPointCompensation) dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION; if (GamutCheck) { cmsUInt16Number Alarm[cmsMAXCHANNELS]; if (hProof == NULL) FatalError("I need proofing profile -p for gamut checking!"); for (i=0; i < cmsMAXCHANNELS; i++) Alarm[i] = 0xFFFF; cmsSetAlarmCodes(Alarm); dwFlags |= cmsFLAGS_GAMUTCHECK; } // The main transform hTrans = cmsCreateProofingTransform(hInput, dwIn, hOutput, dwOut, hProof, Intent, ProofingIntent, dwFlags); if (hProof) cmsCloseProfile(hProof); if (hTrans == NULL) return FALSE; // PCS Dump if requested hTransXYZ = NULL; hTransLab = NULL; if (hOutput && Verbose > 1) { cmsHPROFILE hXYZ = cmsCreateXYZProfile(); cmsHPROFILE hLab = cmsCreateLab4Profile(NULL); hTransXYZ = cmsCreateTransform(hInput, dwIn, hXYZ, lIsFloat ? TYPE_XYZ_DBL : TYPE_XYZ_16, Intent, cmsFLAGS_NOCACHE); if (hTransXYZ == NULL) return FALSE; hTransLab = cmsCreateTransform(hInput, dwIn, hLab, lIsFloat? TYPE_Lab_DBL : TYPE_Lab_16, Intent, cmsFLAGS_NOCACHE); if (hTransLab == NULL) return FALSE; cmsCloseProfile(hXYZ); cmsCloseProfile(hLab); } if (hInput) cmsCloseProfile(hInput); if (hOutput) cmsCloseProfile(hOutput); return TRUE; }