00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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;
00034
00035
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;
00055 *S = max ? (510 * delta + max) / ( 2 * max) : 0;
00056
00057
00058 if(*S == 0)
00059 *H = -1;
00060 else
00061 {
00062 switch(maxValue)
00063 {
00064 case 0:
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:
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:
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) {
00091
00092 if (H >= 360) {
00093
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
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
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
00347
00348
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