github.com/zebozhuang/go@v0.0.0-20200207033046-f8a98f6f5c5d/src/image/color/color.go (about)

     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 a 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 a 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  	var d uint32
   316  	if x > y {
   317  		d = x - y
   318  	} else {
   319  		d = y - x
   320  	}
   321  	return (d * d) >> 2
   322  }
   323  
   324  // Standard colors.
   325  var (
   326  	Black       = Gray16{0}
   327  	White       = Gray16{0xffff}
   328  	Transparent = Alpha16{0}
   329  	Opaque      = Alpha16{0xffff}
   330  )