The Go Programming Language

Source file src/pkg/image/color.go

     1	// Copyright 2009 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 image
     6	
     7	// Color can convert itself to alpha-premultiplied RGBA, with a possible loss
     8	// of precision. Each value ranges within [0, 0xFFFF], but is represented by a
     9	// uint32 so that multiplying by a blend factor up to 0xFFFF will not overflow.
    10	type Color interface {
    11		RGBA() (r, g, b, a uint32)
    12	}
    13	
    14	// RGBAColor represents a traditional 32-bit alpha-premultiplied color,
    15	// having 8 bits for each of red, green, blue and alpha.
    16	type RGBAColor struct {
    17		R, G, B, A uint8
    18	}
    19	
    20	func (c RGBAColor) RGBA() (r, g, b, a uint32) {
    21		r = uint32(c.R)
    22		r |= r << 8
    23		g = uint32(c.G)
    24		g |= g << 8
    25		b = uint32(c.B)
    26		b |= b << 8
    27		a = uint32(c.A)
    28		a |= a << 8
    29		return
    30	}
    31	
    32	// RGBA64Color represents a 64-bit alpha-premultiplied color,
    33	// having 16 bits for each of red, green, blue and alpha.
    34	type RGBA64Color struct {
    35		R, G, B, A uint16
    36	}
    37	
    38	func (c RGBA64Color) RGBA() (r, g, b, a uint32) {
    39		return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
    40	}
    41	
    42	// NRGBAColor represents a non-alpha-premultiplied 32-bit color.
    43	type NRGBAColor struct {
    44		R, G, B, A uint8
    45	}
    46	
    47	func (c NRGBAColor) RGBA() (r, g, b, a uint32) {
    48		r = uint32(c.R)
    49		r |= r << 8
    50		r *= uint32(c.A)
    51		r /= 0xff
    52		g = uint32(c.G)
    53		g |= g << 8
    54		g *= uint32(c.A)
    55		g /= 0xff
    56		b = uint32(c.B)
    57		b |= b << 8
    58		b *= uint32(c.A)
    59		b /= 0xff
    60		a = uint32(c.A)
    61		a |= a << 8
    62		return
    63	}
    64	
    65	// NRGBA64Color represents a non-alpha-premultiplied 64-bit color,
    66	// having 16 bits for each of red, green, blue and alpha.
    67	type NRGBA64Color struct {
    68		R, G, B, A uint16
    69	}
    70	
    71	func (c NRGBA64Color) RGBA() (r, g, b, a uint32) {
    72		r = uint32(c.R)
    73		r *= uint32(c.A)
    74		r /= 0xffff
    75		g = uint32(c.G)
    76		g *= uint32(c.A)
    77		g /= 0xffff
    78		b = uint32(c.B)
    79		b *= uint32(c.A)
    80		b /= 0xffff
    81		a = uint32(c.A)
    82		return
    83	}
    84	
    85	// AlphaColor represents an 8-bit alpha.
    86	type AlphaColor struct {
    87		A uint8
    88	}
    89	
    90	func (c AlphaColor) RGBA() (r, g, b, a uint32) {
    91		a = uint32(c.A)
    92		a |= a << 8
    93		return a, a, a, a
    94	}
    95	
    96	// Alpha16Color represents a 16-bit alpha.
    97	type Alpha16Color struct {
    98		A uint16
    99	}
   100	
   101	func (c Alpha16Color) RGBA() (r, g, b, a uint32) {
   102		a = uint32(c.A)
   103		return a, a, a, a
   104	}
   105	
   106	// GrayColor represents an 8-bit grayscale color.
   107	type GrayColor struct {
   108		Y uint8
   109	}
   110	
   111	func (c GrayColor) RGBA() (r, g, b, a uint32) {
   112		y := uint32(c.Y)
   113		y |= y << 8
   114		return y, y, y, 0xffff
   115	}
   116	
   117	// Gray16Color represents a 16-bit grayscale color.
   118	type Gray16Color struct {
   119		Y uint16
   120	}
   121	
   122	func (c Gray16Color) RGBA() (r, g, b, a uint32) {
   123		y := uint32(c.Y)
   124		return y, y, y, 0xffff
   125	}
   126	
   127	// ColorModel can convert foreign Colors, with a possible loss of precision,
   128	// to a Color from its own color model.
   129	type ColorModel interface {
   130		Convert(c Color) Color
   131	}
   132	
   133	// The ColorModelFunc type is an adapter to allow the use of an ordinary
   134	// color conversion function as a ColorModel.  If f is such a function,
   135	// ColorModelFunc(f) is a ColorModel object that invokes f to implement
   136	// the conversion.
   137	type ColorModelFunc func(Color) Color
   138	
   139	func (f ColorModelFunc) Convert(c Color) Color {
   140		return f(c)
   141	}
   142	
   143	func toRGBAColor(c Color) Color {
   144		if _, ok := c.(RGBAColor); ok {
   145			return c
   146		}
   147		r, g, b, a := c.RGBA()
   148		return RGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
   149	}
   150	
   151	func toRGBA64Color(c Color) Color {
   152		if _, ok := c.(RGBA64Color); ok {
   153			return c
   154		}
   155		r, g, b, a := c.RGBA()
   156		return RGBA64Color{uint16(r), uint16(g), uint16(b), uint16(a)}
   157	}
   158	
   159	func toNRGBAColor(c Color) Color {
   160		if _, ok := c.(NRGBAColor); ok {
   161			return c
   162		}
   163		r, g, b, a := c.RGBA()
   164		if a == 0xffff {
   165			return NRGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), 0xff}
   166		}
   167		if a == 0 {
   168			return NRGBAColor{0, 0, 0, 0}
   169		}
   170		// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
   171		r = (r * 0xffff) / a
   172		g = (g * 0xffff) / a
   173		b = (b * 0xffff) / a
   174		return NRGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
   175	}
   176	
   177	func toNRGBA64Color(c Color) Color {
   178		if _, ok := c.(NRGBA64Color); ok {
   179			return c
   180		}
   181		r, g, b, a := c.RGBA()
   182		if a == 0xffff {
   183			return NRGBA64Color{uint16(r), uint16(g), uint16(b), 0xffff}
   184		}
   185		if a == 0 {
   186			return NRGBA64Color{0, 0, 0, 0}
   187		}
   188		// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
   189		r = (r * 0xffff) / a
   190		g = (g * 0xffff) / a
   191		b = (b * 0xffff) / a
   192		return NRGBA64Color{uint16(r), uint16(g), uint16(b), uint16(a)}
   193	}
   194	
   195	func toAlphaColor(c Color) Color {
   196		if _, ok := c.(AlphaColor); ok {
   197			return c
   198		}
   199		_, _, _, a := c.RGBA()
   200		return AlphaColor{uint8(a >> 8)}
   201	}
   202	
   203	func toAlpha16Color(c Color) Color {
   204		if _, ok := c.(Alpha16Color); ok {
   205			return c
   206		}
   207		_, _, _, a := c.RGBA()
   208		return Alpha16Color{uint16(a)}
   209	}
   210	
   211	func toGrayColor(c Color) Color {
   212		if _, ok := c.(GrayColor); ok {
   213			return c
   214		}
   215		r, g, b, _ := c.RGBA()
   216		y := (299*r + 587*g + 114*b + 500) / 1000
   217		return GrayColor{uint8(y >> 8)}
   218	}
   219	
   220	func toGray16Color(c Color) Color {
   221		if _, ok := c.(Gray16Color); ok {
   222			return c
   223		}
   224		r, g, b, _ := c.RGBA()
   225		y := (299*r + 587*g + 114*b + 500) / 1000
   226		return Gray16Color{uint16(y)}
   227	}
   228	
   229	// The ColorModel associated with RGBAColor.
   230	var RGBAColorModel ColorModel = ColorModelFunc(toRGBAColor)
   231	
   232	// The ColorModel associated with RGBA64Color.
   233	var RGBA64ColorModel ColorModel = ColorModelFunc(toRGBA64Color)
   234	
   235	// The ColorModel associated with NRGBAColor.
   236	var NRGBAColorModel ColorModel = ColorModelFunc(toNRGBAColor)
   237	
   238	// The ColorModel associated with NRGBA64Color.
   239	var NRGBA64ColorModel ColorModel = ColorModelFunc(toNRGBA64Color)
   240	
   241	// The ColorModel associated with AlphaColor.
   242	var AlphaColorModel ColorModel = ColorModelFunc(toAlphaColor)
   243	
   244	// The ColorModel associated with Alpha16Color.
   245	var Alpha16ColorModel ColorModel = ColorModelFunc(toAlpha16Color)
   246	
   247	// The ColorModel associated with GrayColor.
   248	var GrayColorModel ColorModel = ColorModelFunc(toGrayColor)
   249	
   250	// The ColorModel associated with Gray16Color.
   251	var Gray16ColorModel ColorModel = ColorModelFunc(toGray16Color)

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.