-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcolor.c
116 lines (105 loc) · 1.56 KB
/
color.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "a.h"
typedef struct Color Color;
struct Color
{
ulong n;
Image *i;
};
Color cache[255] = {0};
int ncolors = 0;
Image*
ealloccolor(ulong n)
{
Image *i;
i = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, n);
if(i == nil)
sysfatal("allocimage: %r");
return i;
}
void
hsvtorgb(int h, int s, int v, int *r, int *g, int *b)
{
double dh, ds, dv, hh, p, q, t, ff;
long i;
dh = h;
ds = s/100.0;
dv = v/100.0;
if(ds <= 0.0){
*r = v;
*g = v;
*b = v;
}
hh = dh;
if(hh >= 360.0)
hh = 0.0;
hh /= 60.0;
i = (long)hh;
ff = hh - i;
p = dv * (1.0 - ds);
q = dv * (1.0 - (ds * ff));
t = dv * (1.0 - (ds * (1.0 - ff)));
switch(i) {
case 0:
*r = 255 * dv;
*g = 255 * t;
*b = 255 * p;
break;
case 1:
*r = 255 * q;
*g = 255 * dv;
*b = 255 * p;
break;
case 2:
*r = 255 * p;
*g = 255 * dv;
*b = 255 * t;
break;
case 3:
*r = 255 * p;
*g = 255 * q;
*b = 255 * dv;
break;
case 4:
*r = 255 * t;
*g = 255 * p;
*b = 255 * dv;
break;
case 5:
default:
*r = 255 * dv;
*g = 255 * p;
*b = 255 * q;
break;
}
}
Image*
color(int x, int y, int z, int hsv)
{
ulong n;
Image *c;
int i, r, g, b;
if(hsv)
hsvtorgb(x, y, z, &r, &g, &b);
else{
r = x;
g = y;
b = z;
}
c = nil;
n = (r << 24) | (g << 16) | (b << 8) | 0xFF;
for(i = 0; i < nelem(cache); i++){
if(cache[i].n == n){
c = cache[i].i;
break;
}
}
if(c == nil){
c = ealloccolor(n);
cache[ncolors].n = n;
cache[ncolors].i = c;
ncolors++;
if(ncolors == nelem(cache))
ncolors = 0;
}
return c;
}