implement fountain fills similar to most paint programs
[imager.git] / color.c
1 #include "image.h"
2
3 /*
4 =head1 NAME
5
6 color.c - color manipulation functions
7
8 =head1 SYNOPSIS
9
10   i_fcolor color;
11   i_rgb_to_hsvf(&color);
12   i_hsv_to_rgbf(&color);
13
14 =head1 DESCRIPTION
15
16 A collection of utility functions for converting between color spaces.
17
18 */
19
20 #define EPSILON (1e-8)
21
22 /*
23 =item i_rgb2hsvf(&color)
24
25 Converts the first 3 channels of color into hue, saturation and value.
26
27 Each value is scaled into the range 0 to 1.0.
28
29 =cut
30 */
31 void i_rgb_to_hsvf(i_fcolor *color) {
32   double h, s, v;
33   double temp;
34   double Cr, Cg, Cb;
35
36   v = max(max(color->rgb.r, color->rgb.g), color->rgb.b);
37   temp = min(min(color->rgb.r, color->rgb.g), color->rgb.b);
38   if (v < EPSILON)
39     s = 0;
40   else
41     s = (v-temp)/v;
42   if (s == 0)
43     h = 0;
44   else {
45     Cr = (v - color->rgb.r)/(v-temp);
46     Cg = (v - color->rgb.g)/(v-temp);
47     Cb = (v - color->rgb.b)/(v-temp);
48     if (color->rgb.r == v)
49       h = Cb - Cg;
50     else if (color->rgb.g == v)
51       h = 2 + Cr - Cb;
52     else if (color->rgb.b == v)
53       h = 4 + Cg - Cr;
54     h = 60 * h;
55     if (h < 0)
56       h += 360;
57   }
58   color->channel[0] = h / 360.0;
59   color->channel[1] = s;
60   color->channel[2] = v;
61 }
62
63 /*
64 =item i_hsv_to_rgbf(&color)
65
66 Convert a HSV value to an RGB value, each value ranges from 0 to 1.
67
68 =cut
69 */
70
71 void i_hsv_to_rgbf(i_fcolor *color) {
72   double h = color->channel[0];
73   double s = color->channel[1];
74   double v = color->channel[2];
75
76   if (color->channel[1] < EPSILON) {
77     /* ignore h in this case */
78     color->rgb.r = color->rgb.g = color->rgb.b = v;
79   }
80   else {
81     int i;
82     double f, m, n, k;
83     h = fmod(h, 1.0) * 6;
84     i = h;
85     f = h - i;
86     m = v * (1 - s);
87     n = v * (1 - s * f);
88     k = v * (1 - s * (1 - f));
89     switch (i) {
90     case 0:
91       color->rgb.r = v; color->rgb.g = k; color->rgb.b = m;
92       break;
93     case 1:
94       color->rgb.r = n; color->rgb.g = v; color->rgb.b = m;
95       break;
96     case 2:
97       color->rgb.r = m; color->rgb.g = v; color->rgb.b = k;
98       break;
99     case 3:
100       color->rgb.r = m; color->rgb.g = n; color->rgb.b = v;
101       break;
102     case 4:
103       color->rgb.r = k; color->rgb.g = m; color->rgb.b = v;
104       break;
105     case 5:
106       color->rgb.r = v; color->rgb.g = m; color->rgb.b = n;
107       break;
108     }
109   }
110 }
111
112 /*
113 =back
114
115 =head1 AUTHOR
116
117 Tony Cook <tony@develop-help.com>
118
119 =head1 SEE ALSO
120
121 Imager
122
123 =cut
124 */