1
2
3
4
5
6 package color
7
8
9
10 type Color interface {
11
12
13
14
15
16
17
18 RGBA() (r, g, b, a uint32)
19 }
20
21
22
23
24
25
26 type RGBA struct {
27 R, G, B, A uint8
28 }
29
30 func (c RGBA) RGBA() (r, g, b, a uint32) {
31 r = uint32(c.R)
32 r |= r << 8
33 g = uint32(c.G)
34 g |= g << 8
35 b = uint32(c.B)
36 b |= b << 8
37 a = uint32(c.A)
38 a |= a << 8
39 return
40 }
41
42
43
44
45
46
47 type RGBA64 struct {
48 R, G, B, A uint16
49 }
50
51 func (c RGBA64) RGBA() (r, g, b, a uint32) {
52 return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
53 }
54
55
56 type NRGBA struct {
57 R, G, B, A uint8
58 }
59
60 func (c NRGBA) RGBA() (r, g, b, a uint32) {
61 r = uint32(c.R)
62 r |= r << 8
63 r *= uint32(c.A)
64 r /= 0xff
65 g = uint32(c.G)
66 g |= g << 8
67 g *= uint32(c.A)
68 g /= 0xff
69 b = uint32(c.B)
70 b |= b << 8
71 b *= uint32(c.A)
72 b /= 0xff
73 a = uint32(c.A)
74 a |= a << 8
75 return
76 }
77
78
79
80 type NRGBA64 struct {
81 R, G, B, A uint16
82 }
83
84 func (c NRGBA64) RGBA() (r, g, b, a uint32) {
85 r = uint32(c.R)
86 r *= uint32(c.A)
87 r /= 0xffff
88 g = uint32(c.G)
89 g *= uint32(c.A)
90 g /= 0xffff
91 b = uint32(c.B)
92 b *= uint32(c.A)
93 b /= 0xffff
94 a = uint32(c.A)
95 return
96 }
97
98
99 type Alpha struct {
100 A uint8
101 }
102
103 func (c Alpha) RGBA() (r, g, b, a uint32) {
104 a = uint32(c.A)
105 a |= a << 8
106 return a, a, a, a
107 }
108
109
110 type Alpha16 struct {
111 A uint16
112 }
113
114 func (c Alpha16) RGBA() (r, g, b, a uint32) {
115 a = uint32(c.A)
116 return a, a, a, a
117 }
118
119
120 type Gray struct {
121 Y uint8
122 }
123
124 func (c Gray) RGBA() (r, g, b, a uint32) {
125 y := uint32(c.Y)
126 y |= y << 8
127 return y, y, y, 0xffff
128 }
129
130
131 type Gray16 struct {
132 Y uint16
133 }
134
135 func (c Gray16) RGBA() (r, g, b, a uint32) {
136 y := uint32(c.Y)
137 return y, y, y, 0xffff
138 }
139
140
141
142 type Model interface {
143 Convert(c Color) Color
144 }
145
146
147 func ModelFunc(f func(Color) Color) Model {
148
149
150
151
152
153 return &modelFunc{f}
154 }
155
156 type modelFunc struct {
157 f func(Color) Color
158 }
159
160 func (m *modelFunc) Convert(c Color) Color {
161 return m.f(c)
162 }
163
164
165 var (
166 RGBAModel Model = ModelFunc(rgbaModel)
167 RGBA64Model Model = ModelFunc(rgba64Model)
168 NRGBAModel Model = ModelFunc(nrgbaModel)
169 NRGBA64Model Model = ModelFunc(nrgba64Model)
170 AlphaModel Model = ModelFunc(alphaModel)
171 Alpha16Model Model = ModelFunc(alpha16Model)
172 GrayModel Model = ModelFunc(grayModel)
173 Gray16Model Model = ModelFunc(gray16Model)
174 )
175
176 func rgbaModel(c Color) Color {
177 if _, ok := c.(RGBA); ok {
178 return c
179 }
180 r, g, b, a := c.RGBA()
181 return RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
182 }
183
184 func rgba64Model(c Color) Color {
185 if _, ok := c.(RGBA64); ok {
186 return c
187 }
188 r, g, b, a := c.RGBA()
189 return RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
190 }
191
192 func nrgbaModel(c Color) Color {
193 if _, ok := c.(NRGBA); ok {
194 return c
195 }
196 r, g, b, a := c.RGBA()
197 if a == 0xffff {
198 return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), 0xff}
199 }
200 if a == 0 {
201 return NRGBA{0, 0, 0, 0}
202 }
203
204 r = (r * 0xffff) / a
205 g = (g * 0xffff) / a
206 b = (b * 0xffff) / a
207 return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
208 }
209
210 func nrgba64Model(c Color) Color {
211 if _, ok := c.(NRGBA64); ok {
212 return c
213 }
214 r, g, b, a := c.RGBA()
215 if a == 0xffff {
216 return NRGBA64{uint16(r), uint16(g), uint16(b), 0xffff}
217 }
218 if a == 0 {
219 return NRGBA64{0, 0, 0, 0}
220 }
221
222 r = (r * 0xffff) / a
223 g = (g * 0xffff) / a
224 b = (b * 0xffff) / a
225 return NRGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
226 }
227
228 func alphaModel(c Color) Color {
229 if _, ok := c.(Alpha); ok {
230 return c
231 }
232 _, _, _, a := c.RGBA()
233 return Alpha{uint8(a >> 8)}
234 }
235
236 func alpha16Model(c Color) Color {
237 if _, ok := c.(Alpha16); ok {
238 return c
239 }
240 _, _, _, a := c.RGBA()
241 return Alpha16{uint16(a)}
242 }
243
244 func grayModel(c Color) Color {
245 if _, ok := c.(Gray); ok {
246 return c
247 }
248 r, g, b, _ := c.RGBA()
249
250
251
252
253
254
255
256
257
258 y := (19595*r + 38470*g + 7471*b + 1<<15) >> 24
259
260 return Gray{uint8(y)}
261 }
262
263 func gray16Model(c Color) Color {
264 if _, ok := c.(Gray16); ok {
265 return c
266 }
267 r, g, b, _ := c.RGBA()
268
269
270
271
272
273
274 y := (19595*r + 38470*g + 7471*b + 1<<15) >> 16
275
276 return Gray16{uint16(y)}
277 }
278
279
280 type Palette []Color
281
282
283 func (p Palette) Convert(c Color) Color {
284 if len(p) == 0 {
285 return nil
286 }
287 return p[p.Index(c)]
288 }
289
290
291
292 func (p Palette) Index(c Color) int {
293
294
295 cr, cg, cb, ca := c.RGBA()
296 ret, bestSum := 0, uint32(1<<32-1)
297 for i, v := range p {
298 vr, vg, vb, va := v.RGBA()
299 sum := sqDiff(cr, vr) + sqDiff(cg, vg) + sqDiff(cb, vb) + sqDiff(ca, va)
300 if sum < bestSum {
301 if sum == 0 {
302 return i
303 }
304 ret, bestSum = i, sum
305 }
306 }
307 return ret
308 }
309
310
311
312
313
314 func sqDiff(x, y uint32) uint32 {
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337 d := x - y
338 return (d * d) >> 2
339 }
340
341
342 var (
343 Black = Gray16{0}
344 White = Gray16{0xffff}
345 Transparent = Alpha16{0}
346 Opaque = Alpha16{0xffff}
347 )
348
View as plain text