xref: /haiku/src/apps/icon-o-matic/generic/support/rgb_hsv.h (revision b55a57da7173b9af0432bd3e148d03f06161d036)
1 /*
2  * Copyright 2001 Werner Freytag - please read to the LICENSE file
3  *
4  */
5 
6 #ifndef CONVERT_RGB_HSV_H
7 #define CONVERT_RGB_HSV_H
8 
9 #define RETURN_HSV(h, s, v) { H = h; S = s; V = v; return; }
10 #define RETURN_RGB(r, g, b) { R = r; G = g; B = b; return; }
11 
12 #include <math.h>
13 
14 #define UNDEFINED 0
15 
16 inline void
17 RGB_to_HSV(float R, float G, float B, float& H, float& S, float& V)
18 {
19 	// RGB are each on [0, 1]. S and max are returned on [0, 1] and H is
20 	// returned on [0, 6]. Eminception: H is returned UNDEFINED if S==0.
21 
22 	float min, max;
23 
24 	if (R > G) {
25 		if (R > B) {
26 			max = R;
27 			min = G > B ? B : G;
28 		}
29 		else {
30 			max = B;
31 			min = G;
32 		}
33 	}
34 	else {
35 		if (G > B) {
36 			max = G;
37 			min = R > B ? B : R;
38 		}
39 		else {
40 			max = B;
41 			min = R;
42 		}
43 	}
44 
45 	if (max == min) RETURN_HSV(UNDEFINED, 0, max);
46 
47 	float dist = max - min;
48 
49 	float f = (R == min) ? G - B : ((G == min) ? B - R : R - G);
50 	float i = (R == min) ? 3 : ((G == min) ? 5 : 1);
51 	float h = i - f / dist;
52 
53 	while (h >= 6.0) h -= 6.0;
54 
55 	RETURN_HSV(h, dist/max, max);
56 
57 }
58 
59 inline void
60 HSV_to_RGB(float h, float s, float v, float& R, float& G, float& B)
61 {
62 	// H is given on [0, 6] or UNDEFINED. S and V are given on [0, 1].
63 	// RGB are each returned on [0, 1].
64 
65 	int i = (int)floor(h);
66 
67 	float f = h - i;
68 
69 	if ( !(i & 1) ) f = 1 - f; // if i is even
70 
71 	float m = v * (1 - s);
72 
73 	float n = v * (1 - s * f);
74 
75 	switch (i) {
76 
77 		case 6:
78 
79 		case 0: RETURN_RGB(v, n, m);
80 
81 		case 1: RETURN_RGB(n, v, m);
82 
83 		case 2: RETURN_RGB(m, v, n)
84 
85 		case 3: RETURN_RGB(m, n, v);
86 
87 		case 4: RETURN_RGB(n, m, v);
88 
89 		case 5: RETURN_RGB(v, m, n);
90 
91 	}
92 }
93 
94 #endif // CONVERT_RGB_HSV_H
95