lib Library API Documentation

koColor.cc

00001 /* This file is part of the KDE project 00002 Copyright (c) 1999 Matthias Elter (me@kde.org) 00003 Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 00021 #include "koColor.h" 00022 #include "kdebug.h" 00023 #include <cmath> 00024 00025 KoColor::KoColor() 00026 { 00027 // initialise to black 00028 mNative = csRGB; 00029 // RGB 00030 mR = 0; 00031 mG = 0; 00032 mB = 0; 00033 // HSV 00034 mH = mV = 0; 00035 mS = 100; 00036 // CMYK 00037 mC = 0; 00038 mY = 0; 00039 mM = 0; 00040 mK = 0; 00041 // Lab 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; // r = 0, g = 1, b = 2 00357 00358 // find maximum and minimum RGB values 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; // value 00377 *S = max ? (510 * delta + max) / ( 2 * max) : 0; // saturation 00378 00379 // calc hue 00380 if(*S == 0) 00381 *H = -1; // undefined hue 00382 else 00383 { 00384 switch(maxValue) 00385 { 00386 case 0: // red 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: // green 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: // blue 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 // Convert between RGB and CIE-Lab color spaces 00411 // Uses ITU-R recommendation BT.709 with D65 as reference white. 00412 // algorithm contributed by "Mark A. Ruzon" <ruzon@CS.Stanford.EDU> 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 // XXX: these algorithms aren't the best. See www.littlecms.com 00452 // for a suitable library, or the posting by Leo Rosenthol for 00453 // a better, but slower algorithm at 00454 // http://lists.kde.org/?l=koffice-devel&m=106698241227054&w=2 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) // chromatic 00475 { 00476 if(H >= 360) // angle > 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 // Convert between RGB and CIE-Lab color spaces 00548 // Uses ITU-R recommendation BT.709 with D65 as reference white. 00549 // algorithm contributed by "Mark A. Ruzon" <ruzon@CS.Stanford.EDU> 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 }
KDE Logo
This file is part of the documentation for lib Library Version 1.3.5.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Nov 17 06:54:15 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003