//--------------------------------------------------------------------------------- // // Little Color Management System // Copyright (c) 1998-2023 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the Software // is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // //--------------------------------------------------------------------------------- // #include "lcms2_internal.h" // This is the default routine for ICC-style intents. A user may decide to override it by using a plugin. // Supported intents are perceptual, relative colorimetric, saturation and ICC-absolute colorimetric static cmsPipeline* DefaultICCintents(cmsContext ContextID, cmsUInt32Number nProfiles, cmsUInt32Number Intents[], cmsHPROFILE hProfiles[], cmsBool BPC[], cmsFloat64Number AdaptationStates[], cmsUInt32Number dwFlags); //--------------------------------------------------------------------------------- // This is the entry for black-preserving K-only intents, which are non-ICC. Last profile have to be a output profile // to do the trick (no devicelinks allowed at that position) static cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID, cmsUInt32Number nProfiles, cmsUInt32Number Intents[], cmsHPROFILE hProfiles[], cmsBool BPC[], cmsFloat64Number AdaptationStates[], cmsUInt32Number dwFlags); //--------------------------------------------------------------------------------- // This is the entry for black-plane preserving, which are non-ICC. Again, Last profile have to be a output profile // to do the trick (no devicelinks allowed at that position) static cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID, cmsUInt32Number nProfiles, cmsUInt32Number Intents[], cmsHPROFILE hProfiles[], cmsBool BPC[], cmsFloat64Number AdaptationStates[], cmsUInt32Number dwFlags); //--------------------------------------------------------------------------------- // This is a structure holding implementations for all supported intents. cmsIntentsList; // Built-in intents static cmsIntentsList DefaultIntents[] = …; // A pointer to the beginning of the list _cmsIntentsPluginChunkType _cmsIntentsPluginChunk = …; // Duplicates the zone of memory used by the plug-in in the new context static void DupPluginIntentsList(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) { … } void _cmsAllocIntentsPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) { … } // Search the list for a suitable intent. Returns NULL if not found static cmsIntentsList* SearchIntent(cmsContext ContextID, cmsUInt32Number Intent) { … } // Black point compensation. Implemented as a linear scaling in XYZ. Black points // should come relative to the white point. Fills an matrix/offset element m // which is organized as a 4x4 matrix. static void ComputeBlackPointCompensation(const cmsCIEXYZ* BlackPointIn, const cmsCIEXYZ* BlackPointOut, cmsMAT3* m, cmsVEC3* off) { … } // Approximate a blackbody illuminant based on CHAD information static cmsFloat64Number CHAD2Temp(const cmsMAT3* Chad) { … } // Compute a CHAD based on a given temperature static void Temp2CHAD(cmsMAT3* Chad, cmsFloat64Number Temp) { … } // Join scalings to obtain relative input to absolute and then to relative output. // Result is stored in a 3x3 matrix static cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState, const cmsCIEXYZ* WhitePointIn, const cmsMAT3* ChromaticAdaptationMatrixIn, const cmsCIEXYZ* WhitePointOut, const cmsMAT3* ChromaticAdaptationMatrixOut, cmsMAT3* m) { … } // Just to see if m matrix should be applied static cmsBool IsEmptyLayer(cmsMAT3* m, cmsVEC3* off) { … } // Compute the conversion layer static cmsBool ComputeConversion(cmsUInt32Number i, cmsHPROFILE hProfiles[], cmsUInt32Number Intent, cmsBool BPC, cmsFloat64Number AdaptationState, cmsMAT3* m, cmsVEC3* off) { … } // Add a conversion stage if needed. If a matrix/offset m is given, it applies to XYZ space static cmsBool AddConversion(cmsPipeline* Result, cmsColorSpaceSignature InPCS, cmsColorSpaceSignature OutPCS, cmsMAT3* m, cmsVEC3* off) { … } // Is a given space compatible with another? static cmsBool ColorSpaceIsCompatible(cmsColorSpaceSignature a, cmsColorSpaceSignature b) { … } // Default handler for ICC-style intents static cmsPipeline* DefaultICCintents(cmsContext ContextID, cmsUInt32Number nProfiles, cmsUInt32Number TheIntents[], cmsHPROFILE hProfiles[], cmsBool BPC[], cmsFloat64Number AdaptationStates[], cmsUInt32Number dwFlags) { … } // Wrapper for DLL calling convention cmsPipeline* CMSEXPORT _cmsDefaultICCintents(cmsContext ContextID, cmsUInt32Number nProfiles, cmsUInt32Number TheIntents[], cmsHPROFILE hProfiles[], cmsBool BPC[], cmsFloat64Number AdaptationStates[], cmsUInt32Number dwFlags) { … } // Black preserving intents --------------------------------------------------------------------------------------------- // Translate black-preserving intents to ICC ones static cmsUInt32Number TranslateNonICCIntents(cmsUInt32Number Intent) { … } // Sampler for Black-only preserving CMYK->CMYK transforms GrayOnlyParams; // Preserve black only if that is the only ink used static int BlackPreservingGrayOnlySampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Number Out[], CMSREGISTER void* Cargo) { … } // This is the entry for black-preserving K-only intents, which are non-ICC static cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID, cmsUInt32Number nProfiles, cmsUInt32Number TheIntents[], cmsHPROFILE hProfiles[], cmsBool BPC[], cmsFloat64Number AdaptationStates[], cmsUInt32Number dwFlags) { … } // K Plane-preserving CMYK to CMYK ------------------------------------------------------------------------------------ PreserveKPlaneParams; // The CLUT will be stored at 16 bits, but calculations are performed at cmsFloat32Number precision static int BlackPreservingSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Number Out[], CMSREGISTER void* Cargo) { … } // This is the entry for black-plane preserving, which are non-ICC static cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID, cmsUInt32Number nProfiles, cmsUInt32Number TheIntents[], cmsHPROFILE hProfiles[], cmsBool BPC[], cmsFloat64Number AdaptationStates[], cmsUInt32Number dwFlags) { … } // Link routines ------------------------------------------------------------------------------------------------------ // Chain several profiles into a single LUT. It just checks the parameters and then calls the handler // for the first intent in chain. The handler may be user-defined. Is up to the handler to deal with the // rest of intents in chain. A maximum of 255 profiles at time are supported, which is pretty reasonable. cmsPipeline* _cmsLinkProfiles(cmsContext ContextID, cmsUInt32Number nProfiles, cmsUInt32Number TheIntents[], cmsHPROFILE hProfiles[], cmsBool BPC[], cmsFloat64Number AdaptationStates[], cmsUInt32Number dwFlags) { … } // ------------------------------------------------------------------------------------------------- // Get information about available intents. nMax is the maximum space for the supplied "Codes" // and "Descriptions" the function returns the total number of intents, which may be greater // than nMax, although the matrices are not populated beyond this level. cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions) { … } cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions) { … } // The plug-in registration. User can add new intents or override default routines cmsBool _cmsRegisterRenderingIntentPlugin(cmsContext id, cmsPluginBase* Data) { … }