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 }