1 /* Color utilities
2 *
3 * Copyright (C) 1999 The Free Software Foundation
4 *
5 * Authors: Simon Budig <Simon.Budig@unix-ag.org> (original code)
6 * Federico Mena-Quintero <federico@gimp.org> (cleanup for GTK+)
7 * Jonathan Blandford <jrb@redhat.com> (cleanup for GTK+)
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /*
24 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
25 * file for a list of people on the GTK+ Team. See the ChangeLog
26 * files for a list of changes. These files are distributed with
27 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28 */
29
30 #include "config.h"
31
32 #include <math.h>
33 #include <string.h>
34
35 #include "gtkcolorutils.h"
36
37 /* Converts from HSV to RGB */
38 static void
hsv_to_rgb(gdouble * h,gdouble * s,gdouble * v)39 hsv_to_rgb (gdouble *h,
40 gdouble *s,
41 gdouble *v)
42 {
43 gdouble hue, saturation, value;
44 gdouble f, p, q, t;
45
46 if (*s == 0.0)
47 {
48 *h = *v;
49 *s = *v;
50 *v = *v; /* heh */
51 }
52 else
53 {
54 hue = *h * 6.0;
55 saturation = *s;
56 value = *v;
57
58 if (hue == 6.0)
59 hue = 0.0;
60
61 f = hue - (int) hue;
62 p = value * (1.0 - saturation);
63 q = value * (1.0 - saturation * f);
64 t = value * (1.0 - saturation * (1.0 - f));
65
66 switch ((int) hue)
67 {
68 case 0:
69 *h = value;
70 *s = t;
71 *v = p;
72 break;
73
74 case 1:
75 *h = q;
76 *s = value;
77 *v = p;
78 break;
79
80 case 2:
81 *h = p;
82 *s = value;
83 *v = t;
84 break;
85
86 case 3:
87 *h = p;
88 *s = q;
89 *v = value;
90 break;
91
92 case 4:
93 *h = t;
94 *s = p;
95 *v = value;
96 break;
97
98 case 5:
99 *h = value;
100 *s = p;
101 *v = q;
102 break;
103
104 default:
105 g_assert_not_reached ();
106 }
107 }
108 }
109
110 /* Converts from RGB to HSV */
111 static void
rgb_to_hsv(gdouble * r,gdouble * g,gdouble * b)112 rgb_to_hsv (gdouble *r,
113 gdouble *g,
114 gdouble *b)
115 {
116 gdouble red, green, blue;
117 gdouble h, s, v;
118 gdouble min, max;
119 gdouble delta;
120
121 red = *r;
122 green = *g;
123 blue = *b;
124
125 h = 0.0;
126
127 if (red > green)
128 {
129 if (red > blue)
130 max = red;
131 else
132 max = blue;
133
134 if (green < blue)
135 min = green;
136 else
137 min = blue;
138 }
139 else
140 {
141 if (green > blue)
142 max = green;
143 else
144 max = blue;
145
146 if (red < blue)
147 min = red;
148 else
149 min = blue;
150 }
151
152 v = max;
153
154 if (max != 0.0)
155 s = (max - min) / max;
156 else
157 s = 0.0;
158
159 if (s == 0.0)
160 h = 0.0;
161 else
162 {
163 delta = max - min;
164
165 if (red == max)
166 h = (green - blue) / delta;
167 else if (green == max)
168 h = 2 + (blue - red) / delta;
169 else if (blue == max)
170 h = 4 + (red - green) / delta;
171
172 h /= 6.0;
173
174 if (h < 0.0)
175 h += 1.0;
176 else if (h > 1.0)
177 h -= 1.0;
178 }
179
180 *r = h;
181 *g = s;
182 *b = v;
183 }
184
185 /**
186 * gtk_hsv_to_rgb:
187 * @h: Hue
188 * @s: Saturation
189 * @v: Value
190 * @r: (out): Return value for the red component
191 * @g: (out): Return value for the green component
192 * @b: (out): Return value for the blue component
193 *
194 * Converts a color from HSV space to RGB.
195 *
196 * Input values must be in the [0.0, 1.0] range;
197 * output values will be in the same range.
198 *
199 * Since: 2.14
200 */
201 void
gtk_hsv_to_rgb(gdouble h,gdouble s,gdouble v,gdouble * r,gdouble * g,gdouble * b)202 gtk_hsv_to_rgb (gdouble h, gdouble s, gdouble v,
203 gdouble *r, gdouble *g, gdouble *b)
204 {
205 g_return_if_fail (h >= 0.0 && h <= 1.0);
206 g_return_if_fail (s >= 0.0 && s <= 1.0);
207 g_return_if_fail (v >= 0.0 && v <= 1.0);
208
209 hsv_to_rgb (&h, &s, &v);
210
211 if (r)
212 *r = h;
213
214 if (g)
215 *g = s;
216
217 if (b)
218 *b = v;
219 }
220
221 /**
222 * gtk_rgb_to_hsv:
223 * @r: Red
224 * @g: Green
225 * @b: Blue
226 * @h: (out): Return value for the hue component
227 * @s: (out): Return value for the saturation component
228 * @v: (out): Return value for the value component
229 *
230 * Converts a color from RGB space to HSV.
231 *
232 * Input values must be in the [0.0, 1.0] range;
233 * output values will be in the same range.
234 *
235 * Since: 2.14
236 */
237 void
gtk_rgb_to_hsv(gdouble r,gdouble g,gdouble b,gdouble * h,gdouble * s,gdouble * v)238 gtk_rgb_to_hsv (gdouble r, gdouble g, gdouble b,
239 gdouble *h, gdouble *s, gdouble *v)
240 {
241 g_return_if_fail (r >= 0.0 && r <= 1.0);
242 g_return_if_fail (g >= 0.0 && g <= 1.0);
243 g_return_if_fail (b >= 0.0 && b <= 1.0);
244
245 rgb_to_hsv (&r, &g, &b);
246
247 if (h)
248 *h = r;
249
250 if (s)
251 *s = g;
252
253 if (v)
254 *v = b;
255 }
256