...
Run Format

Source file src/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		//
    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		y := (299*r + 587*g + 114*b + 500) / 1000
   250		return Gray{uint8(y >> 8)}
   251	}
   252	
   253	func gray16Model(c Color) Color {
   254		if _, ok := c.(Gray16); ok {
   255			return c
   256		}
   257		r, g, b, _ := c.RGBA()
   258		y := (299*r + 587*g + 114*b + 500) / 1000
   259		return Gray16{uint16(y)}
   260	}
   261	
   262	// Palette is a palette of colors.
   263	type Palette []Color
   264	
   265	// Convert returns the palette color closest to c in Euclidean R,G,B space.
   266	func (p Palette) Convert(c Color) Color {
   267		if len(p) == 0 {
   268			return nil
   269		}
   270		return p[p.Index(c)]
   271	}
   272	
   273	// Index returns the index of the palette color closest to c in Euclidean
   274	// R,G,B,A space.
   275	func (p Palette) Index(c Color) int {
   276		// A batch version of this computation is in image/draw/draw.go.
   277	
   278		cr, cg, cb, ca := c.RGBA()
   279		ret, bestSum := 0, uint32(1<<32-1)
   280		for i, v := range p {
   281			vr, vg, vb, va := v.RGBA()
   282			sum := sqDiff(cr, vr) + sqDiff(cg, vg) + sqDiff(cb, vb) + sqDiff(ca, va)
   283			if sum < bestSum {
   284				if sum == 0 {
   285					return i
   286				}
   287				ret, bestSum = i, sum
   288			}
   289		}
   290		return ret
   291	}
   292	
   293	// sqDiff returns the squared-difference of x and y, shifted by 2 so that
   294	// adding four of those won't overflow a uint32.
   295	//
   296	// x and y are both assumed to be in the range [0, 0xffff].
   297	func sqDiff(x, y uint32) uint32 {
   298		var d uint32
   299		if x > y {
   300			d = x - y
   301		} else {
   302			d = y - x
   303		}
   304		return (d * d) >> 2
   305	}
   306	
   307	// Standard colors.
   308	var (
   309		Black       = Gray16{0}
   310		White       = Gray16{0xffff}
   311		Transparent = Alpha16{0}
   312		Opaque      = Alpha16{0xffff}
   313	)
   314	

View as plain text