]> Pileus Git - ~andy/gtk/blob - gtk/gtkcolorutils.c
ef6371236c9bc9fc3b2b7f0dae745bb6f284b021
[~andy/gtk] / gtk / gtkcolorutils.c
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, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 /*
26  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
27  * file for a list of people on the GTK+ Team.  See the ChangeLog
28  * files for a list of changes.  These files are distributed with
29  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
30  */
31
32 #include "config.h"
33
34 #include <math.h>
35 #include <string.h>
36
37 #include "gtkcolorutils.h"
38
39
40 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
41
42 /* Converts from HSV to RGB */
43 static void
44 hsv_to_rgb (gdouble *h,
45             gdouble *s,
46             gdouble *v)
47 {
48   gdouble hue, saturation, value;
49   gdouble f, p, q, t;
50
51   if (*s == 0.0)
52     {
53       *h = *v;
54       *s = *v;
55       *v = *v; /* heh */
56     }
57   else
58     {
59       hue = *h * 6.0;
60       saturation = *s;
61       value = *v;
62
63       if (hue == 6.0)
64         hue = 0.0;
65
66       f = hue - (int) hue;
67       p = value * (1.0 - saturation);
68       q = value * (1.0 - saturation * f);
69       t = value * (1.0 - saturation * (1.0 - f));
70
71       switch ((int) hue)
72         {
73         case 0:
74           *h = value;
75           *s = t;
76           *v = p;
77           break;
78
79         case 1:
80           *h = q;
81           *s = value;
82           *v = p;
83           break;
84
85         case 2:
86           *h = p;
87           *s = value;
88           *v = t;
89           break;
90
91         case 3:
92           *h = p;
93           *s = q;
94           *v = value;
95           break;
96
97         case 4:
98           *h = t;
99           *s = p;
100           *v = value;
101           break;
102
103         case 5:
104           *h = value;
105           *s = p;
106           *v = q;
107           break;
108
109         default:
110           g_assert_not_reached ();
111         }
112     }
113 }
114
115 /* Converts from RGB to HSV */
116 static void
117 rgb_to_hsv (gdouble *r,
118             gdouble *g,
119             gdouble *b)
120 {
121   gdouble red, green, blue;
122   gdouble h, s, v;
123   gdouble min, max;
124   gdouble delta;
125
126   red = *r;
127   green = *g;
128   blue = *b;
129
130   h = 0.0;
131
132   if (red > green)
133     {
134       if (red > blue)
135         max = red;
136       else
137         max = blue;
138
139       if (green < blue)
140         min = green;
141       else
142         min = blue;
143     }
144   else
145     {
146       if (green > blue)
147         max = green;
148       else
149         max = blue;
150
151       if (red < blue)
152         min = red;
153       else
154         min = blue;
155     }
156
157   v = max;
158
159   if (max != 0.0)
160     s = (max - min) / max;
161   else
162     s = 0.0;
163
164   if (s == 0.0)
165     h = 0.0;
166   else
167     {
168       delta = max - min;
169
170       if (red == max)
171         h = (green - blue) / delta;
172       else if (green == max)
173         h = 2 + (blue - red) / delta;
174       else if (blue == max)
175         h = 4 + (red - green) / delta;
176
177       h /= 6.0;
178
179       if (h < 0.0)
180         h += 1.0;
181       else if (h > 1.0)
182         h -= 1.0;
183     }
184
185   *r = h;
186   *g = s;
187   *b = v;
188 }
189
190 /**
191  * gtk_hsv_to_rgb:
192  * @h: Hue
193  * @s: Saturation
194  * @v: Value
195  * @r: (out): Return value for the red component
196  * @g: (out): Return value for the green component
197  * @b: (out): Return value for the blue component
198  *
199  * Converts a color from HSV space to RGB.
200  *
201  * Input values must be in the [0.0, 1.0] range;
202  * output values will be in the same range.
203  *
204  * Since: 2.14
205  */
206 void
207 gtk_hsv_to_rgb (gdouble  h, gdouble  s, gdouble  v,
208                 gdouble *r, gdouble *g, gdouble *b)
209 {
210   g_return_if_fail (h >= 0.0 && h <= 1.0);
211   g_return_if_fail (s >= 0.0 && s <= 1.0);
212   g_return_if_fail (v >= 0.0 && v <= 1.0);
213
214   hsv_to_rgb (&h, &s, &v);
215
216   if (r)
217     *r = h;
218
219   if (g)
220     *g = s;
221
222   if (b)
223     *b = v;
224 }
225
226 /**
227  * gtk_rgb_to_hsv:
228  * @r: Red
229  * @g: Green
230  * @b: Blue
231  * @h: (out): Return value for the hue component
232  * @s: (out): Return value for the saturation component
233  * @v: (out): Return value for the value component
234  *
235  * Converts a color from RGB space to HSV.
236  *
237  * Input values must be in the [0.0, 1.0] range;
238  * output values will be in the same range.
239  *
240  * Since: 2.14
241  */
242 void
243 gtk_rgb_to_hsv (gdouble  r, gdouble  g, gdouble  b,
244                 gdouble *h, gdouble *s, gdouble *v)
245 {
246   g_return_if_fail (r >= 0.0 && r <= 1.0);
247   g_return_if_fail (g >= 0.0 && g <= 1.0);
248   g_return_if_fail (b >= 0.0 && b <= 1.0);
249
250   rgb_to_hsv (&r, &g, &b);
251
252   if (h)
253     *h = r;
254
255   if (s)
256     *s = g;
257
258   if (v)
259     *v = b;
260 }