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