color.mx raw

   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  	//
  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.
  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  // 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.
  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  // NRGBA represents a non-alpha-premultiplied 32-bit color.
  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  // NRGBA64 represents a non-alpha-premultiplied 64-bit color,
  79  // having 16 bits for each of red, green, blue and alpha.
  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  // Alpha represents an 8-bit alpha color.
  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  // Alpha16 represents a 16-bit alpha color.
 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  // Gray represents an 8-bit grayscale color.
 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  // Gray16 represents a 16-bit grayscale color.
 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  // Model can convert any [Color] to one from its own color model. The conversion
 141  // may be lossy.
 142  type Model interface {
 143  	Convert(c Color) Color
 144  }
 145  
 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.
 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  // Models for the standard color types.
 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  	// 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  
 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  	// 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  
 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  	// 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  
 263  func 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.
 280  type Palette []Color
 281  
 282  // Convert returns the palette color closest to c in Euclidean R,G,B space.
 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  // Index returns the index of the palette color closest to c in Euclidean
 291  // R,G,B,A space.
 292  func (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].
 314  func 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.
 342  var (
 343  	Black       = Gray16{0}
 344  	White       = Gray16{0xffff}
 345  	Transparent = Alpha16{0}
 346  	Opaque      = Alpha16{0xffff}
 347  )
 348