src/pkg/image/color/color.go - The Go Programming Language

Golang

Source file src/pkg/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		RGBA() (r, g, b, a uint32)
    16	}
    17	
    18	// RGBA represents a traditional 32-bit alpha-premultiplied color,
    19	// having 8 bits for each of red, green, blue and alpha.
    20	type RGBA struct {
    21		R, G, B, A uint8
    22	}
    23	
    24	func (c RGBA) RGBA() (r, g, b, a uint32) {
    25		r = uint32(c.R)
    26		r |= r << 8
    27		g = uint32(c.G)
    28		g |= g << 8
    29		b = uint32(c.B)
    30		b |= b << 8
    31		a = uint32(c.A)
    32		a |= a << 8
    33		return
    34	}
    35	
    36	// RGBA64 represents a 64-bit alpha-premultiplied color,
    37	// having 16 bits for each of red, green, blue and alpha.
    38	type RGBA64 struct {
    39		R, G, B, A uint16
    40	}
    41	
    42	func (c RGBA64) RGBA() (r, g, b, a uint32) {
    43		return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
    44	}
    45	
    46	// NRGBA represents a non-alpha-premultiplied 32-bit color.
    47	type NRGBA struct {
    48		R, G, B, A uint8
    49	}
    50	
    51	func (c NRGBA) RGBA() (r, g, b, a uint32) {
    52		r = uint32(c.R)
    53		r |= r << 8
    54		r *= uint32(c.A)
    55		r /= 0xff
    56		g = uint32(c.G)
    57		g |= g << 8
    58		g *= uint32(c.A)
    59		g /= 0xff
    60		b = uint32(c.B)
    61		b |= b << 8
    62		b *= uint32(c.A)
    63		b /= 0xff
    64		a = uint32(c.A)
    65		a |= a << 8
    66		return
    67	}
    68	
    69	// NRGBA64 represents a non-alpha-premultiplied 64-bit color,
    70	// having 16 bits for each of red, green, blue and alpha.
    71	type NRGBA64 struct {
    72		R, G, B, A uint16
    73	}
    74	
    75	func (c NRGBA64) RGBA() (r, g, b, a uint32) {
    76		r = uint32(c.R)
    77		r *= uint32(c.A)
    78		r /= 0xffff
    79		g = uint32(c.G)
    80		g *= uint32(c.A)
    81		g /= 0xffff
    82		b = uint32(c.B)
    83		b *= uint32(c.A)
    84		b /= 0xffff
    85		a = uint32(c.A)
    86		return
    87	}
    88	
    89	// Alpha represents an 8-bit alpha color.
    90	type Alpha struct {
    91		A uint8
    92	}
    93	
    94	func (c Alpha) RGBA() (r, g, b, a uint32) {
    95		a = uint32(c.A)
    96		a |= a << 8
    97		return a, a, a, a
    98	}
    99	
   100	// Alpha16 represents a 16-bit alpha color.
   101	type Alpha16 struct {
   102		A uint16
   103	}
   104	
   105	func (c Alpha16) RGBA() (r, g, b, a uint32) {
   106		a = uint32(c.A)
   107		return a, a, a, a
   108	}
   109	
   110	// Gray represents an 8-bit grayscale color.
   111	type Gray struct {
   112		Y uint8
   113	}
   114	
   115	func (c Gray) RGBA() (r, g, b, a uint32) {
   116		y := uint32(c.Y)
   117		y |= y << 8
   118		return y, y, y, 0xffff
   119	}
   120	
   121	// Gray16 represents a 16-bit grayscale color.
   122	type Gray16 struct {
   123		Y uint16
   124	}
   125	
   126	func (c Gray16) RGBA() (r, g, b, a uint32) {
   127		y := uint32(c.Y)
   128		return y, y, y, 0xffff
   129	}
   130	
   131	// Model can convert any Color to one from its own color model. The conversion
   132	// may be lossy.
   133	type Model interface {
   134		Convert(c Color) Color
   135	}
   136	
   137	// ModelFunc returns a Model that invokes f to implement the conversion.
   138	func ModelFunc(f func(Color) Color) Model {
   139		// Note: using *modelFunc as the implementation
   140		// means that callers can still use comparisons
   141		// like m == RGBAModel.  This is not possible if
   142		// we use the func value directly, because funcs
   143		// are no longer comparable.
   144		return &modelFunc{f}
   145	}
   146	
   147	type modelFunc struct {
   148		f func(Color) Color
   149	}
   150	
   151	func (m *modelFunc) Convert(c Color) Color {
   152		return m.f(c)
   153	}
   154	
   155	// Models for the standard color types.
   156	var (
   157		RGBAModel    Model = ModelFunc(rgbaModel)
   158		RGBA64Model  Model = ModelFunc(rgba64Model)
   159		NRGBAModel   Model = ModelFunc(nrgbaModel)
   160		NRGBA64Model Model = ModelFunc(nrgba64Model)
   161		AlphaModel   Model = ModelFunc(alphaModel)
   162		Alpha16Model Model = ModelFunc(alpha16Model)
   163		GrayModel    Model = ModelFunc(grayModel)
   164		Gray16Model  Model = ModelFunc(gray16Model)
   165	)
   166	
   167	func rgbaModel(c Color) Color {
   168		if _, ok := c.(RGBA); ok {
   169			return c
   170		}
   171		r, g, b, a := c.RGBA()
   172		return RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
   173	}
   174	
   175	func rgba64Model(c Color) Color {
   176		if _, ok := c.(RGBA64); ok {
   177			return c
   178		}
   179		r, g, b, a := c.RGBA()
   180		return RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
   181	}
   182	
   183	func nrgbaModel(c Color) Color {
   184		if _, ok := c.(NRGBA); ok {
   185			return c
   186		}
   187		r, g, b, a := c.RGBA()
   188		if a == 0xffff {
   189			return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), 0xff}
   190		}
   191		if a == 0 {
   192			return NRGBA{0, 0, 0, 0}
   193		}
   194		// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
   195		r = (r * 0xffff) / a
   196		g = (g * 0xffff) / a
   197		b = (b * 0xffff) / a
   198		return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
   199	}
   200	
   201	func nrgba64Model(c Color) Color {
   202		if _, ok := c.(NRGBA64); ok {
   203			return c
   204		}
   205		r, g, b, a := c.RGBA()
   206		if a == 0xffff {
   207			return NRGBA64{uint16(r), uint16(g), uint16(b), 0xffff}
   208		}
   209		if a == 0 {
   210			return NRGBA64{0, 0, 0, 0}
   211		}
   212		// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
   213		r = (r * 0xffff) / a
   214		g = (g * 0xffff) / a
   215		b = (b * 0xffff) / a
   216		return NRGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
   217	}
   218	
   219	func alphaModel(c Color) Color {
   220		if _, ok := c.(Alpha); ok {
   221			return c
   222		}
   223		_, _, _, a := c.RGBA()
   224		return Alpha{uint8(a >> 8)}
   225	}
   226	
   227	func alpha16Model(c Color) Color {
   228		if _, ok := c.(Alpha16); ok {
   229			return c
   230		}
   231		_, _, _, a := c.RGBA()
   232		return Alpha16{uint16(a)}
   233	}
   234	
   235	func grayModel(c Color) Color {
   236		if _, ok := c.(Gray); ok {
   237			return c
   238		}
   239		r, g, b, _ := c.RGBA()
   240		y := (299*r + 587*g + 114*b + 500) / 1000
   241		return Gray{uint8(y >> 8)}
   242	}
   243	
   244	func gray16Model(c Color) Color {
   245		if _, ok := c.(Gray16); ok {
   246			return c
   247		}
   248		r, g, b, _ := c.RGBA()
   249		y := (299*r + 587*g + 114*b + 500) / 1000
   250		return Gray16{uint16(y)}
   251	}
   252	
   253	// Palette is a palette of colors.
   254	type Palette []Color
   255	
   256	func diff(a, b uint32) uint32 {
   257		if a > b {
   258			return a - b
   259		}
   260		return b - a
   261	}
   262	
   263	// Convert returns the palette color closest to c in Euclidean R,G,B space.
   264	func (p Palette) Convert(c Color) Color {
   265		if len(p) == 0 {
   266			return nil
   267		}
   268		return p[p.Index(c)]
   269	}
   270	
   271	// Index returns the index of the palette color closest to c in Euclidean
   272	// R,G,B space.
   273	func (p Palette) Index(c Color) int {
   274		cr, cg, cb, _ := c.RGBA()
   275		// Shift by 1 bit to avoid potential uint32 overflow in sum-squared-difference.
   276		cr >>= 1
   277		cg >>= 1
   278		cb >>= 1
   279		ret, bestSSD := 0, uint32(1<<32-1)
   280		for i, v := range p {
   281			vr, vg, vb, _ := v.RGBA()
   282			vr >>= 1
   283			vg >>= 1
   284			vb >>= 1
   285			dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb)
   286			ssd := (dr * dr) + (dg * dg) + (db * db)
   287			if ssd < bestSSD {
   288				if ssd == 0 {
   289					return i
   290				}
   291				ret, bestSSD = i, ssd
   292			}
   293		}
   294		return ret
   295	}
   296	
   297	// Standard colors.
   298	var (
   299		Black       = Gray16{0}
   300		White       = Gray16{0xffff}
   301		Transparent = Alpha16{0}
   302		Opaque      = Alpha16{0xffff}
   303	)