1 #include "color_helpers.h"
2 /*
3  * Color space conversion helper routines
4  * Convert between rgb and hsv and between rgb and hls
5  */
6 
7 void
__imlib_rgb_to_hsv(int r,int g,int b,float * h,float * s,float * v)8 __imlib_rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v)
9 {
10    float               min, max, delta;
11 
12    min = (((r < g) ? r : g) < b) ? ((r < g) ? r : g) : b;
13    max = (((r > g) ? r : g) > b) ? ((r > g) ? r : g) : b;
14 
15    *v = max / 255.0;
16    delta = (max - min);
17    if (delta == 0)
18      {
19         *h = 0.0;
20         *s = 0.0;
21         return;
22      }
23    *s = delta / max;
24    if (r == max)
25       *h = (g - b) / delta;
26    else if (g == max)
27       *h = 2.0 + (b - r) / delta;
28    else
29       *h = 4.0 + (r - g) / delta;
30    *h *= 60.0;
31    if (*h < 0)
32       *h += 360.0;
33 }
34 
35 void
__imlib_hsv_to_rgb(float h,float s,float v,int * r,int * g,int * b)36 __imlib_hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b)
37 {
38    float               f, vf;
39    int                 i, p, q, t, vv;
40 
41    vf = 255.0 * v;
42    vv = (int)round(vf);
43 
44    if (s == 0.0)
45      {
46         *r = *g = *b = vv;
47         return;
48      }
49 
50    h /= 60.0;
51    i = floor(h);
52    f = h - (float)i;
53    p = (int)round(vf * (1.0 - s));
54    q = (int)round(vf * (1.0 - (s * f)));
55    t = (int)round(vf * (1.0 - s * (1.0 - f)));
56 
57    switch (i % 6)
58      {
59      case 0:
60         *r = vv;
61         *g = t;
62         *b = p;
63         break;
64      case 1:
65         *r = q;
66         *g = vv;
67         *b = p;
68         break;
69      case 2:
70         *r = p;
71         *g = vv;
72         *b = t;
73         break;
74      case 3:
75         *r = p;
76         *g = q;
77         *b = vv;
78         break;
79      case 4:
80         *r = t;
81         *g = p;
82         *b = vv;
83         break;
84      case 5:
85      default:
86         *r = vv;
87         *g = p;
88         *b = q;
89         break;
90      }
91 }
92 
93 void
__imlib_rgb_to_hls(int r,int g,int b,float * hue,float * lightness,float * saturation)94 __imlib_rgb_to_hls(int r, int g, int b, float *hue, float *lightness,
95                    float *saturation)
96 {
97    int                 f;
98    float               i, j, k, max, min, d;
99 
100    i = ((float)r) / 255.0;
101    j = ((float)g) / 255.0;
102    k = ((float)b) / 255.0;
103 
104    f = 0;
105    max = min = i;
106    if (j > max)
107      {
108         max = j;
109         f = 1;
110      }
111    else
112       min = j;
113    if (k > max)
114      {
115         max = k;
116         f = 2;
117      }
118    else if (k < min)
119       min = k;
120    d = max - min;
121 
122    *lightness = (max + min) / 2.0;
123    if (d == 0)
124      {
125         *saturation = 0;
126         *hue = 0;
127      }
128    else
129      {
130         if (*lightness < 0.5)
131            *saturation = d / (max + min);
132         else
133            *saturation = d / (2 - max - min);
134         switch (f)
135           {
136           case 0:
137              *hue = (j - k) / d;
138              break;
139           case 1:
140              *hue = 2 + (k - i) / d;
141              break;
142           case 2:
143              *hue = 4 + (i - j) / d;
144              break;
145           }
146         *hue *= 60.0;
147         if (*hue < 0)
148            *hue += 360.0;
149      }
150 }
151 
152 void
__imlib_hls_to_rgb(float hue,float lightness,float saturation,int * r,int * g,int * b)153 __imlib_hls_to_rgb(float hue, float lightness, float saturation, int *r, int *g,
154                    int *b)
155 {
156    float               m1, m2, m21, h;
157 
158    if (saturation == 0)
159       *r = *g = *b = (int)(lightness * 255.0);
160    else
161      {
162         if (lightness <= 0.5)
163            m2 = lightness * (1 + saturation);
164         else
165            m2 = lightness + saturation + lightness * saturation;
166         m1 = 2 * lightness - m2;
167         m21 = m2 - m1;
168         h = hue + 120;
169         if (h > 360)
170            h -= 360;
171         else if (h < 0)
172            h += 360;
173         if (h < 60)
174            *r = (int)(255.0 * (m1 + m21 * h / 60.0));
175         else if (h < 180)
176            *r = (int)(255.0 * m2);
177         else if (h < 240)
178            *r = (int)(255.0 * (m1 + m21 * (240.0 - h) / 60.0));
179         else
180            *r = (int)(255.0 * m1);
181         h = hue;
182         if (h > 360)
183            h -= 360;
184         else if (h < 0)
185            h += 360;
186         if (h < 60)
187            *g = (int)(255.0 * (m1 + m21 * h / 60.0));
188         else if (h < 180)
189            *g = (int)(255.0 * m2);
190         else if (h < 240)
191            *g = (int)(255.0 * (m1 + m21 * (240.0 - h) / 60.0));
192         else
193            *g = (int)(255.0 * m1);
194         h = hue - 120;
195         if (h > 360)
196            h -= 360;
197         else if (h < 0)
198            h += 360;
199         if (h < 60)
200            *b = (int)(255.0 * (m1 + m21 * h / 60.0));
201         else if (h < 180)
202            *b = (int)(255.0 * m2);
203         else if (h < 240)
204            *b = (int)(255.0 * (m1 + m21 * (240.0 - h) / 60.0));
205         else
206            *b = (int)(255.0 * m1);
207      }
208 }
209