Run Format

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	// http://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 PalettedColorModel 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 PalettedColorModel, 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		if !(Point{x, y}.In(p.Rect)) {
    76			return color.RGBA{}
    77		}
    78		i := p.PixOffset(x, y)
    79		return color.RGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
    80	}
    81	
    82	// PixOffset returns the index of the first element of Pix that corresponds to
    83	// the pixel at (x, y).
    84	func (p *RGBA) PixOffset(x, y int) int {
    85		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
    86	}
    87	
    88	func (p *RGBA) Set(x, y int, c color.Color) {
    89		if !(Point{x, y}.In(p.Rect)) {
    90			return
    91		}
    92		i := p.PixOffset(x, y)
    93		c1 := color.RGBAModel.Convert(c).(color.RGBA)
    94		p.Pix[i+0] = c1.R
    95		p.Pix[i+1] = c1.G
    96		p.Pix[i+2] = c1.B
    97		p.Pix[i+3] = c1.A
    98	}
    99	
   100	func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
   101		if !(Point{x, y}.In(p.Rect)) {
   102			return
   103		}
   104		i := p.PixOffset(x, y)
   105		p.Pix[i+0] = c.R
   106		p.Pix[i+1] = c.G
   107		p.Pix[i+2] = c.B
   108		p.Pix[i+3] = c.A
   109	}
   110	
   111	// SubImage returns an image representing the portion of the image p visible
   112	// through r. The returned value shares pixels with the original image.
   113	func (p *RGBA) SubImage(r Rectangle) Image {
   114		r = r.Intersect(p.Rect)
   115		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   116		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   117		// this, the Pix[i:] expression below can panic.
   118		if r.Empty() {
   119			return &RGBA{}
   120		}
   121		i := p.PixOffset(r.Min.X, r.Min.Y)
   122		return &RGBA{
   123			Pix:    p.Pix[i:],
   124			Stride: p.Stride,
   125			Rect:   r,
   126		}
   127	}
   128	
   129	// Opaque scans the entire image and reports whether it is fully opaque.
   130	func (p *RGBA) Opaque() bool {
   131		if p.Rect.Empty() {
   132			return true
   133		}
   134		i0, i1 := 3, p.Rect.Dx()*4
   135		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   136			for i := i0; i < i1; i += 4 {
   137				if p.Pix[i] != 0xff {
   138					return false
   139				}
   140			}
   141			i0 += p.Stride
   142			i1 += p.Stride
   143		}
   144		return true
   145	}
   146	
   147	// NewRGBA returns a new RGBA with the given bounds.
   148	func NewRGBA(r Rectangle) *RGBA {
   149		w, h := r.Dx(), r.Dy()
   150		buf := make([]uint8, 4*w*h)
   151		return &RGBA{buf, 4 * w, r}
   152	}
   153	
   154	// RGBA64 is an in-memory image whose At method returns color.RGBA64 values.
   155	type RGBA64 struct {
   156		// Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
   157		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
   158		Pix []uint8
   159		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   160		Stride int
   161		// Rect is the image's bounds.
   162		Rect Rectangle
   163	}
   164	
   165	func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model }
   166	
   167	func (p *RGBA64) Bounds() Rectangle { return p.Rect }
   168	
   169	func (p *RGBA64) At(x, y int) color.Color {
   170		if !(Point{x, y}.In(p.Rect)) {
   171			return color.RGBA64{}
   172		}
   173		i := p.PixOffset(x, y)
   174		return color.RGBA64{
   175			uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
   176			uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
   177			uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
   178			uint16(p.Pix[i+6])<<8 | uint16(p.Pix[i+7]),
   179		}
   180	}
   181	
   182	// PixOffset returns the index of the first element of Pix that corresponds to
   183	// the pixel at (x, y).
   184	func (p *RGBA64) PixOffset(x, y int) int {
   185		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
   186	}
   187	
   188	func (p *RGBA64) Set(x, y int, c color.Color) {
   189		if !(Point{x, y}.In(p.Rect)) {
   190			return
   191		}
   192		i := p.PixOffset(x, y)
   193		c1 := color.RGBA64Model.Convert(c).(color.RGBA64)
   194		p.Pix[i+0] = uint8(c1.R >> 8)
   195		p.Pix[i+1] = uint8(c1.R)
   196		p.Pix[i+2] = uint8(c1.G >> 8)
   197		p.Pix[i+3] = uint8(c1.G)
   198		p.Pix[i+4] = uint8(c1.B >> 8)
   199		p.Pix[i+5] = uint8(c1.B)
   200		p.Pix[i+6] = uint8(c1.A >> 8)
   201		p.Pix[i+7] = uint8(c1.A)
   202	}
   203	
   204	func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
   205		if !(Point{x, y}.In(p.Rect)) {
   206			return
   207		}
   208		i := p.PixOffset(x, y)
   209		p.Pix[i+0] = uint8(c.R >> 8)
   210		p.Pix[i+1] = uint8(c.R)
   211		p.Pix[i+2] = uint8(c.G >> 8)
   212		p.Pix[i+3] = uint8(c.G)
   213		p.Pix[i+4] = uint8(c.B >> 8)
   214		p.Pix[i+5] = uint8(c.B)
   215		p.Pix[i+6] = uint8(c.A >> 8)
   216		p.Pix[i+7] = uint8(c.A)
   217	}
   218	
   219	// SubImage returns an image representing the portion of the image p visible
   220	// through r. The returned value shares pixels with the original image.
   221	func (p *RGBA64) SubImage(r Rectangle) Image {
   222		r = r.Intersect(p.Rect)
   223		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   224		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   225		// this, the Pix[i:] expression below can panic.
   226		if r.Empty() {
   227			return &RGBA64{}
   228		}
   229		i := p.PixOffset(r.Min.X, r.Min.Y)
   230		return &RGBA64{
   231			Pix:    p.Pix[i:],
   232			Stride: p.Stride,
   233			Rect:   r,
   234		}
   235	}
   236	
   237	// Opaque scans the entire image and reports whether it is fully opaque.
   238	func (p *RGBA64) Opaque() bool {
   239		if p.Rect.Empty() {
   240			return true
   241		}
   242		i0, i1 := 6, p.Rect.Dx()*8
   243		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   244			for i := i0; i < i1; i += 8 {
   245				if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
   246					return false
   247				}
   248			}
   249			i0 += p.Stride
   250			i1 += p.Stride
   251		}
   252		return true
   253	}
   254	
   255	// NewRGBA64 returns a new RGBA64 with the given bounds.
   256	func NewRGBA64(r Rectangle) *RGBA64 {
   257		w, h := r.Dx(), r.Dy()
   258		pix := make([]uint8, 8*w*h)
   259		return &RGBA64{pix, 8 * w, r}
   260	}
   261	
   262	// NRGBA is an in-memory image whose At method returns color.NRGBA values.
   263	type NRGBA struct {
   264		// Pix holds the image's pixels, in R, G, B, A order. The pixel at
   265		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
   266		Pix []uint8
   267		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   268		Stride int
   269		// Rect is the image's bounds.
   270		Rect Rectangle
   271	}
   272	
   273	func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel }
   274	
   275	func (p *NRGBA) Bounds() Rectangle { return p.Rect }
   276	
   277	func (p *NRGBA) At(x, y int) color.Color {
   278		if !(Point{x, y}.In(p.Rect)) {
   279			return color.NRGBA{}
   280		}
   281		i := p.PixOffset(x, y)
   282		return color.NRGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
   283	}
   284	
   285	// PixOffset returns the index of the first element of Pix that corresponds to
   286	// the pixel at (x, y).
   287	func (p *NRGBA) PixOffset(x, y int) int {
   288		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
   289	}
   290	
   291	func (p *NRGBA) Set(x, y int, c color.Color) {
   292		if !(Point{x, y}.In(p.Rect)) {
   293			return
   294		}
   295		i := p.PixOffset(x, y)
   296		c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
   297		p.Pix[i+0] = c1.R
   298		p.Pix[i+1] = c1.G
   299		p.Pix[i+2] = c1.B
   300		p.Pix[i+3] = c1.A
   301	}
   302	
   303	func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
   304		if !(Point{x, y}.In(p.Rect)) {
   305			return
   306		}
   307		i := p.PixOffset(x, y)
   308		p.Pix[i+0] = c.R
   309		p.Pix[i+1] = c.G
   310		p.Pix[i+2] = c.B
   311		p.Pix[i+3] = c.A
   312	}
   313	
   314	// SubImage returns an image representing the portion of the image p visible
   315	// through r. The returned value shares pixels with the original image.
   316	func (p *NRGBA) SubImage(r Rectangle) Image {
   317		r = r.Intersect(p.Rect)
   318		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   319		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   320		// this, the Pix[i:] expression below can panic.
   321		if r.Empty() {
   322			return &NRGBA{}
   323		}
   324		i := p.PixOffset(r.Min.X, r.Min.Y)
   325		return &NRGBA{
   326			Pix:    p.Pix[i:],
   327			Stride: p.Stride,
   328			Rect:   r,
   329		}
   330	}
   331	
   332	// Opaque scans the entire image and reports whether it is fully opaque.
   333	func (p *NRGBA) Opaque() bool {
   334		if p.Rect.Empty() {
   335			return true
   336		}
   337		i0, i1 := 3, p.Rect.Dx()*4
   338		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   339			for i := i0; i < i1; i += 4 {
   340				if p.Pix[i] != 0xff {
   341					return false
   342				}
   343			}
   344			i0 += p.Stride
   345			i1 += p.Stride
   346		}
   347		return true
   348	}
   349	
   350	// NewNRGBA returns a new NRGBA with the given bounds.
   351	func NewNRGBA(r Rectangle) *NRGBA {
   352		w, h := r.Dx(), r.Dy()
   353		pix := make([]uint8, 4*w*h)
   354		return &NRGBA{pix, 4 * w, r}
   355	}
   356	
   357	// NRGBA64 is an in-memory image whose At method returns color.NRGBA64 values.
   358	type NRGBA64 struct {
   359		// Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
   360		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
   361		Pix []uint8
   362		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   363		Stride int
   364		// Rect is the image's bounds.
   365		Rect Rectangle
   366	}
   367	
   368	func (p *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model }
   369	
   370	func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
   371	
   372	func (p *NRGBA64) At(x, y int) color.Color {
   373		if !(Point{x, y}.In(p.Rect)) {
   374			return color.NRGBA64{}
   375		}
   376		i := p.PixOffset(x, y)
   377		return color.NRGBA64{
   378			uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
   379			uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
   380			uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
   381			uint16(p.Pix[i+6])<<8 | uint16(p.Pix[i+7]),
   382		}
   383	}
   384	
   385	// PixOffset returns the index of the first element of Pix that corresponds to
   386	// the pixel at (x, y).
   387	func (p *NRGBA64) PixOffset(x, y int) int {
   388		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
   389	}
   390	
   391	func (p *NRGBA64) Set(x, y int, c color.Color) {
   392		if !(Point{x, y}.In(p.Rect)) {
   393			return
   394		}
   395		i := p.PixOffset(x, y)
   396		c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
   397		p.Pix[i+0] = uint8(c1.R >> 8)
   398		p.Pix[i+1] = uint8(c1.R)
   399		p.Pix[i+2] = uint8(c1.G >> 8)
   400		p.Pix[i+3] = uint8(c1.G)
   401		p.Pix[i+4] = uint8(c1.B >> 8)
   402		p.Pix[i+5] = uint8(c1.B)
   403		p.Pix[i+6] = uint8(c1.A >> 8)
   404		p.Pix[i+7] = uint8(c1.A)
   405	}
   406	
   407	func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
   408		if !(Point{x, y}.In(p.Rect)) {
   409			return
   410		}
   411		i := p.PixOffset(x, y)
   412		p.Pix[i+0] = uint8(c.R >> 8)
   413		p.Pix[i+1] = uint8(c.R)
   414		p.Pix[i+2] = uint8(c.G >> 8)
   415		p.Pix[i+3] = uint8(c.G)
   416		p.Pix[i+4] = uint8(c.B >> 8)
   417		p.Pix[i+5] = uint8(c.B)
   418		p.Pix[i+6] = uint8(c.A >> 8)
   419		p.Pix[i+7] = uint8(c.A)
   420	}
   421	
   422	// SubImage returns an image representing the portion of the image p visible
   423	// through r. The returned value shares pixels with the original image.
   424	func (p *NRGBA64) SubImage(r Rectangle) Image {
   425		r = r.Intersect(p.Rect)
   426		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   427		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   428		// this, the Pix[i:] expression below can panic.
   429		if r.Empty() {
   430			return &NRGBA64{}
   431		}
   432		i := p.PixOffset(r.Min.X, r.Min.Y)
   433		return &NRGBA64{
   434			Pix:    p.Pix[i:],
   435			Stride: p.Stride,
   436			Rect:   r,
   437		}
   438	}
   439	
   440	// Opaque scans the entire image and reports whether it is fully opaque.
   441	func (p *NRGBA64) Opaque() bool {
   442		if p.Rect.Empty() {
   443			return true
   444		}
   445		i0, i1 := 6, p.Rect.Dx()*8
   446		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   447			for i := i0; i < i1; i += 8 {
   448				if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
   449					return false
   450				}
   451			}
   452			i0 += p.Stride
   453			i1 += p.Stride
   454		}
   455		return true
   456	}
   457	
   458	// NewNRGBA64 returns a new NRGBA64 with the given bounds.
   459	func NewNRGBA64(r Rectangle) *NRGBA64 {
   460		w, h := r.Dx(), r.Dy()
   461		pix := make([]uint8, 8*w*h)
   462		return &NRGBA64{pix, 8 * w, r}
   463	}
   464	
   465	// Alpha is an in-memory image whose At method returns color.Alpha values.
   466	type Alpha struct {
   467		// Pix holds the image's pixels, as alpha values. The pixel at
   468		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
   469		Pix []uint8
   470		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   471		Stride int
   472		// Rect is the image's bounds.
   473		Rect Rectangle
   474	}
   475	
   476	func (p *Alpha) ColorModel() color.Model { return color.AlphaModel }
   477	
   478	func (p *Alpha) Bounds() Rectangle { return p.Rect }
   479	
   480	func (p *Alpha) At(x, y int) color.Color {
   481		if !(Point{x, y}.In(p.Rect)) {
   482			return color.Alpha{}
   483		}
   484		i := p.PixOffset(x, y)
   485		return color.Alpha{p.Pix[i]}
   486	}
   487	
   488	// PixOffset returns the index of the first element of Pix that corresponds to
   489	// the pixel at (x, y).
   490	func (p *Alpha) PixOffset(x, y int) int {
   491		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
   492	}
   493	
   494	func (p *Alpha) Set(x, y int, c color.Color) {
   495		if !(Point{x, y}.In(p.Rect)) {
   496			return
   497		}
   498		i := p.PixOffset(x, y)
   499		p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
   500	}
   501	
   502	func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
   503		if !(Point{x, y}.In(p.Rect)) {
   504			return
   505		}
   506		i := p.PixOffset(x, y)
   507		p.Pix[i] = c.A
   508	}
   509	
   510	// SubImage returns an image representing the portion of the image p visible
   511	// through r. The returned value shares pixels with the original image.
   512	func (p *Alpha) SubImage(r Rectangle) Image {
   513		r = r.Intersect(p.Rect)
   514		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   515		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   516		// this, the Pix[i:] expression below can panic.
   517		if r.Empty() {
   518			return &Alpha{}
   519		}
   520		i := p.PixOffset(r.Min.X, r.Min.Y)
   521		return &Alpha{
   522			Pix:    p.Pix[i:],
   523			Stride: p.Stride,
   524			Rect:   r,
   525		}
   526	}
   527	
   528	// Opaque scans the entire image and reports whether it is fully opaque.
   529	func (p *Alpha) Opaque() bool {
   530		if p.Rect.Empty() {
   531			return true
   532		}
   533		i0, i1 := 0, p.Rect.Dx()
   534		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   535			for i := i0; i < i1; i++ {
   536				if p.Pix[i] != 0xff {
   537					return false
   538				}
   539			}
   540			i0 += p.Stride
   541			i1 += p.Stride
   542		}
   543		return true
   544	}
   545	
   546	// NewAlpha returns a new Alpha with the given bounds.
   547	func NewAlpha(r Rectangle) *Alpha {
   548		w, h := r.Dx(), r.Dy()
   549		pix := make([]uint8, 1*w*h)
   550		return &Alpha{pix, 1 * w, r}
   551	}
   552	
   553	// Alpha16 is an in-memory image whose At method returns color.Alpha64 values.
   554	type Alpha16 struct {
   555		// Pix holds the image's pixels, as alpha values in big-endian format. The pixel at
   556		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
   557		Pix []uint8
   558		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   559		Stride int
   560		// Rect is the image's bounds.
   561		Rect Rectangle
   562	}
   563	
   564	func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model }
   565	
   566	func (p *Alpha16) Bounds() Rectangle { return p.Rect }
   567	
   568	func (p *Alpha16) At(x, y int) color.Color {
   569		if !(Point{x, y}.In(p.Rect)) {
   570			return color.Alpha16{}
   571		}
   572		i := p.PixOffset(x, y)
   573		return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
   574	}
   575	
   576	// PixOffset returns the index of the first element of Pix that corresponds to
   577	// the pixel at (x, y).
   578	func (p *Alpha16) PixOffset(x, y int) int {
   579		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
   580	}
   581	
   582	func (p *Alpha16) Set(x, y int, c color.Color) {
   583		if !(Point{x, y}.In(p.Rect)) {
   584			return
   585		}
   586		i := p.PixOffset(x, y)
   587		c1 := color.Alpha16Model.Convert(c).(color.Alpha16)
   588		p.Pix[i+0] = uint8(c1.A >> 8)
   589		p.Pix[i+1] = uint8(c1.A)
   590	}
   591	
   592	func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
   593		if !(Point{x, y}.In(p.Rect)) {
   594			return
   595		}
   596		i := p.PixOffset(x, y)
   597		p.Pix[i+0] = uint8(c.A >> 8)
   598		p.Pix[i+1] = uint8(c.A)
   599	}
   600	
   601	// SubImage returns an image representing the portion of the image p visible
   602	// through r. The returned value shares pixels with the original image.
   603	func (p *Alpha16) SubImage(r Rectangle) Image {
   604		r = r.Intersect(p.Rect)
   605		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   606		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   607		// this, the Pix[i:] expression below can panic.
   608		if r.Empty() {
   609			return &Alpha16{}
   610		}
   611		i := p.PixOffset(r.Min.X, r.Min.Y)
   612		return &Alpha16{
   613			Pix:    p.Pix[i:],
   614			Stride: p.Stride,
   615			Rect:   r,
   616		}
   617	}
   618	
   619	// Opaque scans the entire image and reports whether it is fully opaque.
   620	func (p *Alpha16) Opaque() bool {
   621		if p.Rect.Empty() {
   622			return true
   623		}
   624		i0, i1 := 0, p.Rect.Dx()*2
   625		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   626			for i := i0; i < i1; i += 2 {
   627				if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
   628					return false
   629				}
   630			}
   631			i0 += p.Stride
   632			i1 += p.Stride
   633		}
   634		return true
   635	}
   636	
   637	// NewAlpha16 returns a new Alpha16 with the given bounds.
   638	func NewAlpha16(r Rectangle) *Alpha16 {
   639		w, h := r.Dx(), r.Dy()
   640		pix := make([]uint8, 2*w*h)
   641		return &Alpha16{pix, 2 * w, r}
   642	}
   643	
   644	// Gray is an in-memory image whose At method returns color.Gray values.
   645	type Gray struct {
   646		// Pix holds the image's pixels, as gray values. The pixel at
   647		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
   648		Pix []uint8
   649		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   650		Stride int
   651		// Rect is the image's bounds.
   652		Rect Rectangle
   653	}
   654	
   655	func (p *Gray) ColorModel() color.Model { return color.GrayModel }
   656	
   657	func (p *Gray) Bounds() Rectangle { return p.Rect }
   658	
   659	func (p *Gray) At(x, y int) color.Color {
   660		if !(Point{x, y}.In(p.Rect)) {
   661			return color.Gray{}
   662		}
   663		i := p.PixOffset(x, y)
   664		return color.Gray{p.Pix[i]}
   665	}
   666	
   667	// PixOffset returns the index of the first element of Pix that corresponds to
   668	// the pixel at (x, y).
   669	func (p *Gray) PixOffset(x, y int) int {
   670		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
   671	}
   672	
   673	func (p *Gray) Set(x, y int, c color.Color) {
   674		if !(Point{x, y}.In(p.Rect)) {
   675			return
   676		}
   677		i := p.PixOffset(x, y)
   678		p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
   679	}
   680	
   681	func (p *Gray) SetGray(x, y int, c color.Gray) {
   682		if !(Point{x, y}.In(p.Rect)) {
   683			return
   684		}
   685		i := p.PixOffset(x, y)
   686		p.Pix[i] = c.Y
   687	}
   688	
   689	// SubImage returns an image representing the portion of the image p visible
   690	// through r. The returned value shares pixels with the original image.
   691	func (p *Gray) SubImage(r Rectangle) Image {
   692		r = r.Intersect(p.Rect)
   693		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   694		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   695		// this, the Pix[i:] expression below can panic.
   696		if r.Empty() {
   697			return &Gray{}
   698		}
   699		i := p.PixOffset(r.Min.X, r.Min.Y)
   700		return &Gray{
   701			Pix:    p.Pix[i:],
   702			Stride: p.Stride,
   703			Rect:   r,
   704		}
   705	}
   706	
   707	// Opaque scans the entire image and reports whether it is fully opaque.
   708	func (p *Gray) Opaque() bool {
   709		return true
   710	}
   711	
   712	// NewGray returns a new Gray with the given bounds.
   713	func NewGray(r Rectangle) *Gray {
   714		w, h := r.Dx(), r.Dy()
   715		pix := make([]uint8, 1*w*h)
   716		return &Gray{pix, 1 * w, r}
   717	}
   718	
   719	// Gray16 is an in-memory image whose At method returns color.Gray16 values.
   720	type Gray16 struct {
   721		// Pix holds the image's pixels, as gray values in big-endian format. The pixel at
   722		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
   723		Pix []uint8
   724		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   725		Stride int
   726		// Rect is the image's bounds.
   727		Rect Rectangle
   728	}
   729	
   730	func (p *Gray16) ColorModel() color.Model { return color.Gray16Model }
   731	
   732	func (p *Gray16) Bounds() Rectangle { return p.Rect }
   733	
   734	func (p *Gray16) At(x, y int) color.Color {
   735		if !(Point{x, y}.In(p.Rect)) {
   736			return color.Gray16{}
   737		}
   738		i := p.PixOffset(x, y)
   739		return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
   740	}
   741	
   742	// PixOffset returns the index of the first element of Pix that corresponds to
   743	// the pixel at (x, y).
   744	func (p *Gray16) PixOffset(x, y int) int {
   745		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
   746	}
   747	
   748	func (p *Gray16) Set(x, y int, c color.Color) {
   749		if !(Point{x, y}.In(p.Rect)) {
   750			return
   751		}
   752		i := p.PixOffset(x, y)
   753		c1 := color.Gray16Model.Convert(c).(color.Gray16)
   754		p.Pix[i+0] = uint8(c1.Y >> 8)
   755		p.Pix[i+1] = uint8(c1.Y)
   756	}
   757	
   758	func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
   759		if !(Point{x, y}.In(p.Rect)) {
   760			return
   761		}
   762		i := p.PixOffset(x, y)
   763		p.Pix[i+0] = uint8(c.Y >> 8)
   764		p.Pix[i+1] = uint8(c.Y)
   765	}
   766	
   767	// SubImage returns an image representing the portion of the image p visible
   768	// through r. The returned value shares pixels with the original image.
   769	func (p *Gray16) SubImage(r Rectangle) Image {
   770		r = r.Intersect(p.Rect)
   771		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   772		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   773		// this, the Pix[i:] expression below can panic.
   774		if r.Empty() {
   775			return &Gray16{}
   776		}
   777		i := p.PixOffset(r.Min.X, r.Min.Y)
   778		return &Gray16{
   779			Pix:    p.Pix[i:],
   780			Stride: p.Stride,
   781			Rect:   r,
   782		}
   783	}
   784	
   785	// Opaque scans the entire image and reports whether it is fully opaque.
   786	func (p *Gray16) Opaque() bool {
   787		return true
   788	}
   789	
   790	// NewGray16 returns a new Gray16 with the given bounds.
   791	func NewGray16(r Rectangle) *Gray16 {
   792		w, h := r.Dx(), r.Dy()
   793		pix := make([]uint8, 2*w*h)
   794		return &Gray16{pix, 2 * w, r}
   795	}
   796	
   797	// Paletted is an in-memory image of uint8 indices into a given palette.
   798	type Paletted struct {
   799		// Pix holds the image's pixels, as palette indices. The pixel at
   800		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
   801		Pix []uint8
   802		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   803		Stride int
   804		// Rect is the image's bounds.
   805		Rect Rectangle
   806		// Palette is the image's palette.
   807		Palette color.Palette
   808	}
   809	
   810	func (p *Paletted) ColorModel() color.Model { return p.Palette }
   811	
   812	func (p *Paletted) Bounds() Rectangle { return p.Rect }
   813	
   814	func (p *Paletted) At(x, y int) color.Color {
   815		if len(p.Palette) == 0 {
   816			return nil
   817		}
   818		if !(Point{x, y}.In(p.Rect)) {
   819			return p.Palette[0]
   820		}
   821		i := p.PixOffset(x, y)
   822		return p.Palette[p.Pix[i]]
   823	}
   824	
   825	// PixOffset returns the index of the first element of Pix that corresponds to
   826	// the pixel at (x, y).
   827	func (p *Paletted) PixOffset(x, y int) int {
   828		return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
   829	}
   830	
   831	func (p *Paletted) Set(x, y int, c color.Color) {
   832		if !(Point{x, y}.In(p.Rect)) {
   833			return
   834		}
   835		i := p.PixOffset(x, y)
   836		p.Pix[i] = uint8(p.Palette.Index(c))
   837	}
   838	
   839	func (p *Paletted) ColorIndexAt(x, y int) uint8 {
   840		if !(Point{x, y}.In(p.Rect)) {
   841			return 0
   842		}
   843		i := p.PixOffset(x, y)
   844		return p.Pix[i]
   845	}
   846	
   847	func (p *Paletted) SetColorIndex(x, y int, index uint8) {
   848		if !(Point{x, y}.In(p.Rect)) {
   849			return
   850		}
   851		i := p.PixOffset(x, y)
   852		p.Pix[i] = index
   853	}
   854	
   855	// SubImage returns an image representing the portion of the image p visible
   856	// through r. The returned value shares pixels with the original image.
   857	func (p *Paletted) SubImage(r Rectangle) Image {
   858		r = r.Intersect(p.Rect)
   859		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   860		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   861		// this, the Pix[i:] expression below can panic.
   862		if r.Empty() {
   863			return &Paletted{
   864				Palette: p.Palette,
   865			}
   866		}
   867		i := p.PixOffset(r.Min.X, r.Min.Y)
   868		return &Paletted{
   869			Pix:     p.Pix[i:],
   870			Stride:  p.Stride,
   871			Rect:    p.Rect.Intersect(r),
   872			Palette: p.Palette,
   873		}
   874	}
   875	
   876	// Opaque scans the entire image and reports whether it is fully opaque.
   877	func (p *Paletted) Opaque() bool {
   878		var present [256]bool
   879		i0, i1 := 0, p.Rect.Dx()
   880		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   881			for _, c := range p.Pix[i0:i1] {
   882				present[c] = true
   883			}
   884			i0 += p.Stride
   885			i1 += p.Stride
   886		}
   887		for i, c := range p.Palette {
   888			if !present[i] {
   889				continue
   890			}
   891			_, _, _, a := c.RGBA()
   892			if a != 0xffff {
   893				return false
   894			}
   895		}
   896		return true
   897	}
   898	
   899	// NewPaletted returns a new Paletted with the given width, height and palette.
   900	func NewPaletted(r Rectangle, p color.Palette) *Paletted {
   901		w, h := r.Dx(), r.Dy()
   902		pix := make([]uint8, 1*w*h)
   903		return &Paletted{pix, 1 * w, r, p}
   904	}

View as plain text