// 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. // //--------------------------------------------------------------------------------- //
#include"lcms2_internal.h"
// PostScript ColorRenderingDictionary and ColorSpaceArray
// // Convert L* to Y // // Y = Yn*[ (L* + 16) / 116] ^ 3 if (L*) >= 6 / 29 // = Yn*( L* / 116) / 7.787 if (L*) < 6 / 29 //
// Lab -> XYZ, see the discussion above
static void EmitLab2XYZ(cmsIOHANDLER* m)
{
_cmsIOPrintf(m, "/RangeABC [ 0 1 0 1 0 1]\n");
_cmsIOPrintf(m, "/DecodeABC [\n");
_cmsIOPrintf(m, "{100 mul 16 add 116 div } bind\n");
_cmsIOPrintf(m, "{255 mul 128 sub 500 div } bind\n");
_cmsIOPrintf(m, "{255 mul 128 sub 200 div } bind\n");
_cmsIOPrintf(m, "]\n");
_cmsIOPrintf(m, "/MatrixABC [ 1 1 1 1 0 0 0 0 -1]\n");
_cmsIOPrintf(m, "/RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]\n");
_cmsIOPrintf(m, "/DecodeLMN [\n");
_cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.964200 mul} bind\n");
_cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind\n");
_cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.824900 mul} bind\n");
_cmsIOPrintf(m, "]\n");
}
static void EmitSafeGuardBegin(cmsIOHANDLER* m, constchar* name)
{
_cmsIOPrintf(m, "%%LCMS2: Save previous definition of %s on the operand stack\n", name);
_cmsIOPrintf(m, "currentdict /%s known { /%s load } { null } ifelse\n", name, name);
}
static void EmitSafeGuardEnd(cmsIOHANDLER* m, constchar* name, int depth)
{
_cmsIOPrintf(m, "%%LCMS2: Restore previous definition of %s\n", name); if (depth > 1) { // cycle topmost items on the stack to bring the previous definition to the front
_cmsIOPrintf(m, "%d -1 roll ", depth);
}
_cmsIOPrintf(m, "dup null eq { pop currentdict /%s undef } { /%s exch def } ifelse\n", name, name);
}
// This is the sampler. Intended to work in SAMPLER_INSPECT mode, // that is, the callback will be called for each knot with // // In[] The grid location coordinates, normalized to 0..ffff // Out[] The Pipeline values, normalized to 0..ffff // // Returning a value other than 0 does terminate the sampling process // // Each row contains Pipeline values for all but first component. So, I // detect row changing by keeping a copy of last value of first // component. -1 is used to mark beginning of whole block.
cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Only 3, 4 channels are supported for CSA. This profile has %d channels.", nChannels); return0;
}
// Does create CSA based on matrix-shaper. Allowed types are gray and RGB based static int WriteInputMatrixShaper(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsStage* Matrix, cmsStage* Shaper)
{
cmsColorSpaceSignature ColorSpace; int rc;
cmsCIEXYZ BlackPointAdaptedToD50;
// Does create a Color Space Array on XYZ colorspace for PostScript usage static
cmsUInt32Number GenerateCSA(cmsContext ContextID,
cmsHPROFILE hProfile,
cmsUInt32Number Intent,
cmsUInt32Number dwFlags,
cmsIOHANDLER* mem)
{
cmsUInt32Number dwBytesUsed;
cmsPipeline* lut = NULL;
cmsStage* Matrix, *Shaper;
// Is a named color profile? if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) {
if (!WriteNamedColorCSA(mem, hProfile, Intent)) goto Error;
} else {
// Any profile class are allowed (including devicelink), but // output (PCS) colorspace must be XYZ or Lab
cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile);
if (ColorSpace != cmsSigXYZData &&
ColorSpace != cmsSigLabData) {
cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Invalid output color space"); goto Error;
}
// Read the lut with all necessary conversion stages
lut = _cmsReadInputLUT(hProfile, Intent); if (lut == NULL) goto Error;
// Tone curves + matrix can be implemented without any LUT if (cmsPipelineCheckAndRetreiveStages(lut, 2, cmsSigCurveSetElemType, cmsSigMatrixElemType, &Shaper, &Matrix)) {
if (!WriteInputMatrixShaper(mem, hProfile, Matrix, Shaper)) goto Error;
} else { // We need a LUT for the rest if (!WriteInputLUT(mem, hProfile, Intent, dwFlags)) goto Error;
}
}
// Done, keep memory usage
dwBytesUsed = mem ->UsedSpace;
// Get rid of LUT if (lut != NULL) cmsPipelineFree(lut);
// Finally, return used byte count return dwBytesUsed;
Error: if (lut != NULL) cmsPipelineFree(lut); return0;
}
// ------------------------------------------------------ Color Rendering Dictionary (CRD)
3index3getBPin(BPout-WPout)*WPout*(PQR/WPin)-(BPin-BPout)*WPoutBPoutWPoutBPinWPin 3index3getWPoutBPin(BPout-WPout)*WPout*(PQR/WPin)-(BPin-BPout)*WPoutBPoutWPoutBPinWPin exch sub(WPout-BPin)(BPout-WPout)*WPout*(PQR/WPin)-(BPin-BPout)*WPoutBPoutWPoutBPinWPin div
exchpop exchpop exchpop exchpop
*/
static void EmitPQRStage(cmsIOHANDLER* m, cmsHPROFILE hProfile, int DoBPC, int lIsAbsolute)
{
if (lIsAbsolute) {
// For absolute colorimetric intent, encode back to relative // and generate a relative Pipeline
// Relative encoding is obtained across XYZpcs*(D50/WhitePoint)
_cmsIOPrintf(m, "%% Absolute colorimetric -- encode to relative to maximize LUT usage\n" "/TransformPQR [\n" "{0.9642 mul %g div exch pop exch pop exch pop exch pop} bind\n" "{1.0000 mul %g div exch pop exch pop exch pop exch pop} bind\n" "{0.8249 mul %g div exch pop exch pop exch pop exch pop} bind\n]\n",
White.X, White.Y, White.Z); return;
}
_cmsIOPrintf(m, "%% VonKries-like transform in Bradford Cone Space\n" "/TransformPQR [\n" "{exch pop exch 3 get mul exch pop exch 3 get div} bind\n" "{exch pop exch 4 get mul exch pop exch 4 get div} bind\n" "{exch pop exch 5 get mul exch pop exch 5 get div} bind\n]\n");
} else {
// BPC
_cmsIOPrintf(m, "%% VonKries-like transform in Bradford Cone Space plus BPC\n" "/TransformPQR [\n");
_cmsIOPrintf(m, "{4 index 3 get div 2 index 3 get mul " "2 index 3 get 2 index 3 get sub mul " "2 index 3 get 4 index 3 get 3 index 3 get sub mul sub " "3 index 3 get 3 index 3 get exch sub div " "exch pop exch pop exch pop exch pop } bind\n");
_cmsIOPrintf(m, "{4 index 4 get div 2 index 4 get mul " "2 index 4 get 2 index 4 get sub mul " "2 index 4 get 4 index 4 get 3 index 4 get sub mul sub " "3 index 4 get 3 index 4 get exch sub div " "exch pop exch pop exch pop exch pop } bind\n");
_cmsIOPrintf(m, "{4 index 5 get div 2 index 5 get mul " "2 index 5 get 2 index 5 get sub mul " "2 index 5 get 4 index 5 get 3 index 5 get sub mul sub " "3 index 5 get 3 index 5 get exch sub div " "exch pop exch pop exch pop exch pop } bind\n]\n");
}
}
static void EmitXYZ2Lab(cmsIOHANDLER* m)
{
_cmsIOPrintf(m, "/RangeLMN [ -0.635 2.0 0 2 -0.635 2.0 ]\n");
_cmsIOPrintf(m, "/EncodeLMN [\n");
_cmsIOPrintf(m, "{ 0.964200 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
_cmsIOPrintf(m, "{ 1.000000 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
_cmsIOPrintf(m, "{ 0.824900 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
_cmsIOPrintf(m, "]\n");
_cmsIOPrintf(m, "/MatrixABC [ 0 1 0 1 -1 1 0 0 -1 ]\n");
_cmsIOPrintf(m, "/EncodeABC [\n");
_cmsIOPrintf(m, "{ 116 mul 16 sub 100 div } bind\n");
_cmsIOPrintf(m, "{ 500 mul 128 add 256 div } bind\n");
_cmsIOPrintf(m, "{ 200 mul 128 add 256 div } bind\n");
_cmsIOPrintf(m, "]\n");
}
// Due to impedance mismatch between XYZ and almost all RGB and CMYK spaces // I choose to dump LUTS in Lab instead of XYZ. There is still a lot of wasted // space on 3D CLUT, but since space seems not to be a problem here, 33 points // would give a reasonable accuracy. Note also that CRD tables must operate in // 8 bits.
// Get a copy of the internal devicelink
v = (_cmsTRANSFORM*) xform;
DeviceLink = cmsPipelineDup(v ->Lut); if (DeviceLink == NULL) return0;
// We need a CLUT
dwFlags |= cmsFLAGS_FORCE_CLUT;
_cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags);
// FIXUP: map Lab (100, 0, 0) to perfect white, because the particular encoding for Lab // does map a=b=0 not falling into any specific node. Since range a,b goes -128..127, // zero is slightly moved towards right, so assure next node (in L=100 slice) is mapped to // zero. This would sacrifice a bit of highlights, but failure to do so would cause // scum dot. Ouch.
if (Intent == INTENT_ABSOLUTE_COLORIMETRIC)
lFixWhite = FALSE;
// Set up the serialization engine if (Buffer == NULL)
mem = cmsOpenIOhandlerFromNULL(ContextID); else
mem = cmsOpenIOhandlerFromMem(ContextID, Buffer, dwBufferLen, "w");
// Get rid of memory stream
cmsCloseIOhandler(mem);
return dwBytesUsed;
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.30Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-06-11)
¤
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 und die Messung sind noch experimentell.