Source file src/pkg/image/color/color.go
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package color implements a basic color library.
6 package color
7
8 // Color can convert itself to alpha-premultiplied 16-bits per channel RGBA.
9 // The conversion may be lossy.
10 type Color interface {
11 // RGBA returns the alpha-premultiplied red, green, blue and alpha values
12 // for the color. Each value ranges within [0, 0xFFFF], but is represented
13 // by a uint32 so that multiplying by a blend factor up to 0xFFFF will not
14 // overflow.
15 RGBA() (r, g, b, a uint32)
16 }
17
18 // RGBA represents a traditional 32-bit alpha-premultiplied color,
19 // having 8 bits for each of red, green, blue and alpha.
20 type RGBA struct {
21 R, G, B, A uint8
22 }
23
24 func (c RGBA) RGBA() (r, g, b, a uint32) {
25 r = uint32(c.R)
26 r |= r << 8
27 g = uint32(c.G)
28 g |= g << 8
29 b = uint32(c.B)
30 b |= b << 8
31 a = uint32(c.A)
32 a |= a << 8
33 return
34 }
35
36 // RGBA64 represents a 64-bit alpha-premultiplied color,
37 // having 16 bits for each of red, green, blue and alpha.
38 type RGBA64 struct {
39 R, G, B, A uint16
40 }
41
42 func (c RGBA64) RGBA() (r, g, b, a uint32) {
43 return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
44 }
45
46 // NRGBA represents a non-alpha-premultiplied 32-bit color.
47 type NRGBA struct {
48 R, G, B, A uint8
49 }
50
51 func (c NRGBA) RGBA() (r, g, b, a uint32) {
52 r = uint32(c.R)
53 r |= r << 8
54 r *= uint32(c.A)
55 r /= 0xff
56 g = uint32(c.G)
57 g |= g << 8
58 g *= uint32(c.A)
59 g /= 0xff
60 b = uint32(c.B)
61 b |= b << 8
62 b *= uint32(c.A)
63 b /= 0xff
64 a = uint32(c.A)
65 a |= a << 8
66 return
67 }
68
69 // NRGBA64 represents a non-alpha-premultiplied 64-bit color,
70 // having 16 bits for each of red, green, blue and alpha.
71 type NRGBA64 struct {
72 R, G, B, A uint16
73 }
74
75 func (c NRGBA64) RGBA() (r, g, b, a uint32) {
76 r = uint32(c.R)
77 r *= uint32(c.A)
78 r /= 0xffff
79 g = uint32(c.G)
80 g *= uint32(c.A)
81 g /= 0xffff
82 b = uint32(c.B)
83 b *= uint32(c.A)
84 b /= 0xffff
85 a = uint32(c.A)
86 return
87 }
88
89 // Alpha represents an 8-bit alpha color.
90 type Alpha struct {
91 A uint8
92 }
93
94 func (c Alpha) RGBA() (r, g, b, a uint32) {
95 a = uint32(c.A)
96 a |= a << 8
97 return a, a, a, a
98 }
99
100 // Alpha16 represents a 16-bit alpha color.
101 type Alpha16 struct {
102 A uint16
103 }
104
105 func (c Alpha16) RGBA() (r, g, b, a uint32) {
106 a = uint32(c.A)
107 return a, a, a, a
108 }
109
110 // Gray represents an 8-bit grayscale color.
111 type Gray struct {
112 Y uint8
113 }
114
115 func (c Gray) RGBA() (r, g, b, a uint32) {
116 y := uint32(c.Y)
117 y |= y << 8
118 return y, y, y, 0xffff
119 }
120
121 // Gray16 represents a 16-bit grayscale color.
122 type Gray16 struct {
123 Y uint16
124 }
125
126 func (c Gray16) RGBA() (r, g, b, a uint32) {
127 y := uint32(c.Y)
128 return y, y, y, 0xffff
129 }
130
131 // Model can convert any Color to one from its own color model. The conversion
132 // may be lossy.
133 type Model interface {
134 Convert(c Color) Color
135 }
136
137 // ModelFunc returns a Model that invokes f to implement the conversion.
138 func ModelFunc(f func(Color) Color) Model {
139 // Note: using *modelFunc as the implementation
140 // means that callers can still use comparisons
141 // like m == RGBAModel. This is not possible if
142 // we use the func value directly, because funcs
143 // are no longer comparable.
144 return &modelFunc{f}
145 }
146
147 type modelFunc struct {
148 f func(Color) Color
149 }
150
151 func (m *modelFunc) Convert(c Color) Color {
152 return m.f(c)
153 }
154
155 // Models for the standard color types.
156 var (
157 RGBAModel Model = ModelFunc(rgbaModel)
158 RGBA64Model Model = ModelFunc(rgba64Model)
159 NRGBAModel Model = ModelFunc(nrgbaModel)
160 NRGBA64Model Model = ModelFunc(nrgba64Model)
161 AlphaModel Model = ModelFunc(alphaModel)
162 Alpha16Model Model = ModelFunc(alpha16Model)
163 GrayModel Model = ModelFunc(grayModel)
164 Gray16Model Model = ModelFunc(gray16Model)
165 )
166
167 func rgbaModel(c Color) Color {
168 if _, ok := c.(RGBA); ok {
169 return c
170 }
171 r, g, b, a := c.RGBA()
172 return RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
173 }
174
175 func rgba64Model(c Color) Color {
176 if _, ok := c.(RGBA64); ok {
177 return c
178 }
179 r, g, b, a := c.RGBA()
180 return RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
181 }
182
183 func nrgbaModel(c Color) Color {
184 if _, ok := c.(NRGBA); ok {
185 return c
186 }
187 r, g, b, a := c.RGBA()
188 if a == 0xffff {
189 return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), 0xff}
190 }
191 if a == 0 {
192 return NRGBA{0, 0, 0, 0}
193 }
194 // Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
195 r = (r * 0xffff) / a
196 g = (g * 0xffff) / a
197 b = (b * 0xffff) / a
198 return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
199 }
200
201 func nrgba64Model(c Color) Color {
202 if _, ok := c.(NRGBA64); ok {
203 return c
204 }
205 r, g, b, a := c.RGBA()
206 if a == 0xffff {
207 return NRGBA64{uint16(r), uint16(g), uint16(b), 0xffff}
208 }
209 if a == 0 {
210 return NRGBA64{0, 0, 0, 0}
211 }
212 // Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
213 r = (r * 0xffff) / a
214 g = (g * 0xffff) / a
215 b = (b * 0xffff) / a
216 return NRGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
217 }
218
219 func alphaModel(c Color) Color {
220 if _, ok := c.(Alpha); ok {
221 return c
222 }
223 _, _, _, a := c.RGBA()
224 return Alpha{uint8(a >> 8)}
225 }
226
227 func alpha16Model(c Color) Color {
228 if _, ok := c.(Alpha16); ok {
229 return c
230 }
231 _, _, _, a := c.RGBA()
232 return Alpha16{uint16(a)}
233 }
234
235 func grayModel(c Color) Color {
236 if _, ok := c.(Gray); ok {
237 return c
238 }
239 r, g, b, _ := c.RGBA()
240 y := (299*r + 587*g + 114*b + 500) / 1000
241 return Gray{uint8(y >> 8)}
242 }
243
244 func gray16Model(c Color) Color {
245 if _, ok := c.(Gray16); ok {
246 return c
247 }
248 r, g, b, _ := c.RGBA()
249 y := (299*r + 587*g + 114*b + 500) / 1000
250 return Gray16{uint16(y)}
251 }
252
253 // Palette is a palette of colors.
254 type Palette []Color
255
256 func diff(a, b uint32) uint32 {
257 if a > b {
258 return a - b
259 }
260 return b - a
261 }
262
263 // Convert returns the palette color closest to c in Euclidean R,G,B space.
264 func (p Palette) Convert(c Color) Color {
265 if len(p) == 0 {
266 return nil
267 }
268 return p[p.Index(c)]
269 }
270
271 // Index returns the index of the palette color closest to c in Euclidean
272 // R,G,B space.
273 func (p Palette) Index(c Color) int {
274 cr, cg, cb, _ := c.RGBA()
275 // Shift by 1 bit to avoid potential uint32 overflow in sum-squared-difference.
276 cr >>= 1
277 cg >>= 1
278 cb >>= 1
279 ret, bestSSD := 0, uint32(1<<32-1)
280 for i, v := range p {
281 vr, vg, vb, _ := v.RGBA()
282 vr >>= 1
283 vg >>= 1
284 vb >>= 1
285 dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb)
286 ssd := (dr * dr) + (dg * dg) + (db * db)
287 if ssd < bestSSD {
288 if ssd == 0 {
289 return i
290 }
291 ret, bestSSD = i, ssd
292 }
293 }
294 return ret
295 }
296
297 // Standard colors.
298 var (
299 Black = Gray16{0}
300 White = Gray16{0xffff}
301 Transparent = Alpha16{0}
302 Opaque = Alpha16{0xffff}
303 )