00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "koColor.h"
00022
#include "kdebug.h"
00023
#include <cmath>
00024
00025 KoColor::KoColor()
00026 {
00027
00028 mNative = csRGB;
00029
00030 mR = 0;
00031 mG = 0;
00032 mB = 0;
00033
00034 mH = mV = 0;
00035 mS = 100;
00036
00037 mC = 0;
00038 mY = 0;
00039 mM = 0;
00040 mK = 0;
00041
00042 mL = 0;
00043 ma = 0;
00044 mB = 0;
00045 rgbChanged();
00046 }
00047
00048 KoColor::KoColor(
int a,
int b,
int c, cSpace m)
00049 {
00050
switch(m)
00051 {
00052
case csRGB:
00053 mR = a;
00054 mG = b;
00055 mB = c;
00056 mNative = csRGB;
00057 rgbChanged();
00058
break;
00059
case csHSV:
00060 mH = a;
00061 mS = b;
00062 mV = c;
00063 mNative = csHSV;
00064 hsvChanged();
00065
break;
00066
case csLab:
00067 mL = a;
00068 ma = b;
00069 mB = c;
00070 mNative = csLab;
00071 labChanged();
00072
break;
00073
default:
00074 mR = 0;
00075 mG = 0;
00076 mB = 0;
00077 mNative = csRGB;
00078 rgbChanged();
00079 }
00080 }
00081
00082 KoColor::KoColor(
int c,
int m,
int y,
int k)
00083 {
00084 mC = c;
00085 mM = m;
00086 mY = y;
00087 mK = k;
00088 mNative = csCMYK;
00089 cmykChanged();
00090 }
00091
00092 KoColor::KoColor(
const QColor &c)
00093 {
00094 mR = c.red();
00095 mG = c.green();
00096 mB = c.blue();
00097 mNative = csRGB;
00098 rgbChanged();
00099 }
00100
00101 KoColor::KoColor(
const QString &name)
00102 {
00103 setNamedColor(name);
00104 }
00105
00106
int KoColor::R()
const
00107
{
00108
if(!mRGBvalid)
00109 calcRGB();
00110
return mR;
00111 }
00112
00113
int KoColor::G()
const
00114
{
00115
if(!mRGBvalid)
00116 calcRGB();
00117
return mG;
00118 }
00119
00120
int KoColor::B()
const
00121
{
00122
if(!mRGBvalid)
00123 calcRGB();
00124
return mB;
00125 }
00126
00127
int KoColor::H()
const
00128
{
00129
if(!mHSVvalid)
00130 calcHSV();
00131
return mH;
00132 }
00133
00134
int KoColor::S()
const
00135
{
00136
if(!mHSVvalid)
00137 calcHSV();
00138
return mS;
00139 }
00140
00141
int KoColor::V()
const
00142
{
00143
if(!mHSVvalid)
00144 calcHSV();
00145
return mV;
00146 }
00147
00148
int KoColor::C()
const
00149
{
00150
if(!mCMYKvalid)
00151 calcCMYK();
00152
return mC;
00153 }
00154
00155
int KoColor::M()
const
00156
{
00157
if(!mCMYKvalid)
00158 calcCMYK();
00159
return mM;
00160 }
00161
00162
int KoColor::Y()
const
00163
{
00164
if(!mCMYKvalid)
00165 calcCMYK();
00166
return mY;
00167 }
00168
00169
int KoColor::K()
const
00170
{
00171
if(!mCMYKvalid)
00172 calcCMYK();
00173
return mK;
00174 }
00175
00176
int KoColor::L()
const
00177
{
00178
if(!mLABvalid)
00179 calcLAB();
00180
return mL;
00181 }
00182
00183
int KoColor::a()
const
00184
{
00185
if(!mLABvalid)
00186 calcLAB();
00187
return ma;
00188 }
00189
00190
int KoColor::b()
const
00191
{
00192
if(!mLABvalid)
00193 calcLAB();
00194
return mB;
00195 }
00196
00197
void KoColor::rgb(
int *R,
int *G,
int *B)
const
00198
{
00199
if(!mRGBvalid)
00200 calcRGB();
00201 *R = mR;
00202 *G = mG;
00203 *B = mB;
00204 }
00205
00206
void KoColor::hsv(
int *H,
int *S,
int *V)
const
00207
{
00208
if(!mHSVvalid)
00209 calcHSV();
00210 *H = mH;
00211 *S = mS;
00212 *V = mV;
00213 }
00214
00215
void KoColor::lab(
int *L,
int *a,
int *b)
const
00216
{
00217
if(!mLABvalid)
00218 calcLAB();
00219 *L = mL;
00220 *a = ma;
00221 *b = mB;
00222 }
00223
00224
void KoColor::cmyk(
int *C,
int *M,
int *Y,
int *K)
const
00225
{
00226
if(!mCMYKvalid)
00227 calcCMYK();
00228 *C = mC;
00229 *M = mM;
00230 *Y = mY;
00231 *K = mK;
00232 }
00233
00234
QString KoColor::name()
const
00235
{
00236
QString s;
00237
switch(mNative)
00238 {
00239
case csRGB:
00240 s.sprintf(
"#%02x%02x%02x", R(), G(), B());
00241
break;
00242
case csHSV:
00243 s.sprintf(
"$%02x%02x%02x", H(), S(), V());
00244
break;
00245
case csCMYK:
00246 s.sprintf(
"@%02x%02x%02x%02x", C(), M(), Y(), K());
00247
break;
00248
case csLab:
00249 s.sprintf(
"*%02x%02x%02x", L(), a(), b());
00250
break;
00251
default:
00252 s.sprintf(
"#%02x%02x%02x", R(), G(), B());
00253 }
00254
return s;
00255 }
00256
00257
QColor KoColor::color()
const
00258
{
00259
if(!mRGBvalid)
00260 calcRGB();
00261
return QColor(mR, mG, mB);
00262 }
00263
00264
void KoColor::setRGB(
int R,
int G,
int B)
00265 {
00266 mR = R;
00267 mG = G;
00268 mB = B;
00269 mNative = csRGB;
00270 rgbChanged();
00271 }
00272
00273
void KoColor::setHSV(
int H,
int S,
int V)
00274 {
00275 mH = H;
00276 mS = S;
00277 mV = V;
00278 mNative = csHSV;
00279 hsvChanged();
00280 }
00281
00282
void KoColor::setLab(
int L,
int a,
int b)
00283 {
00284 mL = L;
00285 ma = a;
00286 mB = b;
00287 mNative = csLab;
00288 labChanged();
00289 }
00290
00291
void KoColor::setCMYK(
int C,
int M,
int Y,
int K)
00292 {
00293 mC = C;
00294 mM = M;
00295 mY = Y;
00296 mK = K;
00297 mNative = csCMYK;
00298 cmykChanged();
00299 }
00300
00301
void KoColor::setNamedColor(
const QString &name)
00302 {
00303
switch(name[0])
00304 {
00305
case '#':
00306 mR = (hex2int(name[1]) << 4) + hex2int(name[2]);
00307 mG = (hex2int(name[3]) << 4) + hex2int(name[4]);
00308 mB = (hex2int(name[5]) << 4) + hex2int(name[6]);
00309 mNative = csRGB;
00310 rgbChanged();
00311
break;
00312
case '$':
00313 mH = (hex2int(name[1]) << 4) + hex2int(name[2]);
00314 mS = (hex2int(name[3]) << 4) + hex2int(name[4]);
00315 mV = (hex2int(name[5]) << 4) + hex2int(name[6]);
00316 mNative = csHSV;
00317 hsvChanged();
00318
break;
00319
case '@':
00320 mC = (hex2int(name[1]) << 4) + hex2int(name[2]);
00321 mM = (hex2int(name[3]) << 4) + hex2int(name[4]);
00322 mY = (hex2int(name[5]) << 4) + hex2int(name[6]);
00323 mK = (hex2int(name[7]) << 4) + hex2int(name[8]);
00324 mNative = csCMYK;
00325 cmykChanged();
00326
break;
00327
case '*':
00328 mL = (hex2int(name[1]) << 4) + hex2int(name[2]);
00329 ma = (hex2int(name[3]) << 4) + hex2int(name[4]);
00330 mb = (hex2int(name[5]) << 4) + hex2int(name[6]);
00331 mNative = csLab;
00332 labChanged();
00333
break;
00334
default:
00335 mR = 0;
00336 mG = 0;
00337 mB = 0;
00338 mNative = csRGB;
00339 rgbChanged();
00340 }
00341 }
00342
00343
void KoColor::setColor(
const QColor &c)
00344 {
00345 mR = c.red();
00346 mG = c.green();
00347 mB = c.blue();
00348 mNative = csRGB;
00349 rgbChanged();
00350 }
00351
00352
void KoColor::RGBtoHSV(
int R,
int G,
int B,
int *H,
int *S,
int *V)
00353 {
00354
unsigned int max = R;
00355
unsigned int min = R;
00356
unsigned char maxValue = 0;
00357
00358
00359
if(static_cast<unsigned int>(G) > max)
00360 {
00361 max = G;
00362 maxValue = 1;
00363 }
00364
if(static_cast<unsigned int>(B) > max)
00365 {
00366 max = B;
00367 maxValue = 2;
00368 }
00369
00370
if(static_cast<unsigned int>(G) < min)
00371 min = G;
00372
if(static_cast<unsigned int>(B) < min )
00373 min = B;
00374
00375
int delta = max - min;
00376 *V = max;
00377 *S = max ? (510 * delta + max) / ( 2 * max) : 0;
00378
00379
00380
if(*S == 0)
00381 *H = -1;
00382
else
00383 {
00384
switch(maxValue)
00385 {
00386
case 0:
00387
if(G >= B)
00388 *H = (120 * (G - B) + delta) / (2 * delta);
00389
else
00390 *H = (120 * (G - B + delta) + delta) / (2 * delta) + 300;
00391
break;
00392
case 1:
00393
if(B > R)
00394 *H = 120 + (120 * (B - R) + delta) / (2 * delta);
00395
else
00396 *H = 60 + (120 * (B - R + delta) + delta) / (2 * delta);
00397
break;
00398
case 2:
00399
if(R > G)
00400 *H = 240 + (120 * (R - G) + delta) / (2 * delta);
00401
else
00402 *H = 180 + (120 * (R - G + delta) + delta) / (2 * delta);
00403
break;
00404 }
00405 }
00406 }
00407
00408
void KoColor::RGBtoLAB(
int R,
int G,
int B,
int *L,
int *a,
int *b)
00409 {
00410
00411
00412
00413
00414
double X, Y, Z, fX, fY, fZ;
00415
00416 X = 0.412453 * R + 0.357580 * G + 0.180423 * B;
00417 Y = 0.212671 * R + 0.715160 * G + 0.072169 * B;
00418 Z = 0.019334 * R + 0.119193 * G + 0.950227 * B;
00419
00420 X /= (255 * 0.950456);
00421 Y /= 255;
00422 Z /= (255 * 1.088754);
00423
00424
if(Y > 0.008856)
00425 {
00426 fY = pow(Y, 1.0 / 3.0);
00427 *L = static_cast<int>(116.0 * fY - 16.0 + 0.5);
00428 }
00429
else
00430 {
00431 fY = 7.787 * Y + 16.0 / 116.0;
00432 *L = static_cast<int>(903.3 * Y + 0.5);
00433 }
00434
00435
if(X > 0.008856)
00436 fX = pow(X, 1.0 / 3.0);
00437
else
00438 fX = 7.787 * X + 16.0 / 116.0;
00439
00440
if(Z > 0.008856)
00441 fZ = pow(Z, 1.0 / 3.0);
00442
else
00443 fZ = 7.787 * Z + 16.0 / 116.0;
00444
00445 *a = static_cast<int>(500.0 * (fX - fY) + 0.5);
00446 *b = static_cast<int>(200.0 * (fY - fZ) + 0.5);
00447 }
00448
00449
void KoColor::RGBtoCMYK(
int R,
int G,
int B,
int *C,
int *M,
int *Y,
int *K)
00450 {
00451
00452
00453
00454
00455
00456 *C = 255 - R;
00457 *M = 255 - G;
00458 *Y = 255 - B;
00459
00460
int min = (*C < *M) ? *C : *M;
00461 *K = (min < *Y) ? min : *Y;
00462
00463 *C -= *K;
00464 *M -= *K;
00465 *Y -= *K;
00466
00467 }
00468
00469
00470
void KoColor::HSVtoRGB(
int H,
int S,
int V,
int *R,
int *G,
int *B)
00471 {
00472 *R = *G = *B = V;
00473
00474
if(S != 0 && H != -1)
00475 {
00476
if(H >= 360)
00477 H %= 360;
00478
00479
unsigned int f = H % 60;
00480 H /= 60;
00481
unsigned int p = static_cast<unsigned int>(2*V*(255-S)+255)/510;
00482
unsigned int q, t;
00483
00484
if(H & 1)
00485 {
00486 q = static_cast<unsigned int>(2 * V * (15300 - S * f) + 15300) / 30600;
00487
switch(H)
00488 {
00489
case 1:
00490 *R = static_cast<int>(q);
00491 *G = static_cast<int>(V);
00492 *B = static_cast<int>(p);
00493
break;
00494
case 3:
00495 *R = static_cast<int>(p);
00496 *G = static_cast<int>(q);
00497 *B = static_cast<int>(V);
00498
break;
00499
case 5:
00500 *R = static_cast<int>(V);
00501 *G = static_cast<int>(p);
00502 *B = static_cast<int>(q);
00503
break;
00504 }
00505 }
00506
else
00507 {
00508 t = static_cast<unsigned int>(2 * V * (15300 - (S * (60 - f))) + 15300) / 30600;
00509
switch(H)
00510 {
00511
case 0:
00512 *R = static_cast<int>(V);
00513 *G = static_cast<int>(t);
00514 *B = static_cast<int>(p);
00515
break;
00516
case 2:
00517 *R = static_cast<int>(p);
00518 *G = static_cast<int>(V);
00519 *B = static_cast<int>(t);
00520
break;
00521
case 4:
00522 *R = static_cast<int>(t);
00523 *G = static_cast<int>(p);
00524 *B = static_cast<int>(V);
00525
break;
00526 }
00527 }
00528 }
00529 }
00530
00531
void KoColor::HSVtoLAB(
int H,
int S,
int V,
int *L,
int *a,
int *b)
00532 {
00533
int R, G, B;
00534 HSVtoRGB(H, S, V, &R, &G, &B);
00535 RGBtoLAB(R, G, B, L, a, b);
00536 }
00537
00538
void KoColor::HSVtoCMYK(
int H,
int S,
int V,
int *C,
int *M,
int *Y,
int*K)
00539 {
00540
int R, G, B;
00541 HSVtoRGB(H, S, V, &R, &G, &B);
00542 RGBtoCMYK(R, G, B, C, M, Y, K);
00543 }
00544
00545
void KoColor::LABtoRGB(
int L,
int a,
int b,
int *R,
int *G,
int *B)
00546 {
00547
00548
00549
00550
00551
double X, Y, Z, fX, fY, fZ;
00552
int RR, GG, BB;
00553
00554 fY = pow((L + 16.0) / 116.0, 3.0);
00555
if(fY < 0.008856)
00556 fY = L / 903.3;
00557 Y = fY;
00558
00559
if(fY > 0.008856)
00560 fY = pow(fY, 1.0 / 3.0);
00561
else
00562 fY = 7.787 * fY + 16.0 / 116.0;
00563
00564 fX = a / 500.0 + fY;
00565
if(fX > 0.206893)
00566 X = pow(fX, 3.0);
00567
else
00568 X = (fX - 16.0 / 116.0) / 7.787;
00569
00570 fZ = fY - b / 200.0;
00571
if(fZ > 0.206893)
00572 Z = pow(fZ, 3.0);
00573
else
00574 Z = (fZ - 16.0/116.0) / 7.787;
00575
00576 X *= 0.950456 * 255;
00577 Y *= 255;
00578 Z *= 1.088754 * 255;
00579
00580 RR = static_cast<int>(3.240479 * X - 1.537150 * Y - 0.498535 * Z + 0.5);
00581 GG = static_cast<int>(-0.969256 * X + 1.875992 * Y + 0.041556 * Z + 0.5);
00582 BB = static_cast<int>(0.055648 * X - 0.204043 * Y + 1.057311 * Z + 0.5);
00583
00584 *R = RR < 0 ? 0 : RR > 255 ? 255 : RR;
00585 *G = GG < 0 ? 0 : GG > 255 ? 255 : GG;
00586 *B = BB < 0 ? 0 : BB > 255 ? 255 : BB;
00587 }
00588
00589
void KoColor::LABtoHSV(
int L,
int a,
int b,
int *H,
int *S,
int *V)
00590 {
00591
int R, G, B;
00592 LABtoRGB(L, a, b, &R, &G, &B);
00593 RGBtoHSV(R, G, B, H, S, V);
00594 }
00595
00596
void KoColor::LABtoCMYK(
int L,
int a,
int b,
int *C,
int *M,
int *Y,
int*K)
00597 {
00598
int R, G, B;
00599 LABtoRGB(L, a, b, &R, &G, &B);
00600 RGBtoCMYK(R, G, B, C, M, Y, K);
00601 }
00602
00603
void KoColor::CMYKtoRGB(
int C,
int M,
int Y,
int K,
int *R,
int *G,
int *B)
00604 {
00605 *R = 255 - (C + K);
00606 *G = 255 - (M + K);
00607 *B = 255 - (Y + K);
00608 }
00609
00610
void KoColor::CMYKtoHSV(
int C,
int M,
int Y,
int K,
int *H,
int *S,
int *V)
00611 {
00612
int R, G, B;
00613 CMYKtoRGB(C, M, Y, K, &R, &G, &B);
00614 RGBtoHSV(R, G, B, H, S, V);
00615 }
00616
00617
void KoColor::CMYKtoLAB(
int C,
int M,
int Y,
int K,
int *L,
int *a,
int *b)
00618 {
00619
int R, G, B;
00620 CMYKtoRGB(C, M, Y, K, &R, &G, &B);
00621 RGBtoLAB(R, G, B, L, a, b);
00622 }
00623
00624
int KoColor::hex2int(
QChar c)
00625 {
00626
if(c.isDigit())
00627
return c.digitValue();
00628
else if(
'A' <= c && c <=
'F')
00629
return c -
'A' + 10;
00630
else if(
'a' <= c && c <=
'f')
00631
return c -
'a' + 10;
00632
else
00633
return 0;
00634 }
00635
00636
void KoColor::calcRGB()
const
00637
{
00638
switch(mNative)
00639 {
00640
case csHSV:
00641 HSVtoRGB(mH, mS, mV, &mR, &mG, &mB);
00642
break;
00643
case csLab:
00644 LABtoRGB(mL, ma, mB, &mR, &mG, &mB);
00645
break;
00646
case csCMYK:
00647 CMYKtoRGB(mC, mM, mY, mK, &mR, &mG, &mB);
00648
break;
00649
default:
00650
break;
00651 }
00652 mRGBvalid =
true;
00653 }
00654
00655
void KoColor::calcHSV()
const
00656
{
00657
switch(mNative)
00658 {
00659
case csRGB:
00660 RGBtoHSV(mR, mG, mB, &mH, &mS, &mV);
00661
break;
00662
case csLab:
00663 LABtoHSV(mL, ma, mB, &mH, &mS, &mV);
00664
break;
00665
case csCMYK:
00666 CMYKtoHSV(mC, mM, mY, mK, &mH, &mS, &mV);
00667
break;
00668
default:
00669
break;
00670 }
00671 mHSVvalid =
true;
00672 }
00673
00674
void KoColor::calcCMYK()
const
00675
{
00676
switch(mNative)
00677 {
00678
case csRGB:
00679 RGBtoCMYK(mR, mG, mB, &mC, &mM, &mY, &mK);
00680
break;
00681
case csLab:
00682 LABtoCMYK(mL, ma, mB, &mC, &mM, &mY, &mK);
00683
break;
00684
case csHSV:
00685 HSVtoCMYK(mH, mS, mV, &mC, &mM, &mY, &mK);
00686
break;
00687
default:
00688
break;
00689 }
00690 mCMYKvalid =
true;
00691 }
00692
00693
void KoColor::calcLAB()
const
00694
{
00695
switch(mNative)
00696 {
00697
case csRGB:
00698 RGBtoLAB(mR, mG, mB, &mL, &ma, &mB);
00699
break;
00700
case csHSV:
00701 HSVtoLAB(mH, mS, mV, &mL, &ma, &mB);
00702
break;
00703
case csCMYK:
00704 CMYKtoLAB(mC, mM, mY, mK, &mL, &ma, &mB);
00705
break;
00706
default:
00707
break;
00708 }
00709 mLABvalid =
true;
00710 }
00711
00712
void KoColor::rgbChanged()
const
00713
{
00714 mRGBvalid =
true;
00715 mHSVvalid =
false;
00716 mCMYKvalid =
false;
00717 mLABvalid =
false;
00718 }
00719
00720
void KoColor::hsvChanged()
const
00721
{
00722 mRGBvalid =
false;
00723 mHSVvalid =
true;
00724 mCMYKvalid =
false;
00725 mLABvalid =
false;
00726 }
00727
00728
void KoColor::cmykChanged()
const
00729
{
00730 mRGBvalid =
false;
00731 mHSVvalid =
false;
00732 mCMYKvalid =
true;
00733 mLABvalid =
false;
00734 }
00735
00736
void KoColor::labChanged()
const
00737
{
00738 mRGBvalid =
false;
00739 mHSVvalid =
false;
00740 mCMYKvalid =
false;
00741 mLABvalid =
true;
00742 }