|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (c) 1999 Matthias Elter (me@kde.org)
|
|
|
|
Copyright (c) 2001-2002 Igor Jansen (rm@kde.org)
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library 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
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "koColor.h"
|
|
|
|
#include "kdebug.h"
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
KoColor::KoColor()
|
|
|
|
{
|
|
|
|
// initialise to black
|
|
|
|
mNative = csRGB;
|
|
|
|
// RGB
|
|
|
|
mR = 0;
|
|
|
|
mG = 0;
|
|
|
|
mB = 0;
|
|
|
|
// HSV
|
|
|
|
mH = mV = 0;
|
|
|
|
mS = 100;
|
|
|
|
// CMYK
|
|
|
|
mC = 0;
|
|
|
|
mY = 0;
|
|
|
|
mM = 0;
|
|
|
|
mK = 0;
|
|
|
|
// Lab
|
|
|
|
mL = 0;
|
|
|
|
ma = 0;
|
|
|
|
mB = 0;
|
|
|
|
rgbChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
KoColor::KoColor(int a, int b, int c, cSpace m)
|
|
|
|
{
|
|
|
|
switch(m)
|
|
|
|
{
|
|
|
|
case csRGB:
|
|
|
|
mR = a;
|
|
|
|
mG = b;
|
|
|
|
mB = c;
|
|
|
|
mNative = csRGB;
|
|
|
|
rgbChanged();
|
|
|
|
break;
|
|
|
|
case csHSV:
|
|
|
|
mH = a;
|
|
|
|
mS = b;
|
|
|
|
mV = c;
|
|
|
|
mNative = csHSV;
|
|
|
|
hsvChanged();
|
|
|
|
break;
|
|
|
|
case csLab:
|
|
|
|
mL = a;
|
|
|
|
ma = b;
|
|
|
|
mB = c;
|
|
|
|
mNative = csLab;
|
|
|
|
labChanged();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
mR = 0;
|
|
|
|
mG = 0;
|
|
|
|
mB = 0;
|
|
|
|
mNative = csRGB;
|
|
|
|
rgbChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KoColor::KoColor(int c, int m, int y, int k)
|
|
|
|
{
|
|
|
|
mC = c;
|
|
|
|
mM = m;
|
|
|
|
mY = y;
|
|
|
|
mK = k;
|
|
|
|
mNative = csCMYK;
|
|
|
|
cmykChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
KoColor::KoColor(const TQColor &c)
|
|
|
|
{
|
|
|
|
mR = c.red();
|
|
|
|
mG = c.green();
|
|
|
|
mB = c.blue();
|
|
|
|
mNative = csRGB;
|
|
|
|
rgbChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
KoColor::KoColor(const TQString &name)
|
|
|
|
{
|
|
|
|
setNamedColor(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::R() const
|
|
|
|
{
|
|
|
|
if(!mRGBvalid)
|
|
|
|
calcRGB();
|
|
|
|
return mR;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::G() const
|
|
|
|
{
|
|
|
|
if(!mRGBvalid)
|
|
|
|
calcRGB();
|
|
|
|
return mG;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::B() const
|
|
|
|
{
|
|
|
|
if(!mRGBvalid)
|
|
|
|
calcRGB();
|
|
|
|
return mB;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::H() const
|
|
|
|
{
|
|
|
|
if(!mHSVvalid)
|
|
|
|
calcHSV();
|
|
|
|
return mH;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::S() const
|
|
|
|
{
|
|
|
|
if(!mHSVvalid)
|
|
|
|
calcHSV();
|
|
|
|
return mS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::V() const
|
|
|
|
{
|
|
|
|
if(!mHSVvalid)
|
|
|
|
calcHSV();
|
|
|
|
return mV;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::C() const
|
|
|
|
{
|
|
|
|
if(!mCMYKvalid)
|
|
|
|
calcCMYK();
|
|
|
|
return mC;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::M() const
|
|
|
|
{
|
|
|
|
if(!mCMYKvalid)
|
|
|
|
calcCMYK();
|
|
|
|
return mM;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::Y() const
|
|
|
|
{
|
|
|
|
if(!mCMYKvalid)
|
|
|
|
calcCMYK();
|
|
|
|
return mY;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::K() const
|
|
|
|
{
|
|
|
|
if(!mCMYKvalid)
|
|
|
|
calcCMYK();
|
|
|
|
return mK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::L() const
|
|
|
|
{
|
|
|
|
if(!mLABvalid)
|
|
|
|
calcLAB();
|
|
|
|
return mL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::a() const
|
|
|
|
{
|
|
|
|
if(!mLABvalid)
|
|
|
|
calcLAB();
|
|
|
|
return ma;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::b() const
|
|
|
|
{
|
|
|
|
if(!mLABvalid)
|
|
|
|
calcLAB();
|
|
|
|
return mB;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::rgb(int *R, int *G, int *B) const
|
|
|
|
{
|
|
|
|
if(!mRGBvalid)
|
|
|
|
calcRGB();
|
|
|
|
*R = mR;
|
|
|
|
*G = mG;
|
|
|
|
*B = mB;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::hsv(int *H, int *S, int *V) const
|
|
|
|
{
|
|
|
|
if(!mHSVvalid)
|
|
|
|
calcHSV();
|
|
|
|
*H = mH;
|
|
|
|
*S = mS;
|
|
|
|
*V = mV;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::lab(int *L, int *a, int *b) const
|
|
|
|
{
|
|
|
|
if(!mLABvalid)
|
|
|
|
calcLAB();
|
|
|
|
*L = mL;
|
|
|
|
*a = ma;
|
|
|
|
*b = mB;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::cmyk(int *C, int *M, int *Y, int *K) const
|
|
|
|
{
|
|
|
|
if(!mCMYKvalid)
|
|
|
|
calcCMYK();
|
|
|
|
*C = mC;
|
|
|
|
*M = mM;
|
|
|
|
*Y = mY;
|
|
|
|
*K = mK;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KoColor::name() const
|
|
|
|
{
|
|
|
|
TQString s;
|
|
|
|
switch(mNative)
|
|
|
|
{
|
|
|
|
case csRGB:
|
|
|
|
s.sprintf("#%02x%02x%02x", R(), G(), B());
|
|
|
|
break;
|
|
|
|
case csHSV:
|
|
|
|
s.sprintf("$%02x%02x%02x", H(), S(), V());
|
|
|
|
break;
|
|
|
|
case csCMYK:
|
|
|
|
s.sprintf("@%02x%02x%02x%02x", C(), M(), Y(), K());
|
|
|
|
break;
|
|
|
|
case csLab:
|
|
|
|
s.sprintf("*%02x%02x%02x", L(), a(), b());
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
s.sprintf("#%02x%02x%02x", R(), G(), B());
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQColor KoColor::color() const
|
|
|
|
{
|
|
|
|
if(!mRGBvalid)
|
|
|
|
calcRGB();
|
|
|
|
return TQColor(mR, mG, mB);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::setRGB(int R, int G, int B)
|
|
|
|
{
|
|
|
|
mR = R;
|
|
|
|
mG = G;
|
|
|
|
mB = B;
|
|
|
|
mNative = csRGB;
|
|
|
|
rgbChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::setHSV(int H, int S, int V)
|
|
|
|
{
|
|
|
|
mH = H;
|
|
|
|
mS = S;
|
|
|
|
mV = V;
|
|
|
|
mNative = csHSV;
|
|
|
|
hsvChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::setLab(int L, int a, int b)
|
|
|
|
{
|
|
|
|
mL = L;
|
|
|
|
ma = a;
|
|
|
|
mB = b;
|
|
|
|
mNative = csLab;
|
|
|
|
labChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::setCMYK(int C, int M, int Y, int K)
|
|
|
|
{
|
|
|
|
mC = C;
|
|
|
|
mM = M;
|
|
|
|
mY = Y;
|
|
|
|
mK = K;
|
|
|
|
mNative = csCMYK;
|
|
|
|
cmykChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::setNamedColor(const TQString &name)
|
|
|
|
{
|
|
|
|
switch(name[0])
|
|
|
|
{
|
|
|
|
case '#':
|
|
|
|
mR = (hex2int(name[1]) << 4) + hex2int(name[2]);
|
|
|
|
mG = (hex2int(name[3]) << 4) + hex2int(name[4]);
|
|
|
|
mB = (hex2int(name[5]) << 4) + hex2int(name[6]);
|
|
|
|
mNative = csRGB;
|
|
|
|
rgbChanged();
|
|
|
|
break;
|
|
|
|
case '$':
|
|
|
|
mH = (hex2int(name[1]) << 4) + hex2int(name[2]);
|
|
|
|
mS = (hex2int(name[3]) << 4) + hex2int(name[4]);
|
|
|
|
mV = (hex2int(name[5]) << 4) + hex2int(name[6]);
|
|
|
|
mNative = csHSV;
|
|
|
|
hsvChanged();
|
|
|
|
break;
|
|
|
|
case '@':
|
|
|
|
mC = (hex2int(name[1]) << 4) + hex2int(name[2]);
|
|
|
|
mM = (hex2int(name[3]) << 4) + hex2int(name[4]);
|
|
|
|
mY = (hex2int(name[5]) << 4) + hex2int(name[6]);
|
|
|
|
mK = (hex2int(name[7]) << 4) + hex2int(name[8]);
|
|
|
|
mNative = csCMYK;
|
|
|
|
cmykChanged();
|
|
|
|
break;
|
|
|
|
case '*':
|
|
|
|
mL = (hex2int(name[1]) << 4) + hex2int(name[2]);
|
|
|
|
ma = (hex2int(name[3]) << 4) + hex2int(name[4]);
|
|
|
|
mb = (hex2int(name[5]) << 4) + hex2int(name[6]);
|
|
|
|
mNative = csLab;
|
|
|
|
labChanged();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
mR = 0;
|
|
|
|
mG = 0;
|
|
|
|
mB = 0;
|
|
|
|
mNative = csRGB;
|
|
|
|
rgbChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::setColor(const TQColor &c)
|
|
|
|
{
|
|
|
|
mR = c.red();
|
|
|
|
mG = c.green();
|
|
|
|
mB = c.blue();
|
|
|
|
mNative = csRGB;
|
|
|
|
rgbChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::RGBtoHSV(int R, int G, int B, int *H, int *S, int *V)
|
|
|
|
{
|
|
|
|
unsigned int max = R;
|
|
|
|
unsigned int min = R;
|
|
|
|
unsigned char maxValue = 0; // r = 0, g = 1, b = 2
|
|
|
|
|
|
|
|
// find maximum and minimum RGB values
|
|
|
|
if(static_cast<unsigned int>(G) > max)
|
|
|
|
{
|
|
|
|
max = G;
|
|
|
|
maxValue = 1;
|
|
|
|
}
|
|
|
|
if(static_cast<unsigned int>(B) > max)
|
|
|
|
{
|
|
|
|
max = B;
|
|
|
|
maxValue = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(static_cast<unsigned int>(G) < min)
|
|
|
|
min = G;
|
|
|
|
if(static_cast<unsigned int>(B) < min )
|
|
|
|
min = B;
|
|
|
|
|
|
|
|
int delta = max - min;
|
|
|
|
*V = max; // value
|
|
|
|
*S = max ? (510 * delta + max) / ( 2 * max) : 0; // saturation
|
|
|
|
|
|
|
|
// calc hue
|
|
|
|
if(*S == 0)
|
|
|
|
*H = -1; // undefined hue
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch(maxValue)
|
|
|
|
{
|
|
|
|
case 0: // red
|
|
|
|
if(G >= B)
|
|
|
|
*H = (120 * (G - B) + delta) / (2 * delta);
|
|
|
|
else
|
|
|
|
*H = (120 * (G - B + delta) + delta) / (2 * delta) + 300;
|
|
|
|
break;
|
|
|
|
case 1: // green
|
|
|
|
if(B > R)
|
|
|
|
*H = 120 + (120 * (B - R) + delta) / (2 * delta);
|
|
|
|
else
|
|
|
|
*H = 60 + (120 * (B - R + delta) + delta) / (2 * delta);
|
|
|
|
break;
|
|
|
|
case 2: // blue
|
|
|
|
if(R > G)
|
|
|
|
*H = 240 + (120 * (R - G) + delta) / (2 * delta);
|
|
|
|
else
|
|
|
|
*H = 180 + (120 * (R - G + delta) + delta) / (2 * delta);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::RGBtoLAB(int R, int G, int B, int *L, int *a, int *b)
|
|
|
|
{
|
|
|
|
// Convert between RGB and CIE-Lab color spaces
|
|
|
|
// Uses ITU-R recommendation BT.709 with D65 as reference white.
|
|
|
|
// algorithm contributed by "Mark A. Ruzon" <ruzon@CS.Stanford.EDU>
|
|
|
|
|
|
|
|
double X, Y, Z, fX, fY, fZ;
|
|
|
|
|
|
|
|
X = 0.412453 * R + 0.357580 * G + 0.180423 * B;
|
|
|
|
Y = 0.212671 * R + 0.715160 * G + 0.072169 * B;
|
|
|
|
Z = 0.019334 * R + 0.119193 * G + 0.950227 * B;
|
|
|
|
|
|
|
|
X /= (255 * 0.950456);
|
|
|
|
Y /= 255;
|
|
|
|
Z /= (255 * 1.088754);
|
|
|
|
|
|
|
|
if(Y > 0.008856)
|
|
|
|
{
|
|
|
|
fY = pow(Y, 1.0 / 3.0);
|
|
|
|
*L = static_cast<int>(116.0 * fY - 16.0 + 0.5);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fY = 7.787 * Y + 16.0 / 116.0;
|
|
|
|
*L = static_cast<int>(903.3 * Y + 0.5);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(X > 0.008856)
|
|
|
|
fX = pow(X, 1.0 / 3.0);
|
|
|
|
else
|
|
|
|
fX = 7.787 * X + 16.0 / 116.0;
|
|
|
|
|
|
|
|
if(Z > 0.008856)
|
|
|
|
fZ = pow(Z, 1.0 / 3.0);
|
|
|
|
else
|
|
|
|
fZ = 7.787 * Z + 16.0 / 116.0;
|
|
|
|
|
|
|
|
*a = static_cast<int>(500.0 * (fX - fY) + 0.5);
|
|
|
|
*b = static_cast<int>(200.0 * (fY - fZ) + 0.5);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::RGBtoCMYK(int R, int G, int B, int *C, int *M, int *Y, int *K)
|
|
|
|
{
|
|
|
|
// XXX: these algorithms aren't the best. See www.littlecms.com
|
|
|
|
// for a suitable library, or the posting by Leo Rosenthol for
|
|
|
|
// a better, but slower algorithm at
|
|
|
|
// http://lists.kde.org/?l=koffice-devel&m=106698241227054&w=2
|
|
|
|
|
|
|
|
*C = 255 - R;
|
|
|
|
*M = 255 - G;
|
|
|
|
*Y = 255 - B;
|
|
|
|
|
|
|
|
int min = (*C < *M) ? *C : *M;
|
|
|
|
*K = (min < *Y) ? min : *Y;
|
|
|
|
|
|
|
|
*C -= *K;
|
|
|
|
*M -= *K;
|
|
|
|
*Y -= *K;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KoColor::HSVtoRGB(int H, int S, int V, int *R, int *G, int *B)
|
|
|
|
{
|
|
|
|
*R = *G = *B = V;
|
|
|
|
|
|
|
|
if(S != 0 && H != -1) // chromatic
|
|
|
|
{
|
|
|
|
if(H >= 360) // angle > 360
|
|
|
|
H %= 360;
|
|
|
|
|
|
|
|
unsigned int f = H % 60;
|
|
|
|
H /= 60;
|
|
|
|
unsigned int p = static_cast<unsigned int>(2*V*(255-S)+255)/510;
|
|
|
|
unsigned int q, t;
|
|
|
|
|
|
|
|
if(H & 1)
|
|
|
|
{
|
|
|
|
q = static_cast<unsigned int>(2 * V * (15300 - S * f) + 15300) / 30600;
|
|
|
|
switch(H)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
*R = static_cast<int>(q);
|
|
|
|
*G = static_cast<int>(V);
|
|
|
|
*B = static_cast<int>(p);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
*R = static_cast<int>(p);
|
|
|
|
*G = static_cast<int>(q);
|
|
|
|
*B = static_cast<int>(V);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
*R = static_cast<int>(V);
|
|
|
|
*G = static_cast<int>(p);
|
|
|
|
*B = static_cast<int>(q);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
t = static_cast<unsigned int>(2 * V * (15300 - (S * (60 - f))) + 15300) / 30600;
|
|
|
|
switch(H)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
*R = static_cast<int>(V);
|
|
|
|
*G = static_cast<int>(t);
|
|
|
|
*B = static_cast<int>(p);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
*R = static_cast<int>(p);
|
|
|
|
*G = static_cast<int>(V);
|
|
|
|
*B = static_cast<int>(t);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
*R = static_cast<int>(t);
|
|
|
|
*G = static_cast<int>(p);
|
|
|
|
*B = static_cast<int>(V);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::HSVtoLAB(int H, int S, int V, int *L, int *a, int *b)
|
|
|
|
{
|
|
|
|
int R, G, B;
|
|
|
|
HSVtoRGB(H, S, V, &R, &G, &B);
|
|
|
|
RGBtoLAB(R, G, B, L, a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::HSVtoCMYK(int H, int S, int V, int *C, int *M, int *Y, int*K)
|
|
|
|
{
|
|
|
|
int R, G, B;
|
|
|
|
HSVtoRGB(H, S, V, &R, &G, &B);
|
|
|
|
RGBtoCMYK(R, G, B, C, M, Y, K);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::LABtoRGB(int L, int a, int b, int *R, int *G, int *B)
|
|
|
|
{
|
|
|
|
// Convert between RGB and CIE-Lab color spaces
|
|
|
|
// Uses ITU-R recommendation BT.709 with D65 as reference white.
|
|
|
|
// algorithm contributed by "Mark A. Ruzon" <ruzon@CS.Stanford.EDU>
|
|
|
|
|
|
|
|
double X, Y, Z, fX, fY, fZ;
|
|
|
|
int RR, GG, BB;
|
|
|
|
|
|
|
|
fY = pow((L + 16.0) / 116.0, 3.0);
|
|
|
|
if(fY < 0.008856)
|
|
|
|
fY = L / 903.3;
|
|
|
|
Y = fY;
|
|
|
|
|
|
|
|
if(fY > 0.008856)
|
|
|
|
fY = pow(fY, 1.0 / 3.0);
|
|
|
|
else
|
|
|
|
fY = 7.787 * fY + 16.0 / 116.0;
|
|
|
|
|
|
|
|
fX = a / 500.0 + fY;
|
|
|
|
if(fX > 0.206893)
|
|
|
|
X = pow(fX, 3.0);
|
|
|
|
else
|
|
|
|
X = (fX - 16.0 / 116.0) / 7.787;
|
|
|
|
|
|
|
|
fZ = fY - b / 200.0;
|
|
|
|
if(fZ > 0.206893)
|
|
|
|
Z = pow(fZ, 3.0);
|
|
|
|
else
|
|
|
|
Z = (fZ - 16.0/116.0) / 7.787;
|
|
|
|
|
|
|
|
X *= 0.950456 * 255;
|
|
|
|
Y *= 255;
|
|
|
|
Z *= 1.088754 * 255;
|
|
|
|
|
|
|
|
RR = static_cast<int>(3.240479 * X - 1.537150 * Y - 0.498535 * Z + 0.5);
|
|
|
|
GG = static_cast<int>(-0.969256 * X + 1.875992 * Y + 0.041556 * Z + 0.5);
|
|
|
|
BB = static_cast<int>(0.055648 * X - 0.204043 * Y + 1.057311 * Z + 0.5);
|
|
|
|
|
|
|
|
*R = RR < 0 ? 0 : RR > 255 ? 255 : RR;
|
|
|
|
*G = GG < 0 ? 0 : GG > 255 ? 255 : GG;
|
|
|
|
*B = BB < 0 ? 0 : BB > 255 ? 255 : BB;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::LABtoHSV(int L, int a, int b, int *H, int *S, int *V)
|
|
|
|
{
|
|
|
|
int R, G, B;
|
|
|
|
LABtoRGB(L, a, b, &R, &G, &B);
|
|
|
|
RGBtoHSV(R, G, B, H, S, V);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::LABtoCMYK(int L, int a, int b, int *C, int *M, int *Y, int*K)
|
|
|
|
{
|
|
|
|
int R, G, B;
|
|
|
|
LABtoRGB(L, a, b, &R, &G, &B);
|
|
|
|
RGBtoCMYK(R, G, B, C, M, Y, K);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::CMYKtoRGB(int C, int M, int Y, int K, int *R, int *G, int *B)
|
|
|
|
{
|
|
|
|
*R = 255 - (C + K);
|
|
|
|
*G = 255 - (M + K);
|
|
|
|
*B = 255 - (Y + K);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::CMYKtoHSV(int C, int M, int Y, int K, int *H, int *S, int *V)
|
|
|
|
{
|
|
|
|
int R, G, B;
|
|
|
|
CMYKtoRGB(C, M, Y, K, &R, &G, &B);
|
|
|
|
RGBtoHSV(R, G, B, H, S, V);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::CMYKtoLAB(int C, int M, int Y, int K, int *L, int *a, int *b)
|
|
|
|
{
|
|
|
|
int R, G, B;
|
|
|
|
CMYKtoRGB(C, M, Y, K, &R, &G, &B);
|
|
|
|
RGBtoLAB(R, G, B, L, a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
int KoColor::hex2int(TQChar c)
|
|
|
|
{
|
|
|
|
if(c.isDigit())
|
|
|
|
return c.digitValue();
|
|
|
|
else if('A' <= (int)c && (int)c <= 'F')
|
|
|
|
return c - 'A' + 10;
|
|
|
|
else if('a' <= (int)c && (int)c <= 'f')
|
|
|
|
return c - 'a' + 10;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::calcRGB() const
|
|
|
|
{
|
|
|
|
switch(mNative)
|
|
|
|
{
|
|
|
|
case csHSV:
|
|
|
|
HSVtoRGB(mH, mS, mV, &mR, &mG, &mB);
|
|
|
|
break;
|
|
|
|
case csLab:
|
|
|
|
LABtoRGB(mL, ma, mB, &mR, &mG, &mB);
|
|
|
|
break;
|
|
|
|
case csCMYK:
|
|
|
|
CMYKtoRGB(mC, mM, mY, mK, &mR, &mG, &mB);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mRGBvalid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::calcHSV() const
|
|
|
|
{
|
|
|
|
switch(mNative)
|
|
|
|
{
|
|
|
|
case csRGB:
|
|
|
|
RGBtoHSV(mR, mG, mB, &mH, &mS, &mV);
|
|
|
|
break;
|
|
|
|
case csLab:
|
|
|
|
LABtoHSV(mL, ma, mB, &mH, &mS, &mV);
|
|
|
|
break;
|
|
|
|
case csCMYK:
|
|
|
|
CMYKtoHSV(mC, mM, mY, mK, &mH, &mS, &mV);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mHSVvalid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::calcCMYK() const
|
|
|
|
{
|
|
|
|
switch(mNative)
|
|
|
|
{
|
|
|
|
case csRGB:
|
|
|
|
RGBtoCMYK(mR, mG, mB, &mC, &mM, &mY, &mK);
|
|
|
|
break;
|
|
|
|
case csLab:
|
|
|
|
LABtoCMYK(mL, ma, mB, &mC, &mM, &mY, &mK);
|
|
|
|
break;
|
|
|
|
case csHSV:
|
|
|
|
HSVtoCMYK(mH, mS, mV, &mC, &mM, &mY, &mK);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mCMYKvalid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::calcLAB() const
|
|
|
|
{
|
|
|
|
switch(mNative)
|
|
|
|
{
|
|
|
|
case csRGB:
|
|
|
|
RGBtoLAB(mR, mG, mB, &mL, &ma, &mB);
|
|
|
|
break;
|
|
|
|
case csHSV:
|
|
|
|
HSVtoLAB(mH, mS, mV, &mL, &ma, &mB);
|
|
|
|
break;
|
|
|
|
case csCMYK:
|
|
|
|
CMYKtoLAB(mC, mM, mY, mK, &mL, &ma, &mB);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mLABvalid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::rgbChanged() const
|
|
|
|
{
|
|
|
|
mRGBvalid = true;
|
|
|
|
mHSVvalid = false;
|
|
|
|
mCMYKvalid = false;
|
|
|
|
mLABvalid = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::hsvChanged() const
|
|
|
|
{
|
|
|
|
mRGBvalid = false;
|
|
|
|
mHSVvalid = true;
|
|
|
|
mCMYKvalid = false;
|
|
|
|
mLABvalid = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::cmykChanged() const
|
|
|
|
{
|
|
|
|
mRGBvalid = false;
|
|
|
|
mHSVvalid = false;
|
|
|
|
mCMYKvalid = true;
|
|
|
|
mLABvalid = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoColor::labChanged() const
|
|
|
|
{
|
|
|
|
mRGBvalid = false;
|
|
|
|
mHSVvalid = false;
|
|
|
|
mCMYKvalid = false;
|
|
|
|
mLABvalid = true;
|
|
|
|
}
|