/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
// This file is available under and governed by the GNU General Public // License version 2 only, as published by the Free Software Foundation. // However, the following notice accompanied the original version of this // file: // //--------------------------------------------------------------------------------- // // Little Color Management System // Copyright (c) 1998-2022 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. // //--------------------------------------------------------------------------------- //
if (!_cmsWriteProfileSequence(hProfile, Seq)) goto Error;
rc = TRUE;
Error: if (Seq)
cmsFreeProfileSequenceDescription(Seq);
return rc;
}
// This function creates a profile based on White point, primaries and // transfer functions.
cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint, const cmsCIExyYTRIPLE* Primaries,
cmsToneCurve* const TransferFunction[3])
{
cmsHPROFILE hICC;
cmsMAT3 MColorants;
cmsCIEXYZTRIPLE Colorants;
cmsCIExyY MaxWhite;
cmsMAT3 CHAD;
cmsCIEXYZ WhitePointXYZ;
hICC = cmsCreateProfilePlaceholder(ContextID); if (!hICC) // can't allocate return NULL;
// This is a V4 tag, but many CMM does read and understand it no matter which version if (!cmsWriteTag(hICC, cmsSigChromaticAdaptationTag, (void*) &CHAD)) goto Error;
}
if (!cmsWriteTag(hICC, cmsSigRedColorantTag, (void*) &Colorants.Red)) goto Error; if (!cmsWriteTag(hICC, cmsSigBlueColorantTag, (void*) &Colorants.Blue)) goto Error; if (!cmsWriteTag(hICC, cmsSigGreenColorantTag, (void*) &Colorants.Green)) goto Error;
}
if (TransferFunction) {
// Tries to minimize space. Thanks to Richard Hughes for this nice idea if (!cmsWriteTag(hICC, cmsSigRedTRCTag, (void*) TransferFunction[0])) goto Error;
if (TransferFunction[1] == TransferFunction[0]) {
if (!cmsLinkTag (hICC, cmsSigGreenTRCTag, cmsSigRedTRCTag)) goto Error;
} else {
if (!cmsWriteTag(hICC, cmsSigGreenTRCTag, (void*) TransferFunction[1])) goto Error;
}
if (TransferFunction[2] == TransferFunction[0]) {
if (!cmsLinkTag (hICC, cmsSigBlueTRCTag, cmsSigRedTRCTag)) goto Error;
} else {
if (!cmsWriteTag(hICC, cmsSigBlueTRCTag, (void*) TransferFunction[2])) goto Error;
}
}
if (Primaries) { if (!cmsWriteTag(hICC, cmsSigChromaticityTag, (void*) Primaries)) goto Error;
}
return hICC;
Error: if (hICC)
cmsCloseProfile(hICC); return NULL;
}
// This function creates a profile based on White point and transfer function.
cmsHPROFILE CMSEXPORT cmsCreateGrayProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint, const cmsToneCurve* TransferFunction)
{
cmsHPROFILE hICC;
cmsCIEXYZ tmp;
hICC = cmsCreateProfilePlaceholder(ContextID); if (!hICC) // can't allocate return NULL;
// Ink-limiting algorithm // // Sum = C + M + Y + K // If Sum > InkLimit // Ratio= 1 - (Sum - InkLimit) / (C + M + Y) // if Ratio <0 // Ratio=0 // endif // Else // Ratio=1 // endif // // C = Ratio * C // M = Ratio * M // Y = Ratio * Y // K: Does not change
// This function creates a named color profile dumping all the contents of transform to a single profile // In this way, LittleCMS may be used to "group" several named color databases into a single profile. // It has, however, several minor limitations. PCS is always Lab, which is not very critic since this // is the normal PCS for named color profiles. static
cmsHPROFILE CreateNamedColorDevicelink(cmsHTRANSFORM xform)
{
_cmsTRANSFORM* v = (_cmsTRANSFORM*) xform;
cmsHPROFILE hICC = NULL;
cmsUInt32Number i, nColors;
cmsNAMEDCOLORLIST *nc2 = NULL, *Original = NULL;
// Create an empty placeholder
hICC = cmsCreateProfilePlaceholder(v->ContextID); if (hICC == NULL) return NULL;
// Critical information
cmsSetDeviceClass(hICC, cmsSigNamedColorClass);
cmsSetColorSpace(hICC, v ->ExitColorSpace);
cmsSetPCS(hICC, cmsSigLabData);
// Tag profile with information if (!SetTextTags(hICC, L"Named color devicelink")) goto Error;
Original = cmsGetNamedColorList(xform); if (Original == NULL) goto Error;
// Colorant count now depends on the output space
nc2 ->ColorantCount = cmsPipelineOutputChannels(v ->Lut);
// Make sure we have proper formatters
cmsChangeBuffersFormat(xform, TYPE_NAMED_COLOR_INDEX,
FLOAT_SH(0) | COLORSPACE_SH(_cmsLCMScolorSpace(v ->ExitColorSpace))
| BYTES_SH(2) | CHANNELS_SH(cmsChannelsOfColorSpace(v ->ExitColorSpace)));
// Apply the transfor to colorants. for (i=0; i < nColors; i++) {
cmsDoTransform(xform, &i, nc2 ->List[i].DeviceColorant, 1);
}
if (!cmsWriteTag(hICC, cmsSigNamedColor2Tag, (void*) nc2)) goto Error;
cmsFreeNamedColorList(nc2);
return hICC;
Error: if (hICC != NULL) cmsCloseProfile(hICC); return NULL;
}
// This structure holds information about which MPU can be stored on a profile based on the version
typedefstruct {
cmsBool IsV4; // Is a V4 tag?
cmsTagSignature RequiredTag; // Set to 0 for both types
cmsTagTypeSignature LutType; // The LUT type int nTypes; // Number of types (up to 5)
cmsStageSignature MpeTypes[5]; // 5 is the maximum number
if (IsV4 ^ Tab -> IsV4) continue; if ((Tab ->RequiredTag != 0) && (Tab ->RequiredTag != DestinationTag)) continue;
if (CheckOne(Tab, Lut)) return Tab;
}
return NULL;
}
// Does convert a transform into a device link profile
cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags)
{
cmsHPROFILE hProfile = NULL;
cmsUInt32Number FrmIn, FrmOut;
cmsInt32Number ChansIn, ChansOut; int 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. Note that due to V2/V4 PCS encoding on lab we cannot fix white misalignments if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) {
dwFlags |= cmsFLAGS_NOWHITEONWHITEFIXUP; if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID))) goto Error;
}
hProfile = cmsCreateProfilePlaceholder(ContextID); if (!hProfile) goto Error; // can't allocate
// 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) {
// Put identity curves if needed
FirstStage = cmsPipelineGetPtrToFirstStage(LUT); if (FirstStage != NULL && FirstStage ->Type != cmsSigCurveSetElemType) if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn))) goto Error;
LastStage = cmsPipelineGetPtrToLastStage(LUT); if (LastStage != NULL && LastStage ->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;
}
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.