···
4
+
import pwkit.colormaps # pip3 install pwkit
7
+
# Most calculations from http://www.chilliant.com/rgb2hsv.html
10
+
def limit(v, low=0, high=1):
11
+
return max(min(v, high), low)
14
+
LUMA_WEIGHTS = (0.299, 0.587, 0.114)
15
+
def __init__(self, r, g, b):
20
+
return iter((self.r, self.g, self.b))
22
+
return 'RGB({}, {}, {})'.format(self.r, self.g, self.b)
24
+
return 'rgb({}%,{}%,{}%)'.format(self.r*100, self.g*100, self.b*100)
25
+
def luma(self, wts=None):
26
+
if wts is None: wts = self.LUMA_WEIGHTS
28
+
return rw*self.r + gw*self.g + bw*self.b
34
+
r = abs(h * 6 - 3) - 1
35
+
g = 2 - abs(h * 6 - 2)
36
+
b = 2 - abs(h * 6 - 4)
37
+
return Srgb(limit(r), limit(g), limit(b))
40
+
def __init__(self, h, s, l):
41
+
self.h = float(h) % 1
45
+
return iter((self.h, self.s, self.l))
47
+
return 'HSL({}, {}, {})'.format(self.h, self.s, self.l)
49
+
r, g, b = self.toSrgb()
50
+
return 'rgb({}%,{}%,{}%)'.format(round(r*100), round(g*100), round(b*100))
52
+
hs = Srgb.fromHue(self.h)
53
+
c = (1 - abs(2 * self.l - 1)) * self.s
55
+
(hs.r - 0.5) * c + self.l,
56
+
(hs.g - 0.5) * c + self.l,
57
+
(hs.b - 0.5) * c + self.l
61
+
def __init__(self, h, s, v):
62
+
self.h = float(h) % 1
66
+
return iter((self.h, self.s, self.v))
68
+
return 'HSV({}, {}, {})'.format(self.h, self.s, self.v)
70
+
r, g, b = self.toSrgb()
71
+
return 'rgb({}%,{}%,{}%)'.format(round(r*100), round(g*100), round(b*100))
73
+
hs = Srgb.fromHue(self.h)
76
+
x = c * (1 - abs(hp % 2 - 1))
78
+
r1, g1, b1 = c, x, 0
80
+
r1, g1, b1 = x, c, 0
82
+
r1, g1, b1 = 0, c, x
84
+
r1, g1, b1 = 0, x, c
86
+
r1, g1, b1 = x, 0, c
88
+
r1, g1, b1 = c, 0, x
90
+
return Srgb(r1+m, g1+m, b1+m)
93
+
def __init__(self, h, s, l):
94
+
self.h = float(h) % 1
98
+
return iter((self.h, self.s, self.l))
100
+
return 'Sin({}, {}, {})'.format(self.h, self.s, self.l)
102
+
r, g, b = self.toSrgb()
103
+
return 'rgb({}%,{}%,{}%)'.format(round(r*100), round(g*100), round(b*100))
107
+
shift = self.l #* (1-2*scale)
109
+
shift + scale * math.cos(math.pi*2 * (h - 0/6)),
110
+
shift + scale * math.cos(math.pi*2 * (h - 2/6)),
111
+
shift + scale * math.cos(math.pi*2 * (h - 4/6)),
115
+
HCY_WEIGHTS = Srgb.LUMA_WEIGHTS
116
+
def __init__(self, h, c, y):
117
+
self.h = float(h) % 1
120
+
def __iter__(self):
121
+
return iter((self.h, self.c, self.y))
122
+
def __repr__(self):
123
+
return 'HCY({}, {}, {})'.format(self.h, self.c, self.y)
125
+
r, g, b = self.toSrgb()
126
+
return 'rgb({}%,{}%,{}%)'.format(r*100, g*100, b*100)
128
+
hs = Srgb.fromHue(self.h)
129
+
y = hs.luma(wts=self.HCY_WEIGHTS)
134
+
c *= (1 - self.y) / (1 - y)
136
+
(hs.r - y) * c + self.y,
137
+
(hs.g - y) * c + self.y,
138
+
(hs.b - y) * c + self.y,
141
+
def _rgbToHcv(srgb):
142
+
if srgb.g < srgb.b:
143
+
p = (srgb.b, srgb.g, -1., 2./3.)
145
+
p = (srgb.g, srgb.b, 0., -1./3.)
147
+
q = (p[0], p[1], p[3], srgb.r)
149
+
q = (srgb.r, p[1], p[2], p[0])
150
+
c = q[0] - min(q[3], q[1])
151
+
h = abs((q[3] - q[1]) / (6*c + 1e-10) + q[2])
152
+
return (h, c, q[0])
154
+
def fromSrgb(cls, srgb):
155
+
hcv = list(cls._rgbToHcv(srgb))
156
+
rw, gw, bw = cls.HCY_WEIGHTS
157
+
y = rw*srgb.r + gw*srgb.g + bw*srgb.b
158
+
hs = Srgb.fromHue(hcv[0])
159
+
z = rw*hs.r + gw*hs.g + bw*hs.b
161
+
hcv[1] *= z / (y + 1e-10)
163
+
hcv[1] *= (1 - z) / (1 - y + 1e-10)
164
+
return Hcy(hcv[0], hcv[1], y)
167
+
REF_WHITE = (0.95047, 1., 1.08883)
168
+
def __init__(self, l, a, b):
172
+
def __iter__(self):
173
+
return iter((self.l, self.a, self.b))
174
+
def __repr__(self):
175
+
return 'CIELAB({}, {}, {})'.format(self.l, self.a, self.b)
177
+
r, g, b = self.toSrgb()
178
+
return 'rgb({}%,{}%,{}%)'.format(round(r*100), round(g*100), round(b*100))
180
+
inArr = np.array((*self.l,), dtype=float)
181
+
xyz = pwkit.colormaps.cielab_to_xyz(inArr, self.REF_WHITE)
182
+
linSrgb = pwkit.colormaps.xyz_to_linsrgb(xyz)
183
+
r, g, b = pwkit.colormaps.linsrgb_to_srgb(linSrgb)
184
+
return Srgb(r, g, b)
186
+
def fromSrgb(cls, srgb, refWhite=None):
187
+
if refWhite is None: refWhite = cls.REF_WHITE
188
+
inArr = np.array((*srgb,), dtype=float)
189
+
linSrgb = pwkit.colormaps.srgb_to_linsrgb(inArr)
190
+
xyz = pwkit.colormaps.linsrgb_to_xyz(linSrgb)
191
+
l, a, b = pwkit.colormaps.xyz_to_cielab(xyz, refWhite)
192
+
return Cielab(l, a, b)
194
+
inArr = np.array((self.l, self.a, self.b))
195
+
xyz = pwkit.colormaps.cielab_to_xyz(inArr, self.REF_WHITE)
196
+
linSrgb = pwkit.colormaps.xyz_to_linsrgb(xyz)
197
+
r, g, b = pwkit.colormaps.linsrgb_to_srgb(linSrgb)
198
+
return Srgb(r, g, b)