krita

kis_color_conversions.cc

00001 /*
00002  *  Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include <cmath>
00020 
00021 #include <qglobal.h>
00022 
00023 #include "kis_color_conversions.h"
00024 
00029 void rgb_to_hsv(int R, int G, int B, int *H, int *S, int *V)
00030 {
00031     unsigned int max = R;
00032     unsigned int min = R;
00033     unsigned char maxValue = 0; // r = 0, g = 1, b = 2
00034 
00035     // find maximum and minimum RGB values
00036     if(static_cast<unsigned int>(G) > max) {
00037         max = G;
00038         maxValue = 1;
00039     }
00040     
00041     if (static_cast<unsigned int>(B) > max)
00042     {
00043         max = B;
00044         maxValue = 2;
00045     }
00046 
00047     if(static_cast<unsigned int>(G) < min)
00048         min = G;
00049         
00050     if(static_cast<unsigned int>(B) < min )
00051         min = B;
00052 
00053     int delta = max - min;
00054 
00055     // To prevent division by zero later on.
00056     if (delta == 0) delta = 1;
00057     
00058     *V = max; // value
00059     *S = max ? (510 * delta + max) / ( 2 * max) : 0; // saturation
00060     
00061     // calc hue
00062     if(*S == 0)
00063         *H = -1; // undefined hue
00064     else
00065     {
00066         switch(maxValue)
00067         {
00068         case 0:  // red
00069             if(G >= B)
00070                 *H = (120 * (G - B) + delta) / (2 * delta);
00071             else
00072                 *H = (120 * (G - B + delta) + delta) / (2 * delta) + 300;
00073             break;
00074         case 1:  // green
00075             if(B > R)
00076                 *H = 120 + (120 * (B - R) + delta) / (2 * delta);
00077             else
00078                 *H = 60 + (120 * (B - R + delta) + delta) / (2 * delta);
00079             break;
00080         case 2:  // blue
00081             if(R > G)
00082                 *H = 240 + (120 * (R - G) + delta) / (2 * delta);
00083             else
00084                 *H = 180 + (120 * (R - G + delta) + delta) / (2 * delta);
00085             break;
00086         }
00087     }
00088 }
00089 
00090 void hsv_to_rgb(int H, int S, int V, int *R, int *G, int *B)
00091 {
00092     *R = *G = *B = V;
00093 
00094     if (S != 0 && H != -1) { // chromatic
00095 
00096         if (H >= 360) {
00097             // angle > 360
00098             H %= 360;
00099         }
00100 
00101         unsigned int f = H % 60;
00102         H /= 60;
00103         unsigned int p = static_cast<unsigned int>(2*V*(255-S)+255)/510;
00104         unsigned int q, t;
00105 
00106         if (H & 1) {
00107             q = static_cast<unsigned int>(2 * V * (15300 - S * f) + 15300) / 30600;
00108             switch (H) {
00109             case 1:
00110                 *R = static_cast<int>(q);
00111                 *G = static_cast<int>(V);
00112                 *B = static_cast<int>(p);
00113                 break;
00114             case 3:
00115                 *R = static_cast<int>(p);
00116                 *G = static_cast<int>(q);
00117                 *B = static_cast<int>(V);
00118                 break;
00119             case 5:
00120                 *R = static_cast<int>(V);
00121                 *G = static_cast<int>(p);
00122                 *B = static_cast<int>(q);
00123                 break;
00124             }
00125         } else {
00126             t = static_cast<unsigned int>(2 * V * (15300 - (S * (60 - f))) + 15300) / 30600;
00127             switch (H) {
00128             case 0:
00129                 *R = static_cast<int>(V);
00130                 *G = static_cast<int>(t);
00131                 *B = static_cast<int>(p);
00132                 break;
00133             case 2:
00134                 *R = static_cast<int>(p);
00135                 *G = static_cast<int>(V);
00136                 *B = static_cast<int>(t);
00137                 break;
00138             case 4:
00139                 *R = static_cast<int>(t);
00140                 *G = static_cast<int>(p);
00141                 *B = static_cast<int>(V);
00142                 break;
00143             }
00144         }
00145     }
00146 }
00147 
00148 #define EPSILON 1e-6
00149 #define UNDEFINED_HUE -1
00150 
00151 void RGBToHSV(float r, float g, float b, float *h, float *s, float *v)
00152 {
00153     float max = QMAX(r, QMAX(g, b));
00154     float min = QMIN(r, QMIN(g, b));
00155 
00156     *v = max;
00157 
00158     if (max > EPSILON) {
00159         *s = (max - min) / max;
00160     } else {
00161         *s = 0;
00162     }
00163 
00164     if (*s < EPSILON) {
00165         *h = UNDEFINED_HUE;
00166     } else {
00167         float delta = max - min;
00168 
00169         if (r == max) {
00170             *h = (g - b) / delta;
00171         } else if (g == max) {
00172             *h = 2 + (b - r) / delta;
00173         } else {
00174             *h = 4 + (r - g) / delta;
00175         }
00176 
00177         *h *= 60;
00178         if (*h < 0) {
00179             *h += 360;
00180         }
00181     }
00182 }
00183 
00184 void HSVToRGB(float h, float s, float v, float *r, float *g, float *b)
00185 {
00186     if (s < EPSILON || h == UNDEFINED_HUE) {
00187         // Achromatic case
00188 
00189         *r = v;
00190         *g = v;
00191         *b = v;
00192     } else {
00193         float f, p, q, t;
00194         int i;
00195 
00196         if (h > 360 - EPSILON) {
00197             h -= 360;
00198         }
00199 
00200         h /= 60;
00201         i = static_cast<int>(floor(h));
00202         f = h - i;
00203         p = v * (1 - s);
00204         q = v * (1 - (s * f));
00205         t = v * (1 - (s * (1 - f)));
00206 
00207         switch (i) {
00208         case 0:
00209             *r = v;
00210             *g = t;
00211             *b = p;
00212             break;
00213         case 1:
00214             *r = q;
00215             *g = v;
00216             *b = p;
00217             break;
00218         case 2:
00219             *r = p;
00220             *g = v;
00221             *b = t;
00222             break;
00223         case 3:
00224             *r = p;
00225             *g = q;
00226             *b = v;
00227             break;
00228         case 4:
00229             *r = t;
00230             *g = p;
00231             *b = v;
00232             break;
00233         case 5:
00234             *r = v;
00235             *g = p;
00236             *b = q;
00237             break;
00238         }
00239     }
00240 }
00241 
00242 void rgb_to_hls(Q_UINT8 red, Q_UINT8 green, Q_UINT8 blue, float * hue, float * lightness, float * saturation)
00243 {
00244     float r = red / 255.0;
00245     float g = green / 255.0;
00246     float b = blue / 255.0;
00247     float h = 0;
00248     float l = 0;
00249     float s = 0;
00250 
00251     float max, min, delta;
00252 
00253     max = QMAX(r, g);
00254     max = QMAX(max, b);
00255     
00256     min = QMIN(r, g);
00257     min = QMIN(min, b);
00258 
00259     delta = max - min;
00260 
00261     l = (max + min) / 2;
00262 
00263     if (delta == 0) {
00264         // This is a gray, no chroma...
00265         h = 0;
00266         s = 0;
00267     }
00268     else {
00269         if ( l < 0.5)
00270             s = delta / ( max + min );
00271         else
00272             s = delta / ( 2 - max - min );
00273 
00274         float delta_r, delta_g, delta_b;
00275 
00276         delta_r = (( max - r ) / 6 ) / delta;
00277         delta_g = (( max - g ) / 6 ) / delta;
00278         delta_b = (( max - b ) / 6 ) / delta;
00279 
00280         if ( r == max )
00281             h = delta_b - delta_g;
00282         else if ( g == max)
00283             h = ( 1.0 / 3 ) + delta_r - delta_b;
00284         else if ( b == max)
00285             h = ( 2.0 / 3 ) + delta_g - delta_r;
00286 
00287         if (h < 0) h += 1;
00288         if (h > 1) h += 1;
00289         
00290     }
00291 
00292     *hue = h * 360;
00293     *saturation = s;
00294     *lightness = l;
00295 }
00296 
00297 float hue_value(float n1, float n2, float hue)
00298 {
00299     if (hue > 360 )
00300         hue = hue -360;
00301     else if (hue < 0 )
00302         hue = hue +360;
00303     if (hue < 60  )
00304         return n1 + (((n2 - n1) * hue) / 60);
00305     else if (hue < 180 )
00306         return n2;
00307     else if (hue < 240 )
00308         return n1 + (((n2 - n1) * (240 - hue)) / 60);
00309     else return n1;
00310 }
00311 
00312 
00313 void hls_to_rgb(float h, float l, float s, Q_UINT8 * r, Q_UINT8 * g, Q_UINT8 * b)
00314 {
00315     float m1, m2;
00316 
00317     if (l <= 0.5 )
00318         m2 = l * ( 1 + s );
00319     else 
00320         m2 = l + s - l * s;
00321 
00322     m1 = 2 * l - m2;
00323     
00324     *r = (Q_UINT8)(hue_value(m1, m2, h + 120) * 255 + 0.5);
00325     *g = (Q_UINT8)(hue_value(m1, m2, h) * 255 + 0.5);
00326     *b = (Q_UINT8)(hue_value(m1, m2, h - 120) * 255 + 0.5);
00327 
00328 }
00329 
00330 void rgb_to_hls(Q_UINT8 r, Q_UINT8 g, Q_UINT8 b, int * h, int * l, int * s)
00331 {
00332     float hue, saturation, lightness;
00333 
00334     rgb_to_hls(r, g, b, &hue, &lightness, &saturation);
00335     *h = (int)(hue + 0.5);
00336     *l = (int)(lightness * 255 + 0.5);
00337     *s = (int)(saturation * 255 + 0.5);
00338 }
00339 
00340 void hls_to_rgb(int h, int l, int s, Q_UINT8 * r, Q_UINT8 * g, Q_UINT8 * b)
00341 {
00342     float hue = h;
00343     float lightness = l / 255.0;
00344     float saturation = s / 255.0;
00345 
00346     hls_to_rgb(hue, lightness, saturation, r, g, b);
00347 }
00348 
00349 /*
00350 A Fast HSL-to-RGB Transform
00351 by Ken Fishkin
00352 from "Graphics Gems", Academic Press, 1990
00353 */
00354 
00355 void RGBToHSL(float r, float g, float b, float *h, float *s, float *l)
00356 {
00357     float v;
00358     float m;
00359     float vm;
00360     float r2, g2, b2;
00361 
00362     v = QMAX(r,g);
00363     v = QMAX(v,b);
00364     m = QMIN(r,g);
00365     m = QMIN(m,b);
00366 
00367     if ((*l = (m + v) / 2.0) <= 0.0) {
00368         *h = UNDEFINED_HUE;
00369         *s = 0;
00370         return;
00371     }
00372     if ((*s = vm = v - m) > 0.0) {
00373         *s /= (*l <= 0.5) ? (v + m ) :
00374               (2.0 - v - m) ;
00375     } else {
00376         *h = UNDEFINED_HUE;
00377         return;
00378     }
00379 
00380 
00381     r2 = (v - r) / vm;
00382     g2 = (v - g) / vm;
00383     b2 = (v - b) / vm;
00384 
00385     if (r == v)
00386         *h = (g == m ? 5.0 + b2 : 1.0 - g2);
00387     else if (g == v)
00388         *h = (b == m ? 1.0 + r2 : 3.0 - b2);
00389     else
00390         *h = (r == m ? 3.0 + g2 : 5.0 - r2);
00391 
00392     *h *= 60;
00393 }
00394 
00395 void HSLToRGB(float h, float sl, float l, float *r, float *g, float *b)
00396 
00397 {
00398     float v;
00399 
00400     v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
00401     if (v <= 0) {
00402         *r = *g = *b = 0.0;
00403     } else {
00404         float m;
00405         float sv;
00406         int sextant;
00407         float fract, vsf, mid1, mid2;
00408 
00409         m = l + l - v;
00410         sv = (v - m ) / v;
00411         h /= 60.0;
00412         sextant = static_cast<int>(h);    
00413         fract = h - sextant;
00414         vsf = v * sv * fract;
00415         mid1 = m + vsf;
00416         mid2 = v - vsf;
00417         switch (sextant) {
00418         case 0: *r = v; *g = mid1; *b = m; break;
00419         case 1: *r = mid2; *g = v; *b = m; break;
00420         case 2: *r = m; *g = v; *b = mid1; break;
00421         case 3: *r = m; *g = mid2; *b = v; break;
00422         case 4: *r = mid1; *g = m; *b = v; break;
00423         case 5: *r = v; *g = m; *b = mid2; break;
00424         }
00425     }
00426 }
00427 
KDE Home | KDE Accessibility Home | Description of Access Keys