babl: fix some annotation to make the function usable in bindings.
[babl.git] / extensions / HSV.c
blob100636ccc51894cb9f57e68ce75a7e37ed2c50d9
1 /* babl - dynamically extendable universal pixel conversion library.
2 * Copyright (C) 2012, Maxime Nicco <maxime.nicco@gmail.fr>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 3 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, see
16 * <https://www.gnu.org/licenses/>.
20 * Adding support for HSV colorspace
23 #include "config.h"
25 #include <math.h>
26 #include <string.h>
28 #include "babl.h"
29 #include "base/util.h"
31 #define MIN(a,b) (a > b) ? b : a;
32 #define MAX(a,b) (a < b) ? b : a;
33 #define EPSILON 1.0e-10
35 static void
36 rgba_to_hsva (const Babl *conversion,
37 char *src,
38 char *dst,
39 long samples);
41 static void
42 hsva_to_rgba (const Babl *conversion,
43 char *src,
44 char *dst,
45 long samples);
47 static void
48 rgba_to_hsv (const Babl *conversion,
49 char *src,
50 char *dst,
51 long samples);
53 static void
54 hsv_to_rgba (const Babl *conversion,
55 char *src,
56 char *dst,
57 long samples);
59 static void
60 rgba_to_hsv_step (char *src,
61 char *dst);
63 static void
64 hsv_to_rgba_step (char *src,
65 char *dst);
67 static void components (void);
68 static void models (void);
69 static void conversions (void);
70 static void formats (void);
72 int init (void);
74 int
75 init (void)
77 components ();
78 models ();
79 conversions ();
80 formats ();
82 return 0;
86 static void
87 components (void)
89 babl_component_new ("hue", NULL);
90 babl_component_new ("saturation", NULL);
91 babl_component_new ("value", NULL);
92 babl_component_new ("alpha", "alpha", NULL);
95 static void
96 models (void)
99 babl_model_new (
100 "name", "HSV",
101 babl_component ("hue"),
102 babl_component ("saturation"),
103 babl_component ("value"),
104 "doc", "A legacy color model that exists for compatibility with old GIMP code, V is MAX(R,G,B).",
105 NULL
107 babl_model_new (
108 "name", "HSVA",
109 babl_component ("hue"),
110 babl_component ("saturation"),
111 babl_component ("value"),
112 babl_component ("alpha"),
113 "alpha",
114 "doc", "HSV with separate alpha.",
115 NULL
119 static void
120 conversions (void)
122 babl_conversion_new (
123 babl_model ("RGBA"),
124 babl_model ("HSVA"),
125 "linear", rgba_to_hsva,
126 NULL
129 babl_conversion_new (
130 babl_model ("RGBA"),
131 babl_model ("HSV"),
132 "linear", rgba_to_hsv,
133 NULL
136 babl_conversion_new (
137 babl_model ("HSVA"),
138 babl_model ("RGBA"),
139 "linear", hsva_to_rgba,
140 NULL
143 babl_conversion_new (
144 babl_model ("HSV"),
145 babl_model ("RGBA"),
146 "linear", hsv_to_rgba,
147 NULL
151 static void
152 formats (void)
154 babl_format_new (
155 "name", "HSVA float",
156 babl_model ("HSVA"),
157 babl_type ("float"),
158 babl_component ("hue"),
159 babl_component ("saturation"),
160 babl_component ("value"),
161 babl_component ("alpha"),
162 NULL
165 babl_format_new (
166 "name", "HSV float",
167 babl_model ("HSV"),
168 babl_type ("float"),
169 babl_component ("hue"),
170 babl_component ("saturation"),
171 babl_component ("value"),
172 NULL
176 static void
177 rgba_to_hsv_step (char *src,
178 char *dst)
180 double hue, saturation, value;
181 double min, chroma;
183 double red = linear_to_gamma_2_2 (((double *) src)[0]);
184 double green = linear_to_gamma_2_2 (((double *) src)[1]);
185 double blue = linear_to_gamma_2_2 (((double *) src)[2]);
187 if (red > green)
189 value = MAX (red, blue);
190 min = MIN (green, blue);
192 else
194 value = MAX (green, blue);
195 min = MIN (red, blue);
198 chroma = value - min;
200 if (value < EPSILON)
201 saturation = 0.0;
202 else
203 saturation = chroma / value;
205 if (saturation < EPSILON)
207 hue = 0.0;
209 else
211 if (fabs (red - value) < EPSILON)
213 hue = (green - blue) / chroma;
215 if (hue < 0.0)
216 hue += 6.0;
218 else if (fabs (green - value) < EPSILON)
219 hue = 2.0 + (blue - red) / chroma;
220 else
221 hue = 4.0 + (red - green) / chroma;
223 hue /= 6.0;
226 ((double *) dst)[0] = hue;
227 ((double *) dst)[1] = saturation;
228 ((double *) dst)[2] = value;
232 static void
233 hsv_to_rgba_step (char *src,
234 char *dst)
236 double hue = ((double *) src)[0];
237 double saturation = ((double *) src)[1];
238 double value = ((double *) src)[2];
240 double red = 0, green = 0, blue = 0;
242 double chroma, h_tmp, x, min;
244 chroma = saturation * value;
246 h_tmp = fmod (hue, 1.0);
247 h_tmp += h_tmp < 0.0;
248 h_tmp *= 6.0;
250 x = chroma * (1.0 - fabs (fmod (h_tmp, 2.0) - 1.0));
252 if (h_tmp < 1.0)
254 red = chroma;
255 green = x;
257 else if (h_tmp < 2.0)
259 red = x;
260 green = chroma;
262 else if (h_tmp < 3.0)
264 green = chroma;
265 blue = x;
267 else if (h_tmp < 4.0)
269 green = x;
270 blue = chroma;
272 else if (h_tmp < 5.0)
274 red = x;
275 blue = chroma;
277 else if (h_tmp < 6.0)
279 red = chroma;
280 blue = x;
283 min = value - chroma;
285 red += min;
286 green += min;
287 blue += min;
289 ((double *) dst)[0] = gamma_2_2_to_linear (red);
290 ((double *) dst)[1] = gamma_2_2_to_linear (green);
291 ((double *) dst)[2] = gamma_2_2_to_linear (blue);
294 static void
295 rgba_to_hsva (const Babl *conversion,
296 char *src,
297 char *dst,
298 long samples)
300 long n = samples;
302 while (n--)
304 double alpha = ((double *) src)[3];
306 rgba_to_hsv_step (src, dst);
308 ((double *) dst)[3] = alpha;
310 src += 4 * sizeof (double);
311 dst += 4 * sizeof (double);
315 static void
316 hsva_to_rgba (const Babl *conversion,
317 char *src,
318 char *dst,
319 long samples)
321 long n = samples;
323 while (n--)
325 double alpha = ((double *) src)[3];
327 hsv_to_rgba_step (src, dst);
329 ((double *) dst)[3] = alpha;
331 src += 4 * sizeof (double);
332 dst += 4 * sizeof (double);
336 static void
337 rgba_to_hsv (const Babl *conversion,
338 char *src,
339 char *dst,
340 long samples)
342 long n = samples;
344 while (n--)
346 rgba_to_hsv_step (src, dst);
348 src += 4 * sizeof (double);
349 dst += 3 * sizeof (double);
353 static void
354 hsv_to_rgba (const Babl *conversion,
355 char *src,
356 char *dst,
357 long samples)
359 long n = samples;
361 while (n--)
363 hsv_to_rgba_step (src, dst);
365 ((double *) dst)[3] = 1.0;
367 src += 3 * sizeof (double);
368 dst += 4 * sizeof (double);