1 /**
2   This module defines RGB <-> HSV conversions.
3 */
4 module gfm.image.hsv;
5 
6 import std.algorithm,
7        std.math;
8 
9 import gfm.math.vector;
10 
11 // RGB <-> HSV conversions.
12 
13 /// Converts a RGB triplet to HSV.
14 /// Authors: Sam Hocevar 
15 /// See_also: $(WEB http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv)
16 vec3f rgb2hsv(vec3f rgb) pure nothrow
17 {
18     float K = 0.0f;
19 
20     if (rgb.y < rgb.z)
21     {
22         swap(rgb.y, rgb.z);
23         K = -1.0f;
24     }
25 
26     if (rgb.x < rgb.y)
27     {
28         swap(rgb.x, rgb.y);
29         K = -2.0f / 6.0f - K;
30     }
31 
32     float chroma = rgb.x - (rgb.y < rgb.z ? rgb.y : rgb.z);
33     float h = abs(K + (rgb.y - rgb.z) / (6.0f * chroma + 1e-20f));
34     float s = chroma / (rgb.x + 1e-20f);
35     float v = rgb.x;
36 
37     return vec3f(h, s, v);
38 }
39 
40 /// Convert a HSV triplet to RGB.
41 /// Authors: Sam Hocevar.
42 /// See_also: $(WEB http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv).
43 vec3f hsv2rgb(vec3f hsv) pure nothrow
44 {
45     float S = hsv.y;
46     float H = hsv.x;
47     float V = hsv.z;
48 
49     vec3f rgb;
50 
51     if ( S == 0.0 ) 
52     {
53         rgb.x = V;
54         rgb.y = V;
55         rgb.z = V;
56     } 
57     else 
58     {        
59         if (H >= 1.0) 
60         {
61             H = 0.0;
62         } 
63         else 
64         {
65             H = H * 6;
66         }
67         int I = cast(int)H;
68         assert(I >= 0 && I < 6);
69         float F = H - I;     /* fractional part */
70 
71         float M = V * (1 - S);
72         float N = V * (1 - S * F);
73         float K = V * (1 - S * (1 - F));
74 
75         if (I == 0) { rgb.x = V; rgb.y = K; rgb.z = M; }
76         if (I == 1) { rgb.x = N; rgb.y = V; rgb.z = M; }
77         if (I == 2) { rgb.x = M; rgb.y = V; rgb.z = K; }
78         if (I == 3) { rgb.x = M; rgb.y = N; rgb.z = V; }
79         if (I == 4) { rgb.x = K; rgb.y = M; rgb.z = V; }
80         if (I == 5) { rgb.x = V; rgb.y = M; rgb.z = N; }
81     }
82     return rgb;
83 }