...

Source file src/pkg/image/image.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 implements a basic 2-D image library.
     6	//
     7	// The fundamental interface is called Image. An Image contains colors, which
     8	// are described in the image/color package.
     9	//
    10	// Values of the Image interface are created either by calling functions such
    11	// as NewRGBA and NewPaletted, or by calling Decode on an io.Reader containing
    12	// image data in a format such as GIF, JPEG or PNG. Decoding any particular
    13	// image format requires the prior registration of a decoder function.
    14	// Registration is typically automatic as a side effect of initializing that
    15	// format's package so that, to decode a PNG image, it suffices to have
    16	//	import _ "image/png"
    17	// in a program's main package. The _ means to import a package purely for its
    18	// initialization side effects.
    19	//
    20	// See "The Go image package" for more details:
    21	// https://golang.org/doc/articles/image_package.html
    22	package image
    23	
    24	import (
    25		"image/color"
    26	)
    27	
    28	// Config holds an image's color model and dimensions.
    29	type Config struct {
    30		ColorModel    color.Model
    31		Width, Height int
    32	}
    33	
    34	// Image is a finite rectangular grid of color.Color values taken from a color
    35	// model.
    36	type Image interface {
    37		// ColorModel returns the Image's color model.
    38		ColorModel() color.Model
    39		// Bounds returns the domain for which At can return non-zero color.
    40		// The bounds do not necessarily contain the point (0, 0).
    41		Bounds() Rectangle
    42		// At returns the color of the pixel at (x, y).
    43		// At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
    44		// At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
    45		At(x, y int) color.Color
    46	}
    47	
    48	// PalettedImage is an image whose colors may come from a limited palette.
    49	// If m is a PalettedImage and m.ColorModel() returns a color.Palette p,
    50	// then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's
    51	// color model is not a color.Palette, then ColorIndexAt's behavior is
    52	// undefined.
    53	type PalettedImage interface {
    54		// ColorIndexAt returns the palette index of the pixel at (x, y).
    55		ColorIndexAt(x, y int) uint8
    56		Image
    57	}
    58	
    59	// RGBA is an in-memory image whose At method returns color.RGBA values.
    60	type RGBA struct {
    61		// Pix holds the image's pixels, in R, G, B, A order. The pixel at
    62		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
    63		Pix []uint8
    64		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
    65		Stride int
    66		// Rect is the image's bounds.
    67		Rect Rectangle
    68	}
    69	
    70	func (p *RGBA) ColorModel() color.Model { return color.RGBAModel }
    71	
    72	func (p *RGBA) Bounds() Rectangle { return p.Rect }
    73	
    74	func (p *RGBA) At(x, y int) color.Color {
    75		return p.RGBAAt(x, y)
    76	}
    77	
    78	func (p *RGBA) RGBAAt(x, y int) color.RGBA {
    79		if !(Point{x, y}.In(p.Rect)) {
    80			return color.RGBA{}
    81		}
    82		i := p.PixOffset(x, y)
    83		s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
    84		return color.RGBA{s[0], s[1], s[2], s[3]}
    85	}
    86	
    87	// PixOffset returns the index of the first element of Pix that corresponds to
    88	// the pixel at (x, y).
    89	func (p *RGBA) PixOffset(x, y int) int {
    90		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
    91	}
    92	
    93	func (p *RGBA) Set(x, y int, c color.Color) {
    94		if !(Point{x, y}.In(p.Rect)) {
    95			return
    96		}
    97		i := p.PixOffset(x, y)
    98		c1 := color.RGBAModel.Convert(c).(color.RGBA)
    99		s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   100		s[0] = c1.R
   101		s[1] = c1.G
   102		s[2] = c1.B
   103		s[3] = c1.A
   104	}
   105	
   106	func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
   107		if !(Point{x, y}.In(p.Rect)) {
   108			return
   109		}
   110		i := p.PixOffset(x, y)
   111		s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   112		s[0] = c.R
   113		s[1] = c.G
   114		s[2] = c.B
   115		s[3] = c.A
   116	}
   117	
   118	// SubImage returns an image representing the portion of the image p visible
   119	// through r. The returned value shares pixels with the original image.
   120	func (p *RGBA) SubImage(r Rectangle) Image {
   121		r = r.Intersect(p.Rect)
   122		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   123		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   124		// this, the Pix[i:] expression below can panic.
   125		if r.Empty() {
   126			return &RGBA{}
   127		}
   128		i := p.PixOffset(r.Min.X, r.Min.Y)
   129		return &RGBA{
   130			Pix:    p.Pix[i:],
   131			Stride: p.Stride,
   132			Rect:   r,
   133		}
   134	}
   135	
   136	// Opaque scans the entire image and reports whether it is fully opaque.
   137	func (p *RGBA) Opaque() bool {
   138		if p.Rect.Empty() {
   139			return true
   140		}
   141		i0, i1 := 3, p.Rect.Dx()*4
   142		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   143			for i := i0; i < i1; i += 4 {
   144				if p.Pix[i] != 0xff {
   145					return false
   146				}
   147			}
   148			i0 += p.Stride
   149			i1 += p.Stride
   150		}
   151		return true
   152	}
   153	
   154	// NewRGBA returns a new RGBA image with the given bounds.
   155	func NewRGBA(r Rectangle) *RGBA {
   156		w, h := r.Dx(), r.Dy()
   157		buf := make([]uint8, 4*w*h)
   158		return &RGBA{buf, 4 * w, r}
   159	}
   160	
   161	// RGBA64 is an in-memory image whose At method returns color.RGBA64 values.
   162	type RGBA64 struct {
   163		// Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
   164		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
   165		Pix []uint8
   166		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   167		Stride int
   168		// Rect is the image's bounds.
   169		Rect Rectangle
   170	}
   171	
   172	func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model }
   173	
   174	func (p *RGBA64) Bounds() Rectangle { return p.Rect }
   175	
   176	func (p *RGBA64) At(x, y int) color.Color {
   177		return p.RGBA64At(x, y)
   178	}
   179	
   180	func (p *RGBA64) RGBA64At(x, y int) color.RGBA64 {
   181		if !(Point{x, y}.In(p.Rect)) {
   182			return color.RGBA64{}
   183		}
   184		i := p.PixOffset(x, y)
   185		s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   186		return color.RGBA64{
   187			uint16(s[0])<<8 | uint16(s[1]),
   188			uint16(s[2])<<8 | uint16(s[3]),
   189			uint16(s[4])<<8 | uint16(s[5]),
   190			uint16(s[6])<<8 | uint16(s[7]),
   191		}
   192	}
   193	
   194	// PixOffset returns the index of the first element of Pix that corresponds to
   195	// the pixel at (x, y).
   196	func (p *RGBA64) PixOffset(x, y int) int {
   197		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
   198	}
   199	
   200	func (p *RGBA64) Set(x, y int, c color.Color) {
   201		if !(Point{x, y}.In(p.Rect)) {
   202			return
   203		}
   204		i := p.PixOffset(x, y)
   205		c1 := color.RGBA64Model.Convert(c).(color.RGBA64)
   206		s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   207		s[0] = uint8(c1.R >> 8)
   208		s[1] = uint8(c1.R)
   209		s[2] = uint8(c1.G >> 8)
   210		s[3] = uint8(c1.G)
   211		s[4] = uint8(c1.B >> 8)
   212		s[5] = uint8(c1.B)
   213		s[6] = uint8(c1.A >> 8)
   214		s[7] = uint8(c1.A)
   215	}
   216	
   217	func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
   218		if !(Point{x, y}.In(p.Rect)) {
   219			return
   220		}
   221		i := p.PixOffset(x, y)
   222		s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   223		s[0] = uint8(c.R >> 8)
   224		s[1] = uint8(c.R)
   225		s[2] = uint8(c.G >> 8)
   226		s[3] = uint8(c.G)
   227		s[4] = uint8(c.B >> 8)
   228		s[5] = uint8(c.B)
   229		s[6] = uint8(c.A >> 8)
   230		s[7] = uint8(c.A)
   231	}
   232	
   233	// SubImage returns an image representing the portion of the image p visible
   234	// through r. The returned value shares pixels with the original image.
   235	func (p *RGBA64) SubImage(r Rectangle) Image {
   236		r = r.Intersect(p.Rect)
   237		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   238		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   239		// this, the Pix[i:] expression below can panic.
   240		if r.Empty() {
   241			return &RGBA64{}
   242		}
   243		i := p.PixOffset(r.Min.X, r.Min.Y)
   244		return &RGBA64{
   245			Pix:    p.Pix[i:],
   246			Stride: p.Stride,
   247			Rect:   r,
   248		}
   249	}
   250	
   251	// Opaque scans the entire image and reports whether it is fully opaque.
   252	func (p *RGBA64) Opaque() bool {
   253		if p.Rect.Empty() {
   254			return true
   255		}
   256		i0, i1 := 6, p.Rect.Dx()*8
   257		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   258			for i := i0; i < i1; i += 8 {
   259				if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
   260					return false
   261				}
   262			}
   263			i0 += p.Stride
   264			i1 += p.Stride
   265		}
   266		return true
   267	}
   268	
   269	// NewRGBA64 returns a new RGBA64 image with the given bounds.
   270	func NewRGBA64(r Rectangle) *RGBA64 {
   271		w, h := r.Dx(), r.Dy()
   272		pix := make([]uint8, 8*w*h)
   273		return &RGBA64{pix, 8 * w, r}
   274	}
   275	
   276	// NRGBA is an in-memory image whose At method returns color.NRGBA values.
   277	type NRGBA struct {
   278		// Pix holds the image's pixels, in R, G, B, A order. The pixel at
   279		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
   280		Pix []uint8
   281		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   282		Stride int
   283		// Rect is the image's bounds.
   284		Rect Rectangle
   285	}
   286	
   287	func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel }
   288	
   289	func (p *NRGBA) Bounds() Rectangle { return p.Rect }
   290	
   291	func (p *NRGBA) At(x, y int) color.Color {
   292		return p.NRGBAAt(x, y)
   293	}
   294	
   295	func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA {
   296		if !(Point{x, y}.In(p.Rect)) {
   297			return color.NRGBA{}
   298		}
   299		i := p.PixOffset(x, y)
   300		s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   301		return color.NRGBA{s[0], s[1], s[2], s[3]}
   302	}
   303	
   304	// PixOffset returns the index of the first element of Pix that corresponds to
   305	// the pixel at (x, y).
   306	func (p *NRGBA) PixOffset(x, y int) int {
   307		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
   308	}
   309	
   310	func (p *NRGBA) Set(x, y int, c color.Color) {
   311		if !(Point{x, y}.In(p.Rect)) {
   312			return
   313		}
   314		i := p.PixOffset(x, y)
   315		c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
   316		s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   317		s[0] = c1.R
   318		s[1] = c1.G
   319		s[2] = c1.B
   320		s[3] = c1.A
   321	}
   322	
   323	func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
   324		if !(Point{x, y}.In(p.Rect)) {
   325			return
   326		}
   327		i := p.PixOffset(x, y)
   328		s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   329		s[0] = c.R
   330		s[1] = c.G
   331		s[2] = c.B
   332		s[3] = c.A
   333	}
   334	
   335	// SubImage returns an image representing the portion of the image p visible
   336	// through r. The returned value shares pixels with the original image.
   337	func (p *NRGBA) SubImage(r Rectangle) Image {
   338		r = r.Intersect(p.Rect)
   339		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   340		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   341		// this, the Pix[i:] expression below can panic.
   342		if r.Empty() {
   343			return &NRGBA{}
   344		}
   345		i := p.PixOffset(r.Min.X, r.Min.Y)
   346		return &NRGBA{
   347			Pix:    p.Pix[i:],
   348			Stride: p.Stride,
   349			Rect:   r,
   350		}
   351	}
   352	
   353	// Opaque scans the entire image and reports whether it is fully opaque.
   354	func (p *NRGBA) Opaque() bool {
   355		if p.Rect.Empty() {
   356			return true
   357		}
   358		i0, i1 := 3, p.Rect.Dx()*4
   359		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   360			for i := i0; i < i1; i += 4 {
   361				if p.Pix[i] != 0xff {
   362					return false
   363				}
   364			}
   365			i0 += p.Stride
   366			i1 += p.Stride
   367		}
   368		return true
   369	}
   370	
   371	// NewNRGBA returns a new NRGBA image with the given bounds.
   372	func NewNRGBA(r Rectangle) *NRGBA {
   373		w, h := r.Dx(), r.Dy()
   374		pix := make([]uint8, 4*w*h)
   375		return &NRGBA{pix, 4 * w, r}
   376	}
   377	
   378	// NRGBA64 is an in-memory image whose At method returns color.NRGBA64 values.
   379	type NRGBA64 struct {
   380		// Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
   381		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
   382		Pix []uint8
   383		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   384		Stride int
   385		// Rect is the image's bounds.
   386		Rect Rectangle
   387	}
   388	
   389	func (p *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model }
   390	
   391	func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
   392	
   393	func (p *NRGBA64) At(x, y int) color.Color {
   394		return p.NRGBA64At(x, y)
   395	}
   396	
   397	func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 {
   398		if !(Point{x, y}.In(p.Rect)) {
   399			return color.NRGBA64{}
   400		}
   401		i := p.PixOffset(x, y)
   402		s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   403		return color.NRGBA64{
   404			uint16(s[0])<<8 | uint16(s[1]),
   405			uint16(s[2])<<8 | uint16(s[3]),
   406			uint16(s[4])<<8 | uint16(s[5]),
   407			uint16(s[6])<<8 | uint16(s[7]),
   408		}
   409	}
   410	
   411	// PixOffset returns the index of the first element of Pix that corresponds to
   412	// the pixel at (x, y).
   413	func (p *NRGBA64) PixOffset(x, y int) int {
   414		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
   415	}
   416	
   417	func (p *NRGBA64) Set(x, y int, c color.Color) {
   418		if !(Point{x, y}.In(p.Rect)) {
   419			return
   420		}
   421		i := p.PixOffset(x, y)
   422		c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
   423		s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   424		s[0] = uint8(c1.R >> 8)
   425		s[1] = uint8(c1.R)
   426		s[2] = uint8(c1.G >> 8)
   427		s[3] = uint8(c1.G)
   428		s[4] = uint8(c1.B >> 8)
   429		s[5] = uint8(c1.B)
   430		s[6] = uint8(c1.A >> 8)
   431		s[7] = uint8(c1.A)
   432	}
   433	
   434	func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
   435		if !(Point{x, y}.In(p.Rect)) {
   436			return
   437		}
   438		i := p.PixOffset(x, y)
   439		s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   440		s[0] = uint8(c.R >> 8)
   441		s[1] = uint8(c.R)
   442		s[2] = uint8(c.G >> 8)
   443		s[3] = uint8(c.G)
   444		s[4] = uint8(c.B >> 8)
   445		s[5] = uint8(c.B)
   446		s[6] = uint8(c.A >> 8)
   447		s[7] = uint8(c.A)
   448	}
   449	
   450	// SubImage returns an image representing the portion of the image p visible
   451	// through r. The returned value shares pixels with the original image.
   452	func (p *NRGBA64) SubImage(r Rectangle) Image {
   453		r = r.Intersect(p.Rect)
   454		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   455		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   456		// this, the Pix[i:] expression below can panic.
   457		if r.Empty() {
   458			return &NRGBA64{}
   459		}
   460		i := p.PixOffset(r.Min.X, r.Min.Y)
   461		return &NRGBA64{
   462			Pix:    p.Pix[i:],
   463			Stride: p.Stride,
   464			Rect:   r,
   465		}
   466	}
   467	
   468	// Opaque scans the entire image and reports whether it is fully opaque.
   469	func (p *NRGBA64) Opaque() bool {
   470		if p.Rect.Empty() {
   471			return true
   472		}
   473		i0, i1 := 6, p.Rect.Dx()*8
   474		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   475			for i := i0; i < i1; i += 8 {
   476				if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
   477					return false
   478				}
   479			}
   480			i0 += p.Stride
   481			i1 += p.Stride
   482		}
   483		return true
   484	}
   485	
   486	// NewNRGBA64 returns a new NRGBA64 image with the given bounds.
   487	func NewNRGBA64(r Rectangle) *NRGBA64 {
   488		w, h := r.Dx(), r.Dy()
   489		pix := make([]uint8, 8*w*h)
   490		return &NRGBA64{pix, 8 * w, r}
   491	}
   492	
   493	// Alpha is an in-memory image whose At method returns color.Alpha values.
   494	type Alpha struct {
   495		// Pix holds the image's pixels, as alpha values. The pixel at
   496		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
   497		Pix []uint8
   498		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   499		Stride int
   500		// Rect is the image's bounds.
   501		Rect Rectangle
   502	}
   503	
   504	func (p *Alpha) ColorModel() color.Model { return color.AlphaModel }
   505	
   506	func (p *Alpha) Bounds() Rectangle { return p.Rect }
   507	
   508	func (p *Alpha) At(x, y int) color.Color {
   509		return p.AlphaAt(x, y)
   510	}
   511	
   512	func (p *Alpha) AlphaAt(x, y int) color.Alpha {
   513		if !(Point{x, y}.In(p.Rect)) {
   514			return color.Alpha{}
   515		}
   516		i := p.PixOffset(x, y)
   517		return color.Alpha{p.Pix[i]}
   518	}
   519	
   520	// PixOffset returns the index of the first element of Pix that corresponds to
   521	// the pixel at (x, y).
   522	func (p *Alpha) PixOffset(x, y int) int {
   523		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
   524	}
   525	
   526	func (p *Alpha) Set(x, y int, c color.Color) {
   527		if !(Point{x, y}.In(p.Rect)) {
   528			return
   529		}
   530		i := p.PixOffset(x, y)
   531		p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
   532	}
   533	
   534	func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
   535		if !(Point{x, y}.In(p.Rect)) {
   536			return
   537		}
   538		i := p.PixOffset(x, y)
   539		p.Pix[i] = c.A
   540	}
   541	
   542	// SubImage returns an image representing the portion of the image p visible
   543	// through r. The returned value shares pixels with the original image.
   544	func (p *Alpha) SubImage(r Rectangle) Image {
   545		r = r.Intersect(p.Rect)
   546		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   547		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   548		// this, the Pix[i:] expression below can panic.
   549		if r.Empty() {
   550			return &Alpha{}
   551		}
   552		i := p.PixOffset(r.Min.X, r.Min.Y)
   553		return &Alpha{
   554			Pix:    p.Pix[i:],
   555			Stride: p.Stride,
   556			Rect:   r,
   557		}
   558	}
   559	
   560	// Opaque scans the entire image and reports whether it is fully opaque.
   561	func (p *Alpha) Opaque() bool {
   562		if p.Rect.Empty() {
   563			return true
   564		}
   565		i0, i1 := 0, p.Rect.Dx()
   566		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   567			for i := i0; i < i1; i++ {
   568				if p.Pix[i] != 0xff {
   569					return false
   570				}
   571			}
   572			i0 += p.Stride
   573			i1 += p.Stride
   574		}
   575		return true
   576	}
   577	
   578	// NewAlpha returns a new Alpha image with the given bounds.
   579	func NewAlpha(r Rectangle) *Alpha {
   580		w, h := r.Dx(), r.Dy()
   581		pix := make([]uint8, 1*w*h)
   582		return &Alpha{pix, 1 * w, r}
   583	}
   584	
   585	// Alpha16 is an in-memory image whose At method returns color.Alpha16 values.
   586	type Alpha16 struct {
   587		// Pix holds the image's pixels, as alpha values in big-endian format. The pixel at
   588		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
   589		Pix []uint8
   590		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   591		Stride int
   592		// Rect is the image's bounds.
   593		Rect Rectangle
   594	}
   595	
   596	func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model }
   597	
   598	func (p *Alpha16) Bounds() Rectangle { return p.Rect }
   599	
   600	func (p *Alpha16) At(x, y int) color.Color {
   601		return p.Alpha16At(x, y)
   602	}
   603	
   604	func (p *Alpha16) Alpha16At(x, y int) color.Alpha16 {
   605		if !(Point{x, y}.In(p.Rect)) {
   606			return color.Alpha16{}
   607		}
   608		i := p.PixOffset(x, y)
   609		return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
   610	}
   611	
   612	// PixOffset returns the index of the first element of Pix that corresponds to
   613	// the pixel at (x, y).
   614	func (p *Alpha16) PixOffset(x, y int) int {
   615		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
   616	}
   617	
   618	func (p *Alpha16) Set(x, y int, c color.Color) {
   619		if !(Point{x, y}.In(p.Rect)) {
   620			return
   621		}
   622		i := p.PixOffset(x, y)
   623		c1 := color.Alpha16Model.Convert(c).(color.Alpha16)
   624		p.Pix[i+0] = uint8(c1.A >> 8)
   625		p.Pix[i+1] = uint8(c1.A)
   626	}
   627	
   628	func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
   629		if !(Point{x, y}.In(p.Rect)) {
   630			return
   631		}
   632		i := p.PixOffset(x, y)
   633		p.Pix[i+0] = uint8(c.A >> 8)
   634		p.Pix[i+1] = uint8(c.A)
   635	}
   636	
   637	// SubImage returns an image representing the portion of the image p visible
   638	// through r. The returned value shares pixels with the original image.
   639	func (p *Alpha16) SubImage(r Rectangle) Image {
   640		r = r.Intersect(p.Rect)
   641		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   642		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   643		// this, the Pix[i:] expression below can panic.
   644		if r.Empty() {
   645			return &Alpha16{}
   646		}
   647		i := p.PixOffset(r.Min.X, r.Min.Y)
   648		return &Alpha16{
   649			Pix:    p.Pix[i:],
   650			Stride: p.Stride,
   651			Rect:   r,
   652		}
   653	}
   654	
   655	// Opaque scans the entire image and reports whether it is fully opaque.
   656	func (p *Alpha16) Opaque() bool {
   657		if p.Rect.Empty() {
   658			return true
   659		}
   660		i0, i1 := 0, p.Rect.Dx()*2
   661		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   662			for i := i0; i < i1; i += 2 {
   663				if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
   664					return false
   665				}
   666			}
   667			i0 += p.Stride
   668			i1 += p.Stride
   669		}
   670		return true
   671	}
   672	
   673	// NewAlpha16 returns a new Alpha16 image with the given bounds.
   674	func NewAlpha16(r Rectangle) *Alpha16 {
   675		w, h := r.Dx(), r.Dy()
   676		pix := make([]uint8, 2*w*h)
   677		return &Alpha16{pix, 2 * w, r}
   678	}
   679	
   680	// Gray is an in-memory image whose At method returns color.Gray values.
   681	type Gray struct {
   682		// Pix holds the image's pixels, as gray values. The pixel at
   683		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
   684		Pix []uint8
   685		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   686		Stride int
   687		// Rect is the image's bounds.
   688		Rect Rectangle
   689	}
   690	
   691	func (p *Gray) ColorModel() color.Model { return color.GrayModel }
   692	
   693	func (p *Gray) Bounds() Rectangle { return p.Rect }
   694	
   695	func (p *Gray) At(x, y int) color.Color {
   696		return p.GrayAt(x, y)
   697	}
   698	
   699	func (p *Gray) GrayAt(x, y int) color.Gray {
   700		if !(Point{x, y}.In(p.Rect)) {
   701			return color.Gray{}
   702		}
   703		i := p.PixOffset(x, y)
   704		return color.Gray{p.Pix[i]}
   705	}
   706	
   707	// PixOffset returns the index of the first element of Pix that corresponds to
   708	// the pixel at (x, y).
   709	func (p *Gray) PixOffset(x, y int) int {
   710		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
   711	}
   712	
   713	func (p *Gray) Set(x, y int, c color.Color) {
   714		if !(Point{x, y}.In(p.Rect)) {
   715			return
   716		}
   717		i := p.PixOffset(x, y)
   718		p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
   719	}
   720	
   721	func (p *Gray) SetGray(x, y int, c color.Gray) {
   722		if !(Point{x, y}.In(p.Rect)) {
   723			return
   724		}
   725		i := p.PixOffset(x, y)
   726		p.Pix[i] = c.Y
   727	}
   728	
   729	// SubImage returns an image representing the portion of the image p visible
   730	// through r. The returned value shares pixels with the original image.
   731	func (p *Gray) SubImage(r Rectangle) Image {
   732		r = r.Intersect(p.Rect)
   733		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   734		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   735		// this, the Pix[i:] expression below can panic.
   736		if r.Empty() {
   737			return &Gray{}
   738		}
   739		i := p.PixOffset(r.Min.X, r.Min.Y)
   740		return &Gray{
   741			Pix:    p.Pix[i:],
   742			Stride: p.Stride,
   743			Rect:   r,
   744		}
   745	}
   746	
   747	// Opaque scans the entire image and reports whether it is fully opaque.
   748	func (p *Gray) Opaque() bool {
   749		return true
   750	}
   751	
   752	// NewGray returns a new Gray image with the given bounds.
   753	func NewGray(r Rectangle) *Gray {
   754		w, h := r.Dx(), r.Dy()
   755		pix := make([]uint8, 1*w*h)
   756		return &Gray{pix, 1 * w, r}
   757	}
   758	
   759	// Gray16 is an in-memory image whose At method returns color.Gray16 values.
   760	type Gray16 struct {
   761		// Pix holds the image's pixels, as gray values in big-endian format. The pixel at
   762		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
   763		Pix []uint8
   764		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   765		Stride int
   766		// Rect is the image's bounds.
   767		Rect Rectangle
   768	}
   769	
   770	func (p *Gray16) ColorModel() color.Model { return color.Gray16Model }
   771	
   772	func (p *Gray16) Bounds() Rectangle { return p.Rect }
   773	
   774	func (p *Gray16) At(x, y int) color.Color {
   775		return p.Gray16At(x, y)
   776	}
   777	
   778	func (p *Gray16) Gray16At(x, y int) color.Gray16 {
   779		if !(Point{x, y}.In(p.Rect)) {
   780			return color.Gray16{}
   781		}
   782		i := p.PixOffset(x, y)
   783		return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
   784	}
   785	
   786	// PixOffset returns the index of the first element of Pix that corresponds to
   787	// the pixel at (x, y).
   788	func (p *Gray16) PixOffset(x, y int) int {
   789		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
   790	}
   791	
   792	func (p *Gray16) Set(x, y int, c color.Color) {
   793		if !(Point{x, y}.In(p.Rect)) {
   794			return
   795		}
   796		i := p.PixOffset(x, y)
   797		c1 := color.Gray16Model.Convert(c).(color.Gray16)
   798		p.Pix[i+0] = uint8(c1.Y >> 8)
   799		p.Pix[i+1] = uint8(c1.Y)
   800	}
   801	
   802	func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
   803		if !(Point{x, y}.In(p.Rect)) {
   804			return
   805		}
   806		i := p.PixOffset(x, y)
   807		p.Pix[i+0] = uint8(c.Y >> 8)
   808		p.Pix[i+1] = uint8(c.Y)
   809	}
   810	
   811	// SubImage returns an image representing the portion of the image p visible
   812	// through r. The returned value shares pixels with the original image.
   813	func (p *Gray16) SubImage(r Rectangle) Image {
   814		r = r.Intersect(p.Rect)
   815		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   816		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   817		// this, the Pix[i:] expression below can panic.
   818		if r.Empty() {
   819			return &Gray16{}
   820		}
   821		i := p.PixOffset(r.Min.X, r.Min.Y)
   822		return &Gray16{
   823			Pix:    p.Pix[i:],
   824			Stride: p.Stride,
   825			Rect:   r,
   826		}
   827	}
   828	
   829	// Opaque scans the entire image and reports whether it is fully opaque.
   830	func (p *Gray16) Opaque() bool {
   831		return true
   832	}
   833	
   834	// NewGray16 returns a new Gray16 image with the given bounds.
   835	func NewGray16(r Rectangle) *Gray16 {
   836		w, h := r.Dx(), r.Dy()
   837		pix := make([]uint8, 2*w*h)
   838		return &Gray16{pix, 2 * w, r}
   839	}
   840	
   841	// CMYK is an in-memory image whose At method returns color.CMYK values.
   842	type CMYK struct {
   843		// Pix holds the image's pixels, in C, M, Y, K order. The pixel at
   844		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
   845		Pix []uint8
   846		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   847		Stride int
   848		// Rect is the image's bounds.
   849		Rect Rectangle
   850	}
   851	
   852	func (p *CMYK) ColorModel() color.Model { return color.CMYKModel }
   853	
   854	func (p *CMYK) Bounds() Rectangle { return p.Rect }
   855	
   856	func (p *CMYK) At(x, y int) color.Color {
   857		return p.CMYKAt(x, y)
   858	}
   859	
   860	func (p *CMYK) CMYKAt(x, y int) color.CMYK {
   861		if !(Point{x, y}.In(p.Rect)) {
   862			return color.CMYK{}
   863		}
   864		i := p.PixOffset(x, y)
   865		s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   866		return color.CMYK{s[0], s[1], s[2], s[3]}
   867	}
   868	
   869	// PixOffset returns the index of the first element of Pix that corresponds to
   870	// the pixel at (x, y).
   871	func (p *CMYK) PixOffset(x, y int) int {
   872		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
   873	}
   874	
   875	func (p *CMYK) Set(x, y int, c color.Color) {
   876		if !(Point{x, y}.In(p.Rect)) {
   877			return
   878		}
   879		i := p.PixOffset(x, y)
   880		c1 := color.CMYKModel.Convert(c).(color.CMYK)
   881		s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   882		s[0] = c1.C
   883		s[1] = c1.M
   884		s[2] = c1.Y
   885		s[3] = c1.K
   886	}
   887	
   888	func (p *CMYK) SetCMYK(x, y int, c color.CMYK) {
   889		if !(Point{x, y}.In(p.Rect)) {
   890			return
   891		}
   892		i := p.PixOffset(x, y)
   893		s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   894		s[0] = c.C
   895		s[1] = c.M
   896		s[2] = c.Y
   897		s[3] = c.K
   898	}
   899	
   900	// SubImage returns an image representing the portion of the image p visible
   901	// through r. The returned value shares pixels with the original image.
   902	func (p *CMYK) SubImage(r Rectangle) Image {
   903		r = r.Intersect(p.Rect)
   904		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   905		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   906		// this, the Pix[i:] expression below can panic.
   907		if r.Empty() {
   908			return &CMYK{}
   909		}
   910		i := p.PixOffset(r.Min.X, r.Min.Y)
   911		return &CMYK{
   912			Pix:    p.Pix[i:],
   913			Stride: p.Stride,
   914			Rect:   r,
   915		}
   916	}
   917	
   918	// Opaque scans the entire image and reports whether it is fully opaque.
   919	func (p *CMYK) Opaque() bool {
   920		return true
   921	}
   922	
   923	// NewCMYK returns a new CMYK image with the given bounds.
   924	func NewCMYK(r Rectangle) *CMYK {
   925		w, h := r.Dx(), r.Dy()
   926		buf := make([]uint8, 4*w*h)
   927		return &CMYK{buf, 4 * w, r}
   928	}
   929	
   930	// Paletted is an in-memory image of uint8 indices into a given palette.
   931	type Paletted struct {
   932		// Pix holds the image's pixels, as palette indices. The pixel at
   933		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
   934		Pix []uint8
   935		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   936		Stride int
   937		// Rect is the image's bounds.
   938		Rect Rectangle
   939		// Palette is the image's palette.
   940		Palette color.Palette
   941	}
   942	
   943	func (p *Paletted) ColorModel() color.Model { return p.Palette }
   944	
   945	func (p *Paletted) Bounds() Rectangle { return p.Rect }
   946	
   947	func (p *Paletted) At(x, y int) color.Color {
   948		if len(p.Palette) == 0 {
   949			return nil
   950		}
   951		if !(Point{x, y}.In(p.Rect)) {
   952			return p.Palette[0]
   953		}
   954		i := p.PixOffset(x, y)
   955		return p.Palette[p.Pix[i]]
   956	}
   957	
   958	// PixOffset returns the index of the first element of Pix that corresponds to
   959	// the pixel at (x, y).
   960	func (p *Paletted) PixOffset(x, y int) int {
   961		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
   962	}
   963	
   964	func (p *Paletted) Set(x, y int, c color.Color) {
   965		if !(Point{x, y}.In(p.Rect)) {
   966			return
   967		}
   968		i := p.PixOffset(x, y)
   969		p.Pix[i] = uint8(p.Palette.Index(c))
   970	}
   971	
   972	func (p *Paletted) ColorIndexAt(x, y int) uint8 {
   973		if !(Point{x, y}.In(p.Rect)) {
   974			return 0
   975		}
   976		i := p.PixOffset(x, y)
   977		return p.Pix[i]
   978	}
   979	
   980	func (p *Paletted) SetColorIndex(x, y int, index uint8) {
   981		if !(Point{x, y}.In(p.Rect)) {
   982			return
   983		}
   984		i := p.PixOffset(x, y)
   985		p.Pix[i] = index
   986	}
   987	
   988	// SubImage returns an image representing the portion of the image p visible
   989	// through r. The returned value shares pixels with the original image.
   990	func (p *Paletted) SubImage(r Rectangle) Image {
   991		r = r.Intersect(p.Rect)
   992		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   993		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   994		// this, the Pix[i:] expression below can panic.
   995		if r.Empty() {
   996			return &Paletted{
   997				Palette: p.Palette,
   998			}
   999		}
  1000		i := p.PixOffset(r.Min.X, r.Min.Y)
  1001		return &Paletted{
  1002			Pix:     p.Pix[i:],
  1003			Stride:  p.Stride,
  1004			Rect:    p.Rect.Intersect(r),
  1005			Palette: p.Palette,
  1006		}
  1007	}
  1008	
  1009	// Opaque scans the entire image and reports whether it is fully opaque.
  1010	func (p *Paletted) Opaque() bool {
  1011		var present [256]bool
  1012		i0, i1 := 0, p.Rect.Dx()
  1013		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
  1014			for _, c := range p.Pix[i0:i1] {
  1015				present[c] = true
  1016			}
  1017			i0 += p.Stride
  1018			i1 += p.Stride
  1019		}
  1020		for i, c := range p.Palette {
  1021			if !present[i] {
  1022				continue
  1023			}
  1024			_, _, _, a := c.RGBA()
  1025			if a != 0xffff {
  1026				return false
  1027			}
  1028		}
  1029		return true
  1030	}
  1031	
  1032	// NewPaletted returns a new Paletted image with the given width, height and
  1033	// palette.
  1034	func NewPaletted(r Rectangle, p color.Palette) *Paletted {
  1035		w, h := r.Dx(), r.Dy()
  1036		pix := make([]uint8, 1*w*h)
  1037		return &Paletted{pix, 1 * w, r, p}
  1038	}
  1039	

View as plain text