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.
5 // Package color implements a basic color library.
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
16 // An alpha-premultiplied color component c has been scaled by alpha (a),
17 // so has valid values 0 <= c <= a.
18 RGBA() (r
, g
, b
, a
uint32)
21 // RGBA represents a traditional 32-bit alpha-premultiplied color, having 8
22 // bits for each of red, green, blue and alpha.
24 // An alpha-premultiplied color component C has been scaled by alpha (A), so
25 // has valid values 0 <= C <= A.
30 func (c RGBA
) RGBA() (r
, g
, b
, a
uint32) {
42 // RGBA64 represents a 64-bit alpha-premultiplied color, having 16 bits for
43 // each of red, green, blue and alpha.
45 // An alpha-premultiplied color component C has been scaled by alpha (A), so
46 // has valid values 0 <= C <= A.
51 func (c RGBA64
) RGBA() (r
, g
, b
, a
uint32) {
52 return uint32(c
.R
), uint32(c
.G
), uint32(c
.B
), uint32(c
.A
)
55 // NRGBA represents a non-alpha-premultiplied 32-bit color.
60 func (c NRGBA
) RGBA() (r
, g
, b
, a
uint32) {
78 // NRGBA64 represents a non-alpha-premultiplied 64-bit color,
79 // having 16 bits for each of red, green, blue and alpha.
84 func (c NRGBA64
) RGBA() (r
, g
, b
, a
uint32) {
98 // Alpha represents an 8-bit alpha color.
103 func (c Alpha
) RGBA() (r
, g
, b
, a
uint32) {
109 // Alpha16 represents a 16-bit alpha color.
110 type Alpha16
struct {
114 func (c Alpha16
) RGBA() (r
, g
, b
, a
uint32) {
119 // Gray represents an 8-bit grayscale color.
124 func (c Gray
) RGBA() (r
, g
, b
, a
uint32) {
127 return y
, y
, y
, 0xffff
130 // Gray16 represents a 16-bit grayscale color.
135 func (c Gray16
) RGBA() (r
, g
, b
, a
uint32) {
137 return y
, y
, y
, 0xffff
140 // Model can convert any Color to one from its own color model. The conversion
142 type Model
interface {
143 Convert(c Color
) Color
146 // ModelFunc returns a Model that invokes f to implement the conversion.
147 func ModelFunc(f
func(Color
) Color
) Model
{
148 // Note: using *modelFunc as the implementation
149 // means that callers can still use comparisons
150 // like m == RGBAModel. This is not possible if
151 // we use the func value directly, because funcs
152 // are no longer comparable.
156 type modelFunc
struct {
160 func (m
*modelFunc
) Convert(c Color
) Color
{
164 // Models for the standard color types.
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
)
176 func rgbaModel(c Color
) Color
{
177 if _
, ok
:= c
.(RGBA
); ok
{
180 r
, g
, b
, a
:= c
.RGBA()
181 return RGBA
{uint8(r
>> 8), uint8(g
>> 8), uint8(b
>> 8), uint8(a
>> 8)}
184 func rgba64Model(c Color
) Color
{
185 if _
, ok
:= c
.(RGBA64
); ok
{
188 r
, g
, b
, a
:= c
.RGBA()
189 return RGBA64
{uint16(r
), uint16(g
), uint16(b
), uint16(a
)}
192 func nrgbaModel(c Color
) Color
{
193 if _
, ok
:= c
.(NRGBA
); ok
{
196 r
, g
, b
, a
:= c
.RGBA()
198 return NRGBA
{uint8(r
>> 8), uint8(g
>> 8), uint8(b
>> 8), 0xff}
201 return NRGBA
{0, 0, 0, 0}
203 // Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
207 return NRGBA
{uint8(r
>> 8), uint8(g
>> 8), uint8(b
>> 8), uint8(a
>> 8)}
210 func nrgba64Model(c Color
) Color
{
211 if _
, ok
:= c
.(NRGBA64
); ok
{
214 r
, g
, b
, a
:= c
.RGBA()
216 return NRGBA64
{uint16(r
), uint16(g
), uint16(b
), 0xffff}
219 return NRGBA64
{0, 0, 0, 0}
221 // Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
225 return NRGBA64
{uint16(r
), uint16(g
), uint16(b
), uint16(a
)}
228 func alphaModel(c Color
) Color
{
229 if _
, ok
:= c
.(Alpha
); ok
{
232 _
, _
, _
, a
:= c
.RGBA()
233 return Alpha
{uint8(a
>> 8)}
236 func alpha16Model(c Color
) Color
{
237 if _
, ok
:= c
.(Alpha16
); ok
{
240 _
, _
, _
, a
:= c
.RGBA()
241 return Alpha16
{uint16(a
)}
244 func grayModel(c Color
) Color
{
245 if _
, ok
:= c
.(Gray
); ok
{
248 r
, g
, b
, _
:= c
.RGBA()
250 // These coefficients (the fractions 0.299, 0.587 and 0.114) are the same
251 // as those given by the JFIF specification and used by func RGBToYCbCr in
254 // Note that 19595 + 38470 + 7471 equals 65536.
256 // The 24 is 16 + 8. The 16 is the same as used in RGBToYCbCr. The 8 is
257 // because the return value is 8 bit color, not 16 bit color.
258 y
:= (19595*r
+ 38470*g
+ 7471*b
+ 1<<15) >> 24
260 return Gray
{uint8(y
)}
263 func gray16Model(c Color
) Color
{
264 if _
, ok
:= c
.(Gray16
); ok
{
267 r
, g
, b
, _
:= c
.RGBA()
269 // These coefficients (the fractions 0.299, 0.587 and 0.114) are the same
270 // as those given by the JFIF specification and used by func RGBToYCbCr in
273 // Note that 19595 + 38470 + 7471 equals 65536.
274 y
:= (19595*r
+ 38470*g
+ 7471*b
+ 1<<15) >> 16
276 return Gray16
{uint16(y
)}
279 // Palette is a palette of colors.
282 // Convert returns the palette color closest to c in Euclidean R,G,B space.
283 func (p Palette
) Convert(c Color
) Color
{
290 // Index returns the index of the palette color closest to c in Euclidean
292 func (p Palette
) Index(c Color
) int {
293 // A batch version of this computation is in image/draw/draw.go.
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
)
304 ret
, bestSum
= i
, sum
310 // sqDiff returns the squared-difference of x and y, shifted by 2 so that
311 // adding four of those won't overflow a uint32.
313 // x and y are both assumed to be in the range [0, 0xffff].
314 func sqDiff(x
, y
uint32) uint32 {
327 White
= Gray16
{0xffff}
328 Transparent
= Alpha16
{0}
329 Opaque
= Alpha16
{0xffff}