File Coverage

color.c
Criterion Covered Total %
statement 93 102 91.1
branch 33 40 82.5
condition n/a
subroutine n/a
pod n/a
total 126 142 88.7


line stmt bran cond sub pod time code
1             #include "imager.h"
2             #include
3              
4             /*
5             =head1 NAME
6              
7             color.c - color manipulation functions
8              
9             =head1 SYNOPSIS
10              
11             i_fcolor color;
12             i_rgb_to_hsvf(&color);
13             i_hsv_to_rgbf(&color);
14              
15             =head1 DESCRIPTION
16              
17             A collection of utility functions for converting between color spaces.
18              
19             =over
20              
21             =cut
22             */
23              
24             #define EPSILON (1e-8)
25              
26             #define my_max(a, b) ((a) < (b) ? (b) : (a))
27             #define my_min(a, b) ((a) > (b) ? (b) : (a))
28              
29             /*
30             =item i_rgb2hsvf(&color)
31              
32             Converts the first 3 channels of color into hue, saturation and value.
33              
34             Each value is scaled into the range 0 to 1.0.
35              
36             =cut
37             */
38 90395           void i_rgb_to_hsvf(i_fcolor *color) {
39 90395           double h = 0, s, v;
40             double temp;
41             double Cr, Cg, Cb;
42              
43 90395 100         v = my_max(my_max(color->rgb.r, color->rgb.g), color->rgb.b);
    100          
    100          
44 90395 100         temp = my_min(my_min(color->rgb.r, color->rgb.g), color->rgb.b);
    100          
    100          
45 90395 100         if (v < EPSILON)
46 31928           s = 0;
47             else
48 58467           s = (v-temp)/v;
49 90395 100         if (s == 0)
50 50003           h = 0;
51             else {
52 40392           Cr = (v - color->rgb.r)/(v-temp);
53 40392           Cg = (v - color->rgb.g)/(v-temp);
54 40392           Cb = (v - color->rgb.b)/(v-temp);
55 40392 100         if (color->rgb.r == v)
56 9397           h = Cb - Cg;
57 30995 100         else if (color->rgb.g == v)
58 20295           h = 2 + Cr - Cb;
59 10700 50         else if (color->rgb.b == v)
60 10700           h = 4 + Cg - Cr;
61 40392           h = 60 * h;
62 40392 100         if (h < 0)
63 2585           h += 360;
64             }
65 90395           color->channel[0] = h / 360.0;
66 90395           color->channel[1] = s;
67 90395           color->channel[2] = v;
68 90395           }
69              
70             /*
71             =item i_rgb2hsv(&color)
72              
73             Converts the first 3 channels of color into hue, saturation and value.
74              
75             Each value is scaled into the range 0 to 255.
76              
77             =cut
78             */
79 389           void i_rgb_to_hsv(i_color *color) {
80 389           double h = 0, s, v;
81             double temp;
82             double Cr, Cg, Cb;
83              
84 389           v = my_max(my_max(color->rgb.r, color->rgb.g), color->rgb.b);
85 389           temp = my_min(my_min(color->rgb.r, color->rgb.g), color->rgb.b);
86 389 50         if (v == 0)
87 0           s = 0;
88             else
89 389           s = (v-temp)*255/v;
90 389 50         if (s == 0)
91 0           h = 0;
92             else {
93 389           Cr = (v - color->rgb.r)/(v-temp);
94 389           Cg = (v - color->rgb.g)/(v-temp);
95 389           Cb = (v - color->rgb.b)/(v-temp);
96 389 100         if (color->rgb.r == v)
97 387           h = Cb - Cg;
98 2 50         else if (color->rgb.g == v)
99 2           h = 2 + Cr - Cb;
100 0 0         else if (color->rgb.b == v)
101 0           h = 4 + Cg - Cr;
102 389           h = h * 60.0;
103 389 100         if (h < 0)
104 193           h += 360;
105             }
106 389           color->channel[0] = h * 255 / 360.0;
107 389           color->channel[1] = s;
108 389           color->channel[2] = v;
109 389           }
110              
111             /*
112             =item i_hsv_to_rgbf(&color)
113              
114             Convert a HSV value to an RGB value, each value ranges from 0 to 1.
115              
116             =cut
117             */
118              
119 86561           void i_hsv_to_rgbf(i_fcolor *color) {
120 86561           double h = color->channel[0];
121 86561           double s = color->channel[1];
122 86561           double v = color->channel[2];
123              
124 86561 100         if (color->channel[1] < EPSILON) {
125             /* ignore h in this case */
126 29213           color->rgb.r = color->rgb.g = color->rgb.b = v;
127             }
128             else {
129             int i;
130             double f, m, n, k;
131 57348           h = fmod(h, 1.0) * 6;
132 57348           i = floor(h);
133 57348           f = h - i;
134 57348           m = v * (1 - s);
135 57348           n = v * (1 - s * f);
136 57348           k = v * (1 - s * (1 - f));
137 57348           switch (i) {
138             case 0:
139 10014           color->rgb.r = v; color->rgb.g = k; color->rgb.b = m;
140 10014           break;
141             case 1:
142 4888           color->rgb.r = n; color->rgb.g = v; color->rgb.b = m;
143 4888           break;
144             case 2:
145 13984           color->rgb.r = m; color->rgb.g = v; color->rgb.b = k;
146 13984           break;
147             case 3:
148 3952           color->rgb.r = m; color->rgb.g = n; color->rgb.b = v;
149 3952           break;
150             case 4:
151 10095           color->rgb.r = k; color->rgb.g = m; color->rgb.b = v;
152 10095           break;
153             case 5:
154 14415           color->rgb.r = v; color->rgb.g = m; color->rgb.b = n;
155 14415           break;
156             }
157             }
158 86561           }
159              
160             /*
161             =item i_hsv_to_rgb(&color)
162              
163             Convert a HSV value to an RGB value, each value ranges from 0 to 1.
164              
165             =cut
166             */
167              
168 197           void i_hsv_to_rgb(i_color *color) {
169 197           double h = color->channel[0];
170 197           double s = color->channel[1];
171 197           double v = color->channel[2];
172              
173 197 50         if (color->channel[1] == 0) {
174             /* ignore h in this case */
175 0           color->rgb.r = color->rgb.g = color->rgb.b = v;
176             }
177             else {
178             int i;
179             double f;
180             int m, n, k;
181 197           h = h / 255.0 * 6;
182 197           i = h;
183 197           f = h - i;
184 197           m = 0.5 + v * (255 - s) / 255;
185 197           n = 0.5 + v * (255 - s * f) / 255;
186 197           k = 0.5 + v * (255 - s * (1 - f)) / 255;
187 197           switch (i) {
188             case 0:
189 98           color->rgb.r = v; color->rgb.g = k; color->rgb.b = m;
190 98           break;
191             case 1:
192 2           color->rgb.r = n; color->rgb.g = v; color->rgb.b = m;
193 2           break;
194             case 2:
195 0           color->rgb.r = m; color->rgb.g = v; color->rgb.b = k;
196 0           break;
197             case 3:
198 0           color->rgb.r = m; color->rgb.g = n; color->rgb.b = v;
199 0           break;
200             case 4:
201 96           color->rgb.r = k; color->rgb.g = m; color->rgb.b = v;
202 96           break;
203             case 5:
204 1           color->rgb.r = v; color->rgb.g = m; color->rgb.b = n;
205 1           break;
206             }
207             }
208 197           }
209              
210             /*
211             =back
212              
213             =head1 AUTHOR
214              
215             Tony Cook
216              
217             =head1 SEE ALSO
218              
219             Imager
220              
221             =cut
222             */