F:/KPlato/koffice/libs/pigment/KoColorConversions.cpp

Aller à la documentation de ce fichier.
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 Lesser General Public License as published
00006  *  by 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 Lesser 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 "KoColorConversions.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     *V = max; // value
00055     *S = max ? (510 * delta + max) / ( 2 * max) : 0; // saturation
00056     
00057     // calc hue
00058     if(*S == 0)
00059         *H = -1; // undefined hue
00060     else
00061     {
00062         switch(maxValue)
00063         {
00064         case 0:  // red
00065             if(G >= B)
00066                 *H = (120 * (G - B) + delta) / (2 * delta);
00067             else
00068                 *H = (120 * (G - B + delta) + delta) / (2 * delta) + 300;
00069             break;
00070         case 1:  // green
00071             if(B > R)
00072                 *H = 120 + (120 * (B - R) + delta) / (2 * delta);
00073             else
00074                 *H = 60 + (120 * (B - R + delta) + delta) / (2 * delta);
00075             break;
00076         case 2:  // blue
00077             if(R > G)
00078                 *H = 240 + (120 * (R - G) + delta) / (2 * delta);
00079             else
00080                 *H = 180 + (120 * (R - G + delta) + delta) / (2 * delta);
00081             break;
00082         }
00083     }
00084 }
00085 
00086 void hsv_to_rgb(int H, int S, int V, int *R, int *G, int *B)
00087 {
00088     *R = *G = *B = V;
00089 
00090     if (S != 0 && H != -1) { // chromatic
00091 
00092         if (H >= 360) {
00093             // angle > 360
00094             H %= 360;
00095         }
00096 
00097         unsigned int f = H % 60;
00098         H /= 60;
00099         unsigned int p = static_cast<unsigned int>(2*V*(255-S)+255)/510;
00100         unsigned int q, t;
00101 
00102         if (H & 1) {
00103             q = static_cast<unsigned int>(2 * V * (15300 - S * f) + 15300) / 30600;
00104             switch (H) {
00105             case 1:
00106                 *R = static_cast<int>(q);
00107                 *G = static_cast<int>(V);
00108                 *B = static_cast<int>(p);
00109                 break;
00110             case 3:
00111                 *R = static_cast<int>(p);
00112                 *G = static_cast<int>(q);
00113                 *B = static_cast<int>(V);
00114                 break;
00115             case 5:
00116                 *R = static_cast<int>(V);
00117                 *G = static_cast<int>(p);
00118                 *B = static_cast<int>(q);
00119                 break;
00120             }
00121         } else {
00122             t = static_cast<unsigned int>(2 * V * (15300 - (S * (60 - f))) + 15300) / 30600;
00123             switch (H) {
00124             case 0:
00125                 *R = static_cast<int>(V);
00126                 *G = static_cast<int>(t);
00127                 *B = static_cast<int>(p);
00128                 break;
00129             case 2:
00130                 *R = static_cast<int>(p);
00131                 *G = static_cast<int>(V);
00132                 *B = static_cast<int>(t);
00133                 break;
00134             case 4:
00135                 *R = static_cast<int>(t);
00136                 *G = static_cast<int>(p);
00137                 *B = static_cast<int>(V);
00138                 break;
00139             }
00140         }
00141     }
00142 }
00143 
00144 #define EPSILON 1e-6
00145 #define UNDEFINED_HUE -1
00146 
00147 void RGBToHSV(float r, float g, float b, float *h, float *s, float *v)
00148 {
00149     float max = qMax(r, qMax(g, b));
00150     float min = qMin(r, qMin(g, b));
00151 
00152     *v = max;
00153 
00154     if (max > EPSILON) {
00155         *s = (max - min) / max;
00156     } else {
00157         *s = 0;
00158     }
00159 
00160     if (*s < EPSILON) {
00161         *h = UNDEFINED_HUE;
00162     } else {
00163         float delta = max - min;
00164 
00165         if (r == max) {
00166             *h = (g - b) / delta;
00167         } else if (g == max) {
00168             *h = 2 + (b - r) / delta;
00169         } else {
00170             *h = 4 + (r - g) / delta;
00171         }
00172 
00173         *h *= 60;
00174         if (*h < 0) {
00175             *h += 360;
00176         }
00177     }
00178 }
00179 
00180 void HSVToRGB(float h, float s, float v, float *r, float *g, float *b)
00181 {
00182     if (s < EPSILON || h == UNDEFINED_HUE) {
00183         // Achromatic case
00184 
00185         *r = v;
00186         *g = v;
00187         *b = v;
00188     } else {
00189         float f, p, q, t;
00190         int i;
00191 
00192         if (h > 360 - EPSILON) {
00193             h -= 360;
00194         }
00195 
00196         h /= 60;
00197         i = static_cast<int>(floor(h));
00198         f = h - i;
00199         p = v * (1 - s);
00200         q = v * (1 - (s * f));
00201         t = v * (1 - (s * (1 - f)));
00202 
00203         switch (i) {
00204         case 0:
00205             *r = v;
00206             *g = t;
00207             *b = p;
00208             break;
00209         case 1:
00210             *r = q;
00211             *g = v;
00212             *b = p;
00213             break;
00214         case 2:
00215             *r = p;
00216             *g = v;
00217             *b = t;
00218             break;
00219         case 3:
00220             *r = p;
00221             *g = q;
00222             *b = v;
00223             break;
00224         case 4:
00225             *r = t;
00226             *g = p;
00227             *b = v;
00228             break;
00229         case 5:
00230             *r = v;
00231             *g = p;
00232             *b = q;
00233             break;
00234         }
00235     }
00236 }
00237 
00238 void rgb_to_hls(quint8 red, quint8 green, quint8 blue, float * hue, float * lightness, float * saturation)
00239 {
00240     float r = red / 255.0;
00241     float g = green / 255.0;
00242     float b = blue / 255.0;
00243     float h = 0;
00244     float l = 0;
00245     float s = 0;
00246 
00247     float max, min, delta;
00248 
00249     max = qMax(r, g);
00250     max = qMax(max, b);
00251     
00252     min = qMin(r, g);
00253     min = qMin(min, b);
00254 
00255     delta = max - min;
00256 
00257     l = (max + min) / 2;
00258 
00259     if (delta == 0) {
00260         // This is a gray, no chroma...
00261         h = 0;
00262         s = 0;
00263     }
00264     else {
00265         if ( l < 0.5)
00266             s = delta / ( max + min );
00267         else
00268             s = delta / ( 2 - max - min );
00269 
00270         float delta_r, delta_g, delta_b;
00271 
00272         delta_r = (( max - r ) / 6 ) / delta;
00273         delta_g = (( max - g ) / 6 ) / delta;
00274         delta_b = (( max - b ) / 6 ) / delta;
00275 
00276         if ( r == max )
00277             h = delta_b - delta_g;
00278         else if ( g == max)
00279             h = ( 1.0 / 3 ) + delta_r - delta_b;
00280         else if ( b == max)
00281             h = ( 2.0 / 3 ) + delta_g - delta_r;
00282 
00283         if (h < 0) h += 1;
00284         if (h > 1) h += 1;
00285         
00286     }
00287 
00288     *hue = h * 360;
00289     *saturation = s;
00290     *lightness = l;
00291 }
00292 
00293 float hue_value(float n1, float n2, float hue)
00294 {
00295     if (hue > 360 )
00296         hue = hue -360;
00297     else if (hue < 0 )
00298         hue = hue +360;
00299     if (hue < 60  )
00300         return n1 + (((n2 - n1) * hue) / 60);
00301     else if (hue < 180 )
00302         return n2;
00303     else if (hue < 240 )
00304         return n1 + (((n2 - n1) * (240 - hue)) / 60);
00305     else return n1;
00306 }
00307 
00308 
00309 void hls_to_rgb(float h, float l, float s, quint8 * r, quint8 * g, quint8 * b)
00310 {
00311     float m1, m2;
00312 
00313     if (l <= 0.5 )
00314         m2 = l * ( 1 + s );
00315     else 
00316         m2 = l + s - l * s;
00317 
00318     m1 = 2 * l - m2;
00319     
00320     *r = (quint8)(hue_value(m1, m2, h + 120) * 255 + 0.5);
00321     *g = (quint8)(hue_value(m1, m2, h) * 255 + 0.5);
00322     *b = (quint8)(hue_value(m1, m2, h - 120) * 255 + 0.5);
00323 
00324 }
00325 
00326 void rgb_to_hls(quint8 r, quint8 g, quint8 b, int * h, int * l, int * s)
00327 {
00328     float hue, saturation, lightness;
00329 
00330     rgb_to_hls(r, g, b, &hue, &lightness, &saturation);
00331     *h = (int)(hue + 0.5);
00332     *l = (int)(lightness * 255 + 0.5);
00333     *s = (int)(saturation * 255 + 0.5);
00334 }
00335 
00336 void hls_to_rgb(int h, int l, int s, quint8 * r, quint8 * g, quint8 * b)
00337 {
00338     float hue = h;
00339     float lightness = l / 255.0;
00340     float saturation = s / 255.0;
00341 
00342     hls_to_rgb(hue, lightness, saturation, r, g, b);
00343 }
00344 
00345 /*
00346 A Fast HSL-to-RGB Transform
00347 by Ken Fishkin
00348 from "Graphics Gems", Academic Press, 1990
00349 */
00350 
00351 void RGBToHSL(float r, float g, float b, float *h, float *s, float *l)
00352 {
00353     float v;
00354     float m;
00355     float vm;
00356     float r2, g2, b2;
00357 
00358     v = qMax(r,g);
00359     v = qMax(v,b);
00360     m = qMin(r,g);
00361     m = qMin(m,b);
00362 
00363     if ((*l = (m + v) / 2.0) <= 0.0) {
00364         *h = UNDEFINED_HUE;
00365         *s = 0;
00366         return;
00367     }
00368     if ((*s = vm = v - m) > 0.0) {
00369         *s /= (*l <= 0.5) ? (v + m ) :
00370               (2.0 - v - m) ;
00371     } else {
00372         *h = UNDEFINED_HUE;
00373         return;
00374     }
00375 
00376 
00377     r2 = (v - r) / vm;
00378     g2 = (v - g) / vm;
00379     b2 = (v - b) / vm;
00380 
00381     if (r == v)
00382         *h = (g == m ? 5.0 + b2 : 1.0 - g2);
00383     else if (g == v)
00384         *h = (b == m ? 1.0 + r2 : 3.0 - b2);
00385     else
00386         *h = (r == m ? 3.0 + g2 : 5.0 - r2);
00387 
00388     *h *= 60;
00389 }
00390 
00391 void HSLToRGB(float h, float sl, float l, float *r, float *g, float *b)
00392 
00393 {
00394     float v;
00395 
00396     v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
00397     if (v <= 0) {
00398         *r = *g = *b = 0.0;
00399     } else {
00400         float m;
00401         float sv;
00402         int sextant;
00403         float fract, vsf, mid1, mid2;
00404 
00405         m = l + l - v;
00406         sv = (v - m ) / v;
00407         h /= 60.0;
00408         sextant = static_cast<int>(h);    
00409         fract = h - sextant;
00410         vsf = v * sv * fract;
00411         mid1 = m + vsf;
00412         mid2 = v - vsf;
00413         switch (sextant) {
00414         case 0: *r = v; *g = mid1; *b = m; break;
00415         case 1: *r = mid2; *g = v; *b = m; break;
00416         case 2: *r = m; *g = v; *b = mid1; break;
00417         case 3: *r = m; *g = mid2; *b = v; break;
00418         case 4: *r = mid1; *g = m; *b = v; break;
00419         case 5: *r = v; *g = m; *b = mid2; break;
00420         }
00421     }
00422 }
00423 

Généré le Wed Nov 22 23:41:13 2006 pour KPlato par  doxygen 1.5.1-p1