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. 6package color 7 8// Color can convert itself to alpha-premultiplied 16-bits per channel RGBA. 9// The conversion may be lossy. 10type 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 // 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) 19} 20 21// RGBA represents a traditional 32-bit alpha-premultiplied color, having 8 22// bits for each of red, green, blue and alpha. 23// 24// An alpha-premultiplied color component C has been scaled by alpha (A), so 25// has valid values 0 <= C <= A. 26type RGBA struct { 27 R, G, B, A uint8 28} 29 30func (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// RGBA64 represents a 64-bit alpha-premultiplied color, having 16 bits for 43// each of red, green, blue and alpha. 44// 45// An alpha-premultiplied color component C has been scaled by alpha (A), so 46// has valid values 0 <= C <= A. 47type RGBA64 struct { 48 R, G, B, A uint16 49} 50 51func (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// NRGBA represents a non-alpha-premultiplied 32-bit color. 56type NRGBA struct { 57 R, G, B, A uint8 58} 59 60func (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// NRGBA64 represents a non-alpha-premultiplied 64-bit color, 79// having 16 bits for each of red, green, blue and alpha. 80type NRGBA64 struct { 81 R, G, B, A uint16 82} 83 84func (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// Alpha represents an 8-bit alpha color. 99type Alpha struct { 100 A uint8 101} 102 103func (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// Alpha16 represents a 16-bit alpha color. 110type Alpha16 struct { 111 A uint16 112} 113 114func (c Alpha16) RGBA() (r, g, b, a uint32) { 115 a = uint32(c.A) 116 return a, a, a, a 117} 118 119// Gray represents an 8-bit grayscale color. 120type Gray struct { 121 Y uint8 122} 123 124func (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// Gray16 represents a 16-bit grayscale color. 131type Gray16 struct { 132 Y uint16 133} 134 135func (c Gray16) RGBA() (r, g, b, a uint32) { 136 y := uint32(c.Y) 137 return y, y, y, 0xffff 138} 139 140// Model can convert any [Color] to one from its own color model. The conversion 141// may be lossy. 142type Model interface { 143 Convert(c Color) Color 144} 145 146// ModelFunc returns a [Model] that invokes f to implement the conversion. 147func 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. 153 return &modelFunc{f} 154} 155 156type modelFunc struct { 157 f func(Color) Color 158} 159 160func (m *modelFunc) Convert(c Color) Color { 161 return m.f(c) 162} 163 164// Models for the standard color types. 165var ( 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 176func 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 184func 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 192func 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 // Since Color.RGBA returns an alpha-premultiplied color, we should have r <= a && g <= a && b <= a. 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 210func 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 // Since Color.RGBA returns an alpha-premultiplied color, we should have r <= a && g <= a && b <= a. 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 228func 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 236func 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 244func grayModel(c Color) Color { 245 if _, ok := c.(Gray); ok { 246 return c 247 } 248 r, g, b, _ := c.RGBA() 249 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 252 // ycbcr.go. 253 // 254 // Note that 19595 + 38470 + 7471 equals 65536. 255 // 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 259 260 return Gray{uint8(y)} 261} 262 263func gray16Model(c Color) Color { 264 if _, ok := c.(Gray16); ok { 265 return c 266 } 267 r, g, b, _ := c.RGBA() 268 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 271 // ycbcr.go. 272 // 273 // Note that 19595 + 38470 + 7471 equals 65536. 274 y := (19595*r + 38470*g + 7471*b + 1<<15) >> 16 275 276 return Gray16{uint16(y)} 277} 278 279// Palette is a palette of colors. 280type Palette []Color 281 282// Convert returns the palette color closest to c in Euclidean R,G,B space. 283func (p Palette) Convert(c Color) Color { 284 if len(p) == 0 { 285 return nil 286 } 287 return p[p.Index(c)] 288} 289 290// Index returns the index of the palette color closest to c in Euclidean 291// R,G,B,A space. 292func (p Palette) Index(c Color) int { 293 // A batch version of this computation is in image/draw/draw.go. 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// sqDiff returns the squared-difference of x and y, shifted by 2 so that 311// adding four of those won't overflow a uint32. 312// 313// x and y are both assumed to be in the range [0, 0xffff]. 314func sqDiff(x, y uint32) uint32 { 315 // The canonical code of this function looks as follows: 316 // 317 // var d uint32 318 // if x > y { 319 // d = x - y 320 // } else { 321 // d = y - x 322 // } 323 // return (d * d) >> 2 324 // 325 // Language spec guarantees the following properties of unsigned integer 326 // values operations with respect to overflow/wrap around: 327 // 328 // > For unsigned integer values, the operations +, -, *, and << are 329 // > computed modulo 2n, where n is the bit width of the unsigned 330 // > integer's type. Loosely speaking, these unsigned integer operations 331 // > discard high bits upon overflow, and programs may rely on ``wrap 332 // > around''. 333 // 334 // Considering these properties and the fact that this function is 335 // called in the hot paths (x,y loops), it is reduced to the below code 336 // which is slightly faster. See TestSqDiff for correctness check. 337 d := x - y 338 return (d * d) >> 2 339} 340 341// Standard colors. 342var ( 343 Black = Gray16{0} 344 White = Gray16{0xffff} 345 Transparent = Alpha16{0} 346 Opaque = Alpha16{0xffff} 347) 348