//---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2010 Marti Maria Saguer
+// Copyright (c) 1998-2016 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
+// 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
+// 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
+// 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.
//
//---------------------------------------------------------------------------------
Dest -> Z = ((1 - Source -> x - Source -> y) / Source -> y) * Source -> Y;
}
+/*
+ The break point (24/116)^3 = (6/29)^3 is a very small amount of tristimulus
+ primary (0.008856). Generally, this only happens for
+ nearly ideal blacks and for some orange / amber colors in transmission mode.
+ For example, the Z value of the orange turn indicator lamp lens on an
+ automobile will often be below this value. But the Z does not
+ contribute to the perceived color directly.
+*/
+
static
cmsFloat64Number f(cmsFloat64Number t)
{
if (t <= Limit)
return (841.0/108.0) * t + (16.0/116.0);
else
- return pow(t, 1.0/3.0);
+ return pow(t, 1.0/3.0);
}
static
{
cmsFloat64Number fx, fy, fz;
- if (WhitePoint == NULL)
+ if (WhitePoint == NULL)
WhitePoint = cmsD50_XYZ();
fx = f(xyz->X / WhitePoint->X);
{
cmsFloat64Number x, y, z;
- if (WhitePoint == NULL)
+ if (WhitePoint == NULL)
WhitePoint = cmsD50_XYZ();
y = (Lab-> L + 16.0) / 116.0;
static
cmsFloat64Number L2float2(cmsUInt16Number v)
{
- return (cmsFloat64Number) v / 652.800;
+ return (cmsFloat64Number) v / 652.800;
}
// the a/b part
static
cmsFloat64Number ab2float2(cmsUInt16Number v)
-{
- return ((cmsFloat64Number) v / 256.0) - 128.0;
+{
+ return ((cmsFloat64Number) v / 256.0) - 128.0;
}
static
cmsUInt16Number L2Fix2(cmsFloat64Number L)
{
- return _cmsQuickSaturateWord(L * 652.8);
+ return _cmsQuickSaturateWord(L * 652.8);
}
static
cmsUInt16Number ab2Fix2(cmsFloat64Number ab)
{
- return _cmsQuickSaturateWord((ab + 128.0) * 256.0);
+ return _cmsQuickSaturateWord((ab + 128.0) * 256.0);
}
Lab.L = Clamp_L_doubleV2(fLab ->L);
Lab.a = Clamp_ab_doubleV2(fLab ->a);
Lab.b = Clamp_ab_doubleV2(fLab ->b);
-
+
wLab[0] = L2Fix2(Lab.L);
wLab[1] = ab2Fix2(Lab.a);
wLab[2] = ab2Fix2(Lab.b);
return ab;
}
-static
+static
cmsUInt16Number L2Fix4(cmsFloat64Number L)
{
return _cmsQuickSaturateWord(L * 655.35);
void CMSEXPORT cmsFloat2LabEncoded(cmsUInt16Number wLab[3], const cmsCIELab* fLab)
{
cmsCIELab Lab;
-
+
Lab.L = Clamp_L_doubleV4(fLab ->L);
Lab.a = Clamp_ab_doubleV4(fLab ->a);
Lab.b = Clamp_ab_doubleV4(fLab ->b);
-
+
wLab[0] = L2Fix4(Lab.L);
wLab[1] = ab2Fix4(Lab.a);
wLab[2] = ab2Fix4(Lab.b);
h = 0;
else
h = atan2(a, b);
-
+
h *= (180. / M_PI);
-
- while (h > 360.)
+
+ while (h > 360.)
h -= 360.;
-
+
while ( h < 0)
h += 360.;
-
+
return h;
}
static
cmsFloat64Number Sqr(cmsFloat64Number v)
{
- return v * v;
+ return v * v;
}
// From cylindrical coordinates. No check is performed, then negative values are allowed
void CMSEXPORT cmsLab2LCh(cmsCIELCh* LCh, const cmsCIELab* Lab)
Lab -> L = LCh -> L;
Lab -> a = LCh -> C * cos(h);
- Lab -> b = LCh -> C * sin(h);
+ Lab -> b = LCh -> C * sin(h);
}
// In XYZ All 3 components are encoded using 1.15 fixed point
static
cmsUInt16Number XYZ2Fix(cmsFloat64Number d)
-{
+{
return _cmsQuickSaturateWord(d * 32768.0);
}
xyz.Y = fXYZ -> Y;
xyz.Z = fXYZ -> Z;
- // Clamp to encodeable values.
+ // Clamp to encodeable values.
if (xyz.Y <= 0) {
xyz.X = 0;
xyz.Z = 0;
}
- if (xyz.X > MAX_ENCODEABLE_XYZ)
+ if (xyz.X > MAX_ENCODEABLE_XYZ)
xyz.X = MAX_ENCODEABLE_XYZ;
if (xyz.X < 0)
xyz.X = 0;
- if (xyz.Y > MAX_ENCODEABLE_XYZ)
+ if (xyz.Y > MAX_ENCODEABLE_XYZ)
xyz.Y = MAX_ENCODEABLE_XYZ;
if (xyz.Y < 0)
xyz.Y = 0;
- if (xyz.Z > MAX_ENCODEABLE_XYZ)
+ if (xyz.Z > MAX_ENCODEABLE_XYZ)
xyz.Z = MAX_ENCODEABLE_XYZ;
if (xyz.Z < 0)
XYZ[0] = XYZ2Fix(xyz.X);
XYZ[1] = XYZ2Fix(xyz.Y);
- XYZ[2] = XYZ2Fix(xyz.Z);
+ XYZ[2] = XYZ2Fix(xyz.Z);
}
fXYZ -> X = XYZ2float(XYZ[0]);
fXYZ -> Y = XYZ2float(XYZ[1]);
fXYZ -> Z = XYZ2float(XYZ[2]);
-}
+}
// Returns dE on two Lab values
}
-// Return the CIE94 Delta E
+// Return the CIE94 Delta E
cmsFloat64Number CMSEXPORT cmsCIE94DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2)
{
cmsCIELCh LCh1, LCh2;
dC = fabs(LCh1.C - LCh2.C);
dE = cmsDeltaE(Lab1, Lab2);
-
+
dhsq = Sqr(dE) - Sqr(dL) - Sqr(dC);
if (dhsq < 0)
dh = 0;
sc = 1.0 + (0.048 * c12);
sh = 1.0 + (0.014 * c12);
-
+
return sqrt(Sqr(dL) + Sqr(dC) / Sqr(sc) + Sqr(dh) / Sqr(sh));
}
dc = 0.035 * AveC / (1 + 0.00365 * AveC)+0.521;
g = sqrt(Sqr(Sqr(AveC))/(Sqr(Sqr(AveC))+14000));
- t = 0.627+(0.055*cos((Aveh-254)/(180/M_PI))-
+ t = 0.627+(0.055*cos((Aveh-254)/(180/M_PI))-
0.040*cos((2*Aveh-136)/(180/M_PI))+
0.070*cos((3*Aveh-31)/(180/M_PI))+
0.049*cos((4*Aveh+114)/(180/M_PI))-
cmsLab2LCh(&LCh1, Lab1);
cmsLab2LCh(&LCh2, Lab2);
-
+
dL = Lab2->L-Lab1->L;
dC = LCh2.C-LCh1.C;
dE = cmsDeltaE(Lab1, Lab2);
- if (Sqr(dE)>(Sqr(dL)+Sqr(dC)))
+ if (Sqr(dE)>(Sqr(dL)+Sqr(dC)))
dh = sqrt(Sqr(dE)-Sqr(dL)-Sqr(dC));
else
dh =0;
- if ((LCh1.h > 164) && (LCh1.h < 345))
+ if ((LCh1.h > 164) && (LCh1.h < 345))
t = 0.56 + fabs(0.2 * cos(((LCh1.h + 168)/(180/M_PI))));
- else
+ else
t = 0.36 + fabs(0.4 * cos(((LCh1.h + 35 )/(180/M_PI))));
sc = 0.0638 * LCh1.C / (1 + 0.0131 * LCh1.C) + 0.638;
sl = 0.040975 * Lab1->L /(1 + 0.01765 * Lab1->L);
-
+
if (Lab1->L<16)
- sl = 0.511;
+ sl = 0.511;
f = sqrt((LCh1.C * LCh1.C * LCh1.C * LCh1.C)/((LCh1.C * LCh1.C * LCh1.C * LCh1.C)+1900));
sh = sc*(t*f+1-f);
return cmc;
}
-// dE2000 The weightings KL, KC and KH can be modified to reflect the relative
+// dE2000 The weightings KL, KC and KH can be modified to reflect the relative
// importance of lightness, chroma and hue in different industrial applications
cmsFloat64Number CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2,
cmsFloat64Number Kl, cmsFloat64Number Kc, cmsFloat64Number Kh)
cmsFloat64Number a_p = (1 + G ) * a1;
cmsFloat64Number b_p = b1;
cmsFloat64Number C_p = sqrt( Sqr(a_p) + Sqr(b_p));
- cmsFloat64Number h_p = atan2deg(b_p, a_p);
-
+ cmsFloat64Number h_p = atan2deg(b_p, a_p);
+
cmsFloat64Number a_ps = (1 + G) * as;
cmsFloat64Number b_ps = bs;
cmsFloat64Number C_ps = sqrt(Sqr(a_ps) + Sqr(b_ps));
cmsFloat64Number h_ps = atan2deg(b_ps, a_ps);
-
+
cmsFloat64Number meanC_p =(C_p + C_ps) / 2;
cmsFloat64Number hps_plus_hp = h_ps + h_p;
cmsFloat64Number hps_minus_hp = h_ps - h_p;
- cmsFloat64Number meanh_p = fabs(hps_minus_hp) <= 180.000001 ? (hps_plus_hp)/2 :
- (hps_plus_hp) < 360 ? (hps_plus_hp + 360)/2 :
+ cmsFloat64Number meanh_p = fabs(hps_minus_hp) <= 180.000001 ? (hps_plus_hp)/2 :
+ (hps_plus_hp) < 360 ? (hps_plus_hp + 360)/2 :
(hps_plus_hp - 360)/2;
cmsFloat64Number delta_h = (hps_minus_hp) <= -180.000001 ? (hps_minus_hp + 360) :
- (hps_minus_hp) > 180 ? (hps_minus_hp - 360) :
+ (hps_minus_hp) > 180 ? (hps_minus_hp - 360) :
(hps_minus_hp);
cmsFloat64Number delta_L = (Ls - L1);
cmsFloat64Number delta_C = (C_ps - C_p );
cmsFloat64Number delta_H =2 * sqrt(C_ps*C_p) * sin(RADIANS(delta_h) / 2);
- cmsFloat64Number T = 1 - 0.17 * cos(RADIANS(meanh_p-30))
- + 0.24 * cos(RADIANS(2*meanh_p))
- + 0.32 * cos(RADIANS(3*meanh_p + 6))
+ cmsFloat64Number T = 1 - 0.17 * cos(RADIANS(meanh_p-30))
+ + 0.24 * cos(RADIANS(2*meanh_p))
+ + 0.32 * cos(RADIANS(3*meanh_p + 6))
- 0.2 * cos(RADIANS(4*meanh_p - 63));
cmsFloat64Number Sl = 1 + (0.015 * Sqr((Ls + L1) /2- 50) )/ sqrt(20 + Sqr( (Ls+L1)/2 - 50) );
cmsFloat64Number Rt = -sin(2 * RADIANS(delta_ro)) * Rc;
- cmsFloat64Number deltaE00 = sqrt( Sqr(delta_L /(Sl * Kl)) +
- Sqr(delta_C/(Sc * Kc)) +
- Sqr(delta_H/(Sh * Kh)) +
+ cmsFloat64Number deltaE00 = sqrt( Sqr(delta_L /(Sl * Kl)) +
+ Sqr(delta_C/(Sc * Kc)) +
+ Sqr(delta_H/(Sh * Kh)) +
Rt*(delta_C/(Sc * Kc)) * (delta_H / (Sh * Kh)));
return deltaE00;
// HighResPrecalc is maximum resolution
if (dwFlags & cmsFLAGS_HIGHRESPRECALC) {
- if (nChannels > 4)
+ if (nChannels > 4)
return 7; // 7 for Hifi
if (nChannels == 4) // 23 for CMYK
return 23;
-
- return 49; // 49 for RGB and others
+
+ return 49; // 49 for RGB and others
}
// LowResPrecal is lower resolution
if (dwFlags & cmsFLAGS_LOWRESPRECALC) {
-
- if (nChannels > 4)
+
+ if (nChannels > 4)
return 6; // 6 for more than 4 channels
- if (nChannels == 1)
+ if (nChannels == 1)
return 33; // For monochrome
return 17; // 17 for remaining
}
// Default values
- if (nChannels > 4)
+ if (nChannels > 4)
return 7; // 7 for Hifi
if (nChannels == 4)
return 17; // 17 for CMYK
- return 33; // 33 for RGB
+ return 33; // 33 for RGB
}
-cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
- cmsUInt16Number **White,
+cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
+ cmsUInt16Number **White,
cmsUInt16Number **Black,
cmsUInt32Number *nOutputs)
{
if (Black) *Black = Grayblack;
if (nOutputs) *nOutputs = 1;
return TRUE;
-
+
case cmsSigRgbData: if (White) *White = RGBwhite;
if (Black) *Black = RGBblack;
if (nOutputs) *nOutputs = 3;
return FALSE;
}
-
+
// Several utilities -------------------------------------------------------
int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace)
-{
+{
switch (ProfileSpace) {
-
+
case cmsSigGrayData: return PT_GRAY;
case cmsSigRgbData: return PT_RGB;
case cmsSigCmyData: return PT_CMY;
case cmsSigHsvData: return PT_HSV;
case cmsSigHlsData: return PT_HLS;
case cmsSigYxyData: return PT_Yxy;
-
+
case cmsSig1colorData:
case cmsSigMCH1Data: return PT_MCH1;
-
+
case cmsSig2colorData:
case cmsSigMCH2Data: return PT_MCH2;
-
+
case cmsSig3colorData:
case cmsSigMCH3Data: return PT_MCH3;
-
+
case cmsSig4colorData:
case cmsSigMCH4Data: return PT_MCH4;
-
+
case cmsSig5colorData:
case cmsSigMCH5Data: return PT_MCH5;
-
+
case cmsSig6colorData:
case cmsSigMCH6Data: return PT_MCH6;
-
+
case cmsSigMCH7Data:
case cmsSig7colorData:return PT_MCH7;
-
+
case cmsSigMCH8Data:
case cmsSig8colorData:return PT_MCH8;
-
+
case cmsSigMCH9Data:
case cmsSig9colorData:return PT_MCH9;
-
+
case cmsSigMCHAData:
case cmsSig10colorData:return PT_MCH10;
-
+
case cmsSigMCHBData:
case cmsSig11colorData:return PT_MCH11;
-
+
case cmsSigMCHCData:
case cmsSig12colorData:return PT_MCH12;
-
+
case cmsSigMCHDData:
case cmsSig13colorData:return PT_MCH13;
-
+
case cmsSigMCHEData:
case cmsSig14colorData:return PT_MCH14;
-
+
case cmsSigMCHFData:
case cmsSig15colorData:return PT_MCH15;
-
+
default: return (cmsColorSpaceSignature) (-1);
}
}
{
switch (ColorSpace) {
+ case cmsSigMCH1Data:
+ case cmsSig1colorData:
case cmsSigGrayData: return 1;
+ case cmsSigMCH2Data:
case cmsSig2colorData: return 2;
-
+
case cmsSigXYZData:
case cmsSigLabData:
case cmsSigLuvData:
case cmsSigYCbCrData:
case cmsSigYxyData:
- case cmsSigRgbData:
+ case cmsSigRgbData:
case cmsSigHsvData:
case cmsSigHlsData:
- case cmsSigCmyData:
+ case cmsSigCmyData:
+ case cmsSigMCH3Data:
case cmsSig3colorData: return 3;
-
+
case cmsSigLuvKData:
case cmsSigCmykData:
+ case cmsSigMCH4Data:
case cmsSig4colorData: return 4;
case cmsSigMCH5Data:
- case cmsSig5colorData: return 5;
+ case cmsSig5colorData: return 5;
- case cmsSigMCH6Data:
+ case cmsSigMCH6Data:
case cmsSig6colorData: return 6;
-
+
case cmsSigMCH7Data:
case cmsSig7colorData: return 7;
case cmsSigMCHBData:
case cmsSig11colorData: return 11;
-
+
case cmsSigMCHCData:
case cmsSig12colorData: return 12;