...

Source file src/image/image.go

Documentation: image

     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  //
    17  //	import _ "image/png"
    18  //
    19  // in a program's main package. The _ means to import a package purely for its
    20  // initialization side effects.
    21  //
    22  // See "The Go image package" for more details:
    23  // https://golang.org/doc/articles/image_package.html
    24  package image
    25  
    26  import (
    27  	"image/color"
    28  )
    29  
    30  // Config holds an image's color model and dimensions.
    31  type Config struct {
    32  	ColorModel    color.Model
    33  	Width, Height int
    34  }
    35  
    36  // Image is a finite rectangular grid of color.Color values taken from a color
    37  // model.
    38  type Image interface {
    39  	// ColorModel returns the Image's color model.
    40  	ColorModel() color.Model
    41  	// Bounds returns the domain for which At can return non-zero color.
    42  	// The bounds do not necessarily contain the point (0, 0).
    43  	Bounds() Rectangle
    44  	// At returns the color of the pixel at (x, y).
    45  	// At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
    46  	// At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
    47  	At(x, y int) color.Color
    48  }
    49  
    50  // RGBA64Image is an Image whose pixels can be converted directly to a
    51  // color.RGBA64.
    52  type RGBA64Image interface {
    53  	// RGBA64At returns the RGBA64 color of the pixel at (x, y). It is
    54  	// equivalent to calling At(x, y).RGBA() and converting the resulting
    55  	// 32-bit return values to a color.RGBA64, but it can avoid allocations
    56  	// from converting concrete color types to the color.Color interface type.
    57  	RGBA64At(x, y int) color.RGBA64
    58  	Image
    59  }
    60  
    61  // PalettedImage is an image whose colors may come from a limited palette.
    62  // If m is a PalettedImage and m.ColorModel() returns a color.Palette p,
    63  // then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's
    64  // color model is not a color.Palette, then ColorIndexAt's behavior is
    65  // undefined.
    66  type PalettedImage interface {
    67  	// ColorIndexAt returns the palette index of the pixel at (x, y).
    68  	ColorIndexAt(x, y int) uint8
    69  	Image
    70  }
    71  
    72  // pixelBufferLength returns the length of the []uint8 typed Pix slice field
    73  // for the NewXxx functions. Conceptually, this is just (bpp * width * height),
    74  // but this function panics if at least one of those is negative or if the
    75  // computation would overflow the int type.
    76  //
    77  // This panics instead of returning an error because of backwards
    78  // compatibility. The NewXxx functions do not return an error.
    79  func pixelBufferLength(bytesPerPixel int, r Rectangle, imageTypeName string) int {
    80  	totalLength := mul3NonNeg(bytesPerPixel, r.Dx(), r.Dy())
    81  	if totalLength < 0 {
    82  		panic("image: New" + imageTypeName + " Rectangle has huge or negative dimensions")
    83  	}
    84  	return totalLength
    85  }
    86  
    87  // RGBA is an in-memory image whose At method returns color.RGBA values.
    88  type RGBA struct {
    89  	// Pix holds the image's pixels, in R, G, B, A order. The pixel at
    90  	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
    91  	Pix []uint8
    92  	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
    93  	Stride int
    94  	// Rect is the image's bounds.
    95  	Rect Rectangle
    96  }
    97  
    98  func (p *RGBA) ColorModel() color.Model { return color.RGBAModel }
    99  
   100  func (p *RGBA) Bounds() Rectangle { return p.Rect }
   101  
   102  func (p *RGBA) At(x, y int) color.Color {
   103  	return p.RGBAAt(x, y)
   104  }
   105  
   106  func (p *RGBA) RGBA64At(x, y int) color.RGBA64 {
   107  	if !(Point{x, y}.In(p.Rect)) {
   108  		return color.RGBA64{}
   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  	r := uint16(s[0])
   113  	g := uint16(s[1])
   114  	b := uint16(s[2])
   115  	a := uint16(s[3])
   116  	return color.RGBA64{
   117  		(r << 8) | r,
   118  		(g << 8) | g,
   119  		(b << 8) | b,
   120  		(a << 8) | a,
   121  	}
   122  }
   123  
   124  func (p *RGBA) RGBAAt(x, y int) color.RGBA {
   125  	if !(Point{x, y}.In(p.Rect)) {
   126  		return color.RGBA{}
   127  	}
   128  	i := p.PixOffset(x, y)
   129  	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   130  	return color.RGBA{s[0], s[1], s[2], s[3]}
   131  }
   132  
   133  // PixOffset returns the index of the first element of Pix that corresponds to
   134  // the pixel at (x, y).
   135  func (p *RGBA) PixOffset(x, y int) int {
   136  	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
   137  }
   138  
   139  func (p *RGBA) Set(x, y int, c color.Color) {
   140  	if !(Point{x, y}.In(p.Rect)) {
   141  		return
   142  	}
   143  	i := p.PixOffset(x, y)
   144  	c1 := color.RGBAModel.Convert(c).(color.RGBA)
   145  	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   146  	s[0] = c1.R
   147  	s[1] = c1.G
   148  	s[2] = c1.B
   149  	s[3] = c1.A
   150  }
   151  
   152  func (p *RGBA) SetRGBA64(x, y int, c color.RGBA64) {
   153  	if !(Point{x, y}.In(p.Rect)) {
   154  		return
   155  	}
   156  	i := p.PixOffset(x, y)
   157  	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   158  	s[0] = uint8(c.R >> 8)
   159  	s[1] = uint8(c.G >> 8)
   160  	s[2] = uint8(c.B >> 8)
   161  	s[3] = uint8(c.A >> 8)
   162  }
   163  
   164  func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
   165  	if !(Point{x, y}.In(p.Rect)) {
   166  		return
   167  	}
   168  	i := p.PixOffset(x, y)
   169  	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   170  	s[0] = c.R
   171  	s[1] = c.G
   172  	s[2] = c.B
   173  	s[3] = c.A
   174  }
   175  
   176  // SubImage returns an image representing the portion of the image p visible
   177  // through r. The returned value shares pixels with the original image.
   178  func (p *RGBA) SubImage(r Rectangle) Image {
   179  	r = r.Intersect(p.Rect)
   180  	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   181  	// either r1 or r2 if the intersection is empty. Without explicitly checking for
   182  	// this, the Pix[i:] expression below can panic.
   183  	if r.Empty() {
   184  		return &RGBA{}
   185  	}
   186  	i := p.PixOffset(r.Min.X, r.Min.Y)
   187  	return &RGBA{
   188  		Pix:    p.Pix[i:],
   189  		Stride: p.Stride,
   190  		Rect:   r,
   191  	}
   192  }
   193  
   194  // Opaque scans the entire image and reports whether it is fully opaque.
   195  func (p *RGBA) Opaque() bool {
   196  	if p.Rect.Empty() {
   197  		return true
   198  	}
   199  	i0, i1 := 3, p.Rect.Dx()*4
   200  	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   201  		for i := i0; i < i1; i += 4 {
   202  			if p.Pix[i] != 0xff {
   203  				return false
   204  			}
   205  		}
   206  		i0 += p.Stride
   207  		i1 += p.Stride
   208  	}
   209  	return true
   210  }
   211  
   212  // NewRGBA returns a new RGBA image with the given bounds.
   213  func NewRGBA(r Rectangle) *RGBA {
   214  	return &RGBA{
   215  		Pix:    make([]uint8, pixelBufferLength(4, r, "RGBA")),
   216  		Stride: 4 * r.Dx(),
   217  		Rect:   r,
   218  	}
   219  }
   220  
   221  // RGBA64 is an in-memory image whose At method returns color.RGBA64 values.
   222  type RGBA64 struct {
   223  	// Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
   224  	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
   225  	Pix []uint8
   226  	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   227  	Stride int
   228  	// Rect is the image's bounds.
   229  	Rect Rectangle
   230  }
   231  
   232  func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model }
   233  
   234  func (p *RGBA64) Bounds() Rectangle { return p.Rect }
   235  
   236  func (p *RGBA64) At(x, y int) color.Color {
   237  	return p.RGBA64At(x, y)
   238  }
   239  
   240  func (p *RGBA64) RGBA64At(x, y int) color.RGBA64 {
   241  	if !(Point{x, y}.In(p.Rect)) {
   242  		return color.RGBA64{}
   243  	}
   244  	i := p.PixOffset(x, y)
   245  	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   246  	return color.RGBA64{
   247  		uint16(s[0])<<8 | uint16(s[1]),
   248  		uint16(s[2])<<8 | uint16(s[3]),
   249  		uint16(s[4])<<8 | uint16(s[5]),
   250  		uint16(s[6])<<8 | uint16(s[7]),
   251  	}
   252  }
   253  
   254  // PixOffset returns the index of the first element of Pix that corresponds to
   255  // the pixel at (x, y).
   256  func (p *RGBA64) PixOffset(x, y int) int {
   257  	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
   258  }
   259  
   260  func (p *RGBA64) Set(x, y int, c color.Color) {
   261  	if !(Point{x, y}.In(p.Rect)) {
   262  		return
   263  	}
   264  	i := p.PixOffset(x, y)
   265  	c1 := color.RGBA64Model.Convert(c).(color.RGBA64)
   266  	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   267  	s[0] = uint8(c1.R >> 8)
   268  	s[1] = uint8(c1.R)
   269  	s[2] = uint8(c1.G >> 8)
   270  	s[3] = uint8(c1.G)
   271  	s[4] = uint8(c1.B >> 8)
   272  	s[5] = uint8(c1.B)
   273  	s[6] = uint8(c1.A >> 8)
   274  	s[7] = uint8(c1.A)
   275  }
   276  
   277  func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
   278  	if !(Point{x, y}.In(p.Rect)) {
   279  		return
   280  	}
   281  	i := p.PixOffset(x, y)
   282  	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   283  	s[0] = uint8(c.R >> 8)
   284  	s[1] = uint8(c.R)
   285  	s[2] = uint8(c.G >> 8)
   286  	s[3] = uint8(c.G)
   287  	s[4] = uint8(c.B >> 8)
   288  	s[5] = uint8(c.B)
   289  	s[6] = uint8(c.A >> 8)
   290  	s[7] = uint8(c.A)
   291  }
   292  
   293  // SubImage returns an image representing the portion of the image p visible
   294  // through r. The returned value shares pixels with the original image.
   295  func (p *RGBA64) SubImage(r Rectangle) Image {
   296  	r = r.Intersect(p.Rect)
   297  	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   298  	// either r1 or r2 if the intersection is empty. Without explicitly checking for
   299  	// this, the Pix[i:] expression below can panic.
   300  	if r.Empty() {
   301  		return &RGBA64{}
   302  	}
   303  	i := p.PixOffset(r.Min.X, r.Min.Y)
   304  	return &RGBA64{
   305  		Pix:    p.Pix[i:],
   306  		Stride: p.Stride,
   307  		Rect:   r,
   308  	}
   309  }
   310  
   311  // Opaque scans the entire image and reports whether it is fully opaque.
   312  func (p *RGBA64) Opaque() bool {
   313  	if p.Rect.Empty() {
   314  		return true
   315  	}
   316  	i0, i1 := 6, p.Rect.Dx()*8
   317  	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   318  		for i := i0; i < i1; i += 8 {
   319  			if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
   320  				return false
   321  			}
   322  		}
   323  		i0 += p.Stride
   324  		i1 += p.Stride
   325  	}
   326  	return true
   327  }
   328  
   329  // NewRGBA64 returns a new RGBA64 image with the given bounds.
   330  func NewRGBA64(r Rectangle) *RGBA64 {
   331  	return &RGBA64{
   332  		Pix:    make([]uint8, pixelBufferLength(8, r, "RGBA64")),
   333  		Stride: 8 * r.Dx(),
   334  		Rect:   r,
   335  	}
   336  }
   337  
   338  // NRGBA is an in-memory image whose At method returns color.NRGBA values.
   339  type NRGBA struct {
   340  	// Pix holds the image's pixels, in R, G, B, A order. The pixel at
   341  	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
   342  	Pix []uint8
   343  	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   344  	Stride int
   345  	// Rect is the image's bounds.
   346  	Rect Rectangle
   347  }
   348  
   349  func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel }
   350  
   351  func (p *NRGBA) Bounds() Rectangle { return p.Rect }
   352  
   353  func (p *NRGBA) At(x, y int) color.Color {
   354  	return p.NRGBAAt(x, y)
   355  }
   356  
   357  func (p *NRGBA) RGBA64At(x, y int) color.RGBA64 {
   358  	r, g, b, a := p.NRGBAAt(x, y).RGBA()
   359  	return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
   360  }
   361  
   362  func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA {
   363  	if !(Point{x, y}.In(p.Rect)) {
   364  		return color.NRGBA{}
   365  	}
   366  	i := p.PixOffset(x, y)
   367  	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   368  	return color.NRGBA{s[0], s[1], s[2], s[3]}
   369  }
   370  
   371  // PixOffset returns the index of the first element of Pix that corresponds to
   372  // the pixel at (x, y).
   373  func (p *NRGBA) PixOffset(x, y int) int {
   374  	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
   375  }
   376  
   377  func (p *NRGBA) Set(x, y int, c color.Color) {
   378  	if !(Point{x, y}.In(p.Rect)) {
   379  		return
   380  	}
   381  	i := p.PixOffset(x, y)
   382  	c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
   383  	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   384  	s[0] = c1.R
   385  	s[1] = c1.G
   386  	s[2] = c1.B
   387  	s[3] = c1.A
   388  }
   389  
   390  func (p *NRGBA) SetRGBA64(x, y int, c color.RGBA64) {
   391  	if !(Point{x, y}.In(p.Rect)) {
   392  		return
   393  	}
   394  	r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
   395  	if (a != 0) && (a != 0xffff) {
   396  		r = (r * 0xffff) / a
   397  		g = (g * 0xffff) / a
   398  		b = (b * 0xffff) / a
   399  	}
   400  	i := p.PixOffset(x, y)
   401  	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   402  	s[0] = uint8(r >> 8)
   403  	s[1] = uint8(g >> 8)
   404  	s[2] = uint8(b >> 8)
   405  	s[3] = uint8(a >> 8)
   406  }
   407  
   408  func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
   409  	if !(Point{x, y}.In(p.Rect)) {
   410  		return
   411  	}
   412  	i := p.PixOffset(x, y)
   413  	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
   414  	s[0] = c.R
   415  	s[1] = c.G
   416  	s[2] = c.B
   417  	s[3] = c.A
   418  }
   419  
   420  // SubImage returns an image representing the portion of the image p visible
   421  // through r. The returned value shares pixels with the original image.
   422  func (p *NRGBA) SubImage(r Rectangle) Image {
   423  	r = r.Intersect(p.Rect)
   424  	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   425  	// either r1 or r2 if the intersection is empty. Without explicitly checking for
   426  	// this, the Pix[i:] expression below can panic.
   427  	if r.Empty() {
   428  		return &NRGBA{}
   429  	}
   430  	i := p.PixOffset(r.Min.X, r.Min.Y)
   431  	return &NRGBA{
   432  		Pix:    p.Pix[i:],
   433  		Stride: p.Stride,
   434  		Rect:   r,
   435  	}
   436  }
   437  
   438  // Opaque scans the entire image and reports whether it is fully opaque.
   439  func (p *NRGBA) Opaque() bool {
   440  	if p.Rect.Empty() {
   441  		return true
   442  	}
   443  	i0, i1 := 3, p.Rect.Dx()*4
   444  	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   445  		for i := i0; i < i1; i += 4 {
   446  			if p.Pix[i] != 0xff {
   447  				return false
   448  			}
   449  		}
   450  		i0 += p.Stride
   451  		i1 += p.Stride
   452  	}
   453  	return true
   454  }
   455  
   456  // NewNRGBA returns a new NRGBA image with the given bounds.
   457  func NewNRGBA(r Rectangle) *NRGBA {
   458  	return &NRGBA{
   459  		Pix:    make([]uint8, pixelBufferLength(4, r, "NRGBA")),
   460  		Stride: 4 * r.Dx(),
   461  		Rect:   r,
   462  	}
   463  }
   464  
   465  // NRGBA64 is an in-memory image whose At method returns color.NRGBA64 values.
   466  type NRGBA64 struct {
   467  	// Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
   468  	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
   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 *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model }
   477  
   478  func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
   479  
   480  func (p *NRGBA64) At(x, y int) color.Color {
   481  	return p.NRGBA64At(x, y)
   482  }
   483  
   484  func (p *NRGBA64) RGBA64At(x, y int) color.RGBA64 {
   485  	r, g, b, a := p.NRGBA64At(x, y).RGBA()
   486  	return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
   487  }
   488  
   489  func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 {
   490  	if !(Point{x, y}.In(p.Rect)) {
   491  		return color.NRGBA64{}
   492  	}
   493  	i := p.PixOffset(x, y)
   494  	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   495  	return color.NRGBA64{
   496  		uint16(s[0])<<8 | uint16(s[1]),
   497  		uint16(s[2])<<8 | uint16(s[3]),
   498  		uint16(s[4])<<8 | uint16(s[5]),
   499  		uint16(s[6])<<8 | uint16(s[7]),
   500  	}
   501  }
   502  
   503  // PixOffset returns the index of the first element of Pix that corresponds to
   504  // the pixel at (x, y).
   505  func (p *NRGBA64) PixOffset(x, y int) int {
   506  	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
   507  }
   508  
   509  func (p *NRGBA64) Set(x, y int, c color.Color) {
   510  	if !(Point{x, y}.In(p.Rect)) {
   511  		return
   512  	}
   513  	i := p.PixOffset(x, y)
   514  	c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
   515  	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   516  	s[0] = uint8(c1.R >> 8)
   517  	s[1] = uint8(c1.R)
   518  	s[2] = uint8(c1.G >> 8)
   519  	s[3] = uint8(c1.G)
   520  	s[4] = uint8(c1.B >> 8)
   521  	s[5] = uint8(c1.B)
   522  	s[6] = uint8(c1.A >> 8)
   523  	s[7] = uint8(c1.A)
   524  }
   525  
   526  func (p *NRGBA64) SetRGBA64(x, y int, c color.RGBA64) {
   527  	if !(Point{x, y}.In(p.Rect)) {
   528  		return
   529  	}
   530  	r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
   531  	if (a != 0) && (a != 0xffff) {
   532  		r = (r * 0xffff) / a
   533  		g = (g * 0xffff) / a
   534  		b = (b * 0xffff) / a
   535  	}
   536  	i := p.PixOffset(x, y)
   537  	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   538  	s[0] = uint8(r >> 8)
   539  	s[1] = uint8(r)
   540  	s[2] = uint8(g >> 8)
   541  	s[3] = uint8(g)
   542  	s[4] = uint8(b >> 8)
   543  	s[5] = uint8(b)
   544  	s[6] = uint8(a >> 8)
   545  	s[7] = uint8(a)
   546  }
   547  
   548  func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
   549  	if !(Point{x, y}.In(p.Rect)) {
   550  		return
   551  	}
   552  	i := p.PixOffset(x, y)
   553  	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
   554  	s[0] = uint8(c.R >> 8)
   555  	s[1] = uint8(c.R)
   556  	s[2] = uint8(c.G >> 8)
   557  	s[3] = uint8(c.G)
   558  	s[4] = uint8(c.B >> 8)
   559  	s[5] = uint8(c.B)
   560  	s[6] = uint8(c.A >> 8)
   561  	s[7] = uint8(c.A)
   562  }
   563  
   564  // SubImage returns an image representing the portion of the image p visible
   565  // through r. The returned value shares pixels with the original image.
   566  func (p *NRGBA64) SubImage(r Rectangle) Image {
   567  	r = r.Intersect(p.Rect)
   568  	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   569  	// either r1 or r2 if the intersection is empty. Without explicitly checking for
   570  	// this, the Pix[i:] expression below can panic.
   571  	if r.Empty() {
   572  		return &NRGBA64{}
   573  	}
   574  	i := p.PixOffset(r.Min.X, r.Min.Y)
   575  	return &NRGBA64{
   576  		Pix:    p.Pix[i:],
   577  		Stride: p.Stride,
   578  		Rect:   r,
   579  	}
   580  }
   581  
   582  // Opaque scans the entire image and reports whether it is fully opaque.
   583  func (p *NRGBA64) Opaque() bool {
   584  	if p.Rect.Empty() {
   585  		return true
   586  	}
   587  	i0, i1 := 6, p.Rect.Dx()*8
   588  	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   589  		for i := i0; i < i1; i += 8 {
   590  			if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
   591  				return false
   592  			}
   593  		}
   594  		i0 += p.Stride
   595  		i1 += p.Stride
   596  	}
   597  	return true
   598  }
   599  
   600  // NewNRGBA64 returns a new NRGBA64 image with the given bounds.
   601  func NewNRGBA64(r Rectangle) *NRGBA64 {
   602  	return &NRGBA64{
   603  		Pix:    make([]uint8, pixelBufferLength(8, r, "NRGBA64")),
   604  		Stride: 8 * r.Dx(),
   605  		Rect:   r,
   606  	}
   607  }
   608  
   609  // Alpha is an in-memory image whose At method returns color.Alpha values.
   610  type Alpha struct {
   611  	// Pix holds the image's pixels, as alpha values. The pixel at
   612  	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
   613  	Pix []uint8
   614  	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   615  	Stride int
   616  	// Rect is the image's bounds.
   617  	Rect Rectangle
   618  }
   619  
   620  func (p *Alpha) ColorModel() color.Model { return color.AlphaModel }
   621  
   622  func (p *Alpha) Bounds() Rectangle { return p.Rect }
   623  
   624  func (p *Alpha) At(x, y int) color.Color {
   625  	return p.AlphaAt(x, y)
   626  }
   627  
   628  func (p *Alpha) RGBA64At(x, y int) color.RGBA64 {
   629  	a := uint16(p.AlphaAt(x, y).A)
   630  	a |= a << 8
   631  	return color.RGBA64{a, a, a, a}
   632  }
   633  
   634  func (p *Alpha) AlphaAt(x, y int) color.Alpha {
   635  	if !(Point{x, y}.In(p.Rect)) {
   636  		return color.Alpha{}
   637  	}
   638  	i := p.PixOffset(x, y)
   639  	return color.Alpha{p.Pix[i]}
   640  }
   641  
   642  // PixOffset returns the index of the first element of Pix that corresponds to
   643  // the pixel at (x, y).
   644  func (p *Alpha) PixOffset(x, y int) int {
   645  	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
   646  }
   647  
   648  func (p *Alpha) Set(x, y int, c color.Color) {
   649  	if !(Point{x, y}.In(p.Rect)) {
   650  		return
   651  	}
   652  	i := p.PixOffset(x, y)
   653  	p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
   654  }
   655  
   656  func (p *Alpha) SetRGBA64(x, y int, c color.RGBA64) {
   657  	if !(Point{x, y}.In(p.Rect)) {
   658  		return
   659  	}
   660  	i := p.PixOffset(x, y)
   661  	p.Pix[i] = uint8(c.A >> 8)
   662  }
   663  
   664  func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
   665  	if !(Point{x, y}.In(p.Rect)) {
   666  		return
   667  	}
   668  	i := p.PixOffset(x, y)
   669  	p.Pix[i] = c.A
   670  }
   671  
   672  // SubImage returns an image representing the portion of the image p visible
   673  // through r. The returned value shares pixels with the original image.
   674  func (p *Alpha) SubImage(r Rectangle) Image {
   675  	r = r.Intersect(p.Rect)
   676  	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   677  	// either r1 or r2 if the intersection is empty. Without explicitly checking for
   678  	// this, the Pix[i:] expression below can panic.
   679  	if r.Empty() {
   680  		return &Alpha{}
   681  	}
   682  	i := p.PixOffset(r.Min.X, r.Min.Y)
   683  	return &Alpha{
   684  		Pix:    p.Pix[i:],
   685  		Stride: p.Stride,
   686  		Rect:   r,
   687  	}
   688  }
   689  
   690  // Opaque scans the entire image and reports whether it is fully opaque.
   691  func (p *Alpha) Opaque() bool {
   692  	if p.Rect.Empty() {
   693  		return true
   694  	}
   695  	i0, i1 := 0, p.Rect.Dx()
   696  	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   697  		for i := i0; i < i1; i++ {
   698  			if p.Pix[i] != 0xff {
   699  				return false
   700  			}
   701  		}
   702  		i0 += p.Stride
   703  		i1 += p.Stride
   704  	}
   705  	return true
   706  }
   707  
   708  // NewAlpha returns a new Alpha image with the given bounds.
   709  func NewAlpha(r Rectangle) *Alpha {
   710  	return &Alpha{
   711  		Pix:    make([]uint8, pixelBufferLength(1, r, "Alpha")),
   712  		Stride: 1 * r.Dx(),
   713  		Rect:   r,
   714  	}
   715  }
   716  
   717  // Alpha16 is an in-memory image whose At method returns color.Alpha16 values.
   718  type Alpha16 struct {
   719  	// Pix holds the image's pixels, as alpha values in big-endian format. The pixel at
   720  	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
   721  	Pix []uint8
   722  	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   723  	Stride int
   724  	// Rect is the image's bounds.
   725  	Rect Rectangle
   726  }
   727  
   728  func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model }
   729  
   730  func (p *Alpha16) Bounds() Rectangle { return p.Rect }
   731  
   732  func (p *Alpha16) At(x, y int) color.Color {
   733  	return p.Alpha16At(x, y)
   734  }
   735  
   736  func (p *Alpha16) RGBA64At(x, y int) color.RGBA64 {
   737  	a := p.Alpha16At(x, y).A
   738  	return color.RGBA64{a, a, a, a}
   739  }
   740  
   741  func (p *Alpha16) Alpha16At(x, y int) color.Alpha16 {
   742  	if !(Point{x, y}.In(p.Rect)) {
   743  		return color.Alpha16{}
   744  	}
   745  	i := p.PixOffset(x, y)
   746  	return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
   747  }
   748  
   749  // PixOffset returns the index of the first element of Pix that corresponds to
   750  // the pixel at (x, y).
   751  func (p *Alpha16) PixOffset(x, y int) int {
   752  	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
   753  }
   754  
   755  func (p *Alpha16) Set(x, y int, c color.Color) {
   756  	if !(Point{x, y}.In(p.Rect)) {
   757  		return
   758  	}
   759  	i := p.PixOffset(x, y)
   760  	c1 := color.Alpha16Model.Convert(c).(color.Alpha16)
   761  	p.Pix[i+0] = uint8(c1.A >> 8)
   762  	p.Pix[i+1] = uint8(c1.A)
   763  }
   764  
   765  func (p *Alpha16) SetRGBA64(x, y int, c color.RGBA64) {
   766  	if !(Point{x, y}.In(p.Rect)) {
   767  		return
   768  	}
   769  	i := p.PixOffset(x, y)
   770  	p.Pix[i+0] = uint8(c.A >> 8)
   771  	p.Pix[i+1] = uint8(c.A)
   772  }
   773  
   774  func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
   775  	if !(Point{x, y}.In(p.Rect)) {
   776  		return
   777  	}
   778  	i := p.PixOffset(x, y)
   779  	p.Pix[i+0] = uint8(c.A >> 8)
   780  	p.Pix[i+1] = uint8(c.A)
   781  }
   782  
   783  // SubImage returns an image representing the portion of the image p visible
   784  // through r. The returned value shares pixels with the original image.
   785  func (p *Alpha16) SubImage(r Rectangle) Image {
   786  	r = r.Intersect(p.Rect)
   787  	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   788  	// either r1 or r2 if the intersection is empty. Without explicitly checking for
   789  	// this, the Pix[i:] expression below can panic.
   790  	if r.Empty() {
   791  		return &Alpha16{}
   792  	}
   793  	i := p.PixOffset(r.Min.X, r.Min.Y)
   794  	return &Alpha16{
   795  		Pix:    p.Pix[i:],
   796  		Stride: p.Stride,
   797  		Rect:   r,
   798  	}
   799  }
   800  
   801  // Opaque scans the entire image and reports whether it is fully opaque.
   802  func (p *Alpha16) Opaque() bool {
   803  	if p.Rect.Empty() {
   804  		return true
   805  	}
   806  	i0, i1 := 0, p.Rect.Dx()*2
   807  	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   808  		for i := i0; i < i1; i += 2 {
   809  			if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
   810  				return false
   811  			}
   812  		}
   813  		i0 += p.Stride
   814  		i1 += p.Stride
   815  	}
   816  	return true
   817  }
   818  
   819  // NewAlpha16 returns a new Alpha16 image with the given bounds.
   820  func NewAlpha16(r Rectangle) *Alpha16 {
   821  	return &Alpha16{
   822  		Pix:    make([]uint8, pixelBufferLength(2, r, "Alpha16")),
   823  		Stride: 2 * r.Dx(),
   824  		Rect:   r,
   825  	}
   826  }
   827  
   828  // Gray is an in-memory image whose At method returns color.Gray values.
   829  type Gray struct {
   830  	// Pix holds the image's pixels, as gray values. The pixel at
   831  	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
   832  	Pix []uint8
   833  	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   834  	Stride int
   835  	// Rect is the image's bounds.
   836  	Rect Rectangle
   837  }
   838  
   839  func (p *Gray) ColorModel() color.Model { return color.GrayModel }
   840  
   841  func (p *Gray) Bounds() Rectangle { return p.Rect }
   842  
   843  func (p *Gray) At(x, y int) color.Color {
   844  	return p.GrayAt(x, y)
   845  }
   846  
   847  func (p *Gray) RGBA64At(x, y int) color.RGBA64 {
   848  	gray := uint16(p.GrayAt(x, y).Y)
   849  	gray |= gray << 8
   850  	return color.RGBA64{gray, gray, gray, 0xffff}
   851  }
   852  
   853  func (p *Gray) GrayAt(x, y int) color.Gray {
   854  	if !(Point{x, y}.In(p.Rect)) {
   855  		return color.Gray{}
   856  	}
   857  	i := p.PixOffset(x, y)
   858  	return color.Gray{p.Pix[i]}
   859  }
   860  
   861  // PixOffset returns the index of the first element of Pix that corresponds to
   862  // the pixel at (x, y).
   863  func (p *Gray) PixOffset(x, y int) int {
   864  	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
   865  }
   866  
   867  func (p *Gray) Set(x, y int, c color.Color) {
   868  	if !(Point{x, y}.In(p.Rect)) {
   869  		return
   870  	}
   871  	i := p.PixOffset(x, y)
   872  	p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
   873  }
   874  
   875  func (p *Gray) SetRGBA64(x, y int, c color.RGBA64) {
   876  	if !(Point{x, y}.In(p.Rect)) {
   877  		return
   878  	}
   879  	// This formula is the same as in color.grayModel.
   880  	gray := (19595*uint32(c.R) + 38470*uint32(c.G) + 7471*uint32(c.B) + 1<<15) >> 24
   881  	i := p.PixOffset(x, y)
   882  	p.Pix[i] = uint8(gray)
   883  }
   884  
   885  func (p *Gray) SetGray(x, y int, c color.Gray) {
   886  	if !(Point{x, y}.In(p.Rect)) {
   887  		return
   888  	}
   889  	i := p.PixOffset(x, y)
   890  	p.Pix[i] = c.Y
   891  }
   892  
   893  // SubImage returns an image representing the portion of the image p visible
   894  // through r. The returned value shares pixels with the original image.
   895  func (p *Gray) SubImage(r Rectangle) Image {
   896  	r = r.Intersect(p.Rect)
   897  	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   898  	// either r1 or r2 if the intersection is empty. Without explicitly checking for
   899  	// this, the Pix[i:] expression below can panic.
   900  	if r.Empty() {
   901  		return &Gray{}
   902  	}
   903  	i := p.PixOffset(r.Min.X, r.Min.Y)
   904  	return &Gray{
   905  		Pix:    p.Pix[i:],
   906  		Stride: p.Stride,
   907  		Rect:   r,
   908  	}
   909  }
   910  
   911  // Opaque scans the entire image and reports whether it is fully opaque.
   912  func (p *Gray) Opaque() bool {
   913  	return true
   914  }
   915  
   916  // NewGray returns a new Gray image with the given bounds.
   917  func NewGray(r Rectangle) *Gray {
   918  	return &Gray{
   919  		Pix:    make([]uint8, pixelBufferLength(1, r, "Gray")),
   920  		Stride: 1 * r.Dx(),
   921  		Rect:   r,
   922  	}
   923  }
   924  
   925  // Gray16 is an in-memory image whose At method returns color.Gray16 values.
   926  type Gray16 struct {
   927  	// Pix holds the image's pixels, as gray values in big-endian format. The pixel at
   928  	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
   929  	Pix []uint8
   930  	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   931  	Stride int
   932  	// Rect is the image's bounds.
   933  	Rect Rectangle
   934  }
   935  
   936  func (p *Gray16) ColorModel() color.Model { return color.Gray16Model }
   937  
   938  func (p *Gray16) Bounds() Rectangle { return p.Rect }
   939  
   940  func (p *Gray16) At(x, y int) color.Color {
   941  	return p.Gray16At(x, y)
   942  }
   943  
   944  func (p *Gray16) RGBA64At(x, y int) color.RGBA64 {
   945  	gray := p.Gray16At(x, y).Y
   946  	return color.RGBA64{gray, gray, gray, 0xffff}
   947  }
   948  
   949  func (p *Gray16) Gray16At(x, y int) color.Gray16 {
   950  	if !(Point{x, y}.In(p.Rect)) {
   951  		return color.Gray16{}
   952  	}
   953  	i := p.PixOffset(x, y)
   954  	return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
   955  }
   956  
   957  // PixOffset returns the index of the first element of Pix that corresponds to
   958  // the pixel at (x, y).
   959  func (p *Gray16) PixOffset(x, y int) int {
   960  	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
   961  }
   962  
   963  func (p *Gray16) Set(x, y int, c color.Color) {
   964  	if !(Point{x, y}.In(p.Rect)) {
   965  		return
   966  	}
   967  	i := p.PixOffset(x, y)
   968  	c1 := color.Gray16Model.Convert(c).(color.Gray16)
   969  	p.Pix[i+0] = uint8(c1.Y >> 8)
   970  	p.Pix[i+1] = uint8(c1.Y)
   971  }
   972  
   973  func (p *Gray16) SetRGBA64(x, y int, c color.RGBA64) {
   974  	if !(Point{x, y}.In(p.Rect)) {
   975  		return
   976  	}
   977  	// This formula is the same as in color.gray16Model.
   978  	gray := (19595*uint32(c.R) + 38470*uint32(c.G) + 7471*uint32(c.B) + 1<<15) >> 16
   979  	i := p.PixOffset(x, y)
   980  	p.Pix[i+0] = uint8(gray >> 8)
   981  	p.Pix[i+1] = uint8(gray)
   982  }
   983  
   984  func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
   985  	if !(Point{x, y}.In(p.Rect)) {
   986  		return
   987  	}
   988  	i := p.PixOffset(x, y)
   989  	p.Pix[i+0] = uint8(c.Y >> 8)
   990  	p.Pix[i+1] = uint8(c.Y)
   991  }
   992  
   993  // SubImage returns an image representing the portion of the image p visible
   994  // through r. The returned value shares pixels with the original image.
   995  func (p *Gray16) SubImage(r Rectangle) Image {
   996  	r = r.Intersect(p.Rect)
   997  	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   998  	// either r1 or r2 if the intersection is empty. Without explicitly checking for
   999  	// this, the Pix[i:] expression below can panic.
  1000  	if r.Empty() {
  1001  		return &Gray16{}
  1002  	}
  1003  	i := p.PixOffset(r.Min.X, r.Min.Y)
  1004  	return &Gray16{
  1005  		Pix:    p.Pix[i:],
  1006  		Stride: p.Stride,
  1007  		Rect:   r,
  1008  	}
  1009  }
  1010  
  1011  // Opaque scans the entire image and reports whether it is fully opaque.
  1012  func (p *Gray16) Opaque() bool {
  1013  	return true
  1014  }
  1015  
  1016  // NewGray16 returns a new Gray16 image with the given bounds.
  1017  func NewGray16(r Rectangle) *Gray16 {
  1018  	return &Gray16{
  1019  		Pix:    make([]uint8, pixelBufferLength(2, r, "Gray16")),
  1020  		Stride: 2 * r.Dx(),
  1021  		Rect:   r,
  1022  	}
  1023  }
  1024  
  1025  // CMYK is an in-memory image whose At method returns color.CMYK values.
  1026  type CMYK struct {
  1027  	// Pix holds the image's pixels, in C, M, Y, K order. The pixel at
  1028  	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
  1029  	Pix []uint8
  1030  	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
  1031  	Stride int
  1032  	// Rect is the image's bounds.
  1033  	Rect Rectangle
  1034  }
  1035  
  1036  func (p *CMYK) ColorModel() color.Model { return color.CMYKModel }
  1037  
  1038  func (p *CMYK) Bounds() Rectangle { return p.Rect }
  1039  
  1040  func (p *CMYK) At(x, y int) color.Color {
  1041  	return p.CMYKAt(x, y)
  1042  }
  1043  
  1044  func (p *CMYK) RGBA64At(x, y int) color.RGBA64 {
  1045  	r, g, b, a := p.CMYKAt(x, y).RGBA()
  1046  	return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
  1047  }
  1048  
  1049  func (p *CMYK) CMYKAt(x, y int) color.CMYK {
  1050  	if !(Point{x, y}.In(p.Rect)) {
  1051  		return color.CMYK{}
  1052  	}
  1053  	i := p.PixOffset(x, y)
  1054  	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
  1055  	return color.CMYK{s[0], s[1], s[2], s[3]}
  1056  }
  1057  
  1058  // PixOffset returns the index of the first element of Pix that corresponds to
  1059  // the pixel at (x, y).
  1060  func (p *CMYK) PixOffset(x, y int) int {
  1061  	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
  1062  }
  1063  
  1064  func (p *CMYK) Set(x, y int, c color.Color) {
  1065  	if !(Point{x, y}.In(p.Rect)) {
  1066  		return
  1067  	}
  1068  	i := p.PixOffset(x, y)
  1069  	c1 := color.CMYKModel.Convert(c).(color.CMYK)
  1070  	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
  1071  	s[0] = c1.C
  1072  	s[1] = c1.M
  1073  	s[2] = c1.Y
  1074  	s[3] = c1.K
  1075  }
  1076  
  1077  func (p *CMYK) SetRGBA64(x, y int, c color.RGBA64) {
  1078  	if !(Point{x, y}.In(p.Rect)) {
  1079  		return
  1080  	}
  1081  	cc, mm, yy, kk := color.RGBToCMYK(uint8(c.R>>8), uint8(c.G>>8), uint8(c.B>>8))
  1082  	i := p.PixOffset(x, y)
  1083  	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
  1084  	s[0] = cc
  1085  	s[1] = mm
  1086  	s[2] = yy
  1087  	s[3] = kk
  1088  }
  1089  
  1090  func (p *CMYK) SetCMYK(x, y int, c color.CMYK) {
  1091  	if !(Point{x, y}.In(p.Rect)) {
  1092  		return
  1093  	}
  1094  	i := p.PixOffset(x, y)
  1095  	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
  1096  	s[0] = c.C
  1097  	s[1] = c.M
  1098  	s[2] = c.Y
  1099  	s[3] = c.K
  1100  }
  1101  
  1102  // SubImage returns an image representing the portion of the image p visible
  1103  // through r. The returned value shares pixels with the original image.
  1104  func (p *CMYK) SubImage(r Rectangle) Image {
  1105  	r = r.Intersect(p.Rect)
  1106  	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
  1107  	// either r1 or r2 if the intersection is empty. Without explicitly checking for
  1108  	// this, the Pix[i:] expression below can panic.
  1109  	if r.Empty() {
  1110  		return &CMYK{}
  1111  	}
  1112  	i := p.PixOffset(r.Min.X, r.Min.Y)
  1113  	return &CMYK{
  1114  		Pix:    p.Pix[i:],
  1115  		Stride: p.Stride,
  1116  		Rect:   r,
  1117  	}
  1118  }
  1119  
  1120  // Opaque scans the entire image and reports whether it is fully opaque.
  1121  func (p *CMYK) Opaque() bool {
  1122  	return true
  1123  }
  1124  
  1125  // NewCMYK returns a new CMYK image with the given bounds.
  1126  func NewCMYK(r Rectangle) *CMYK {
  1127  	return &CMYK{
  1128  		Pix:    make([]uint8, pixelBufferLength(4, r, "CMYK")),
  1129  		Stride: 4 * r.Dx(),
  1130  		Rect:   r,
  1131  	}
  1132  }
  1133  
  1134  // Paletted is an in-memory image of uint8 indices into a given palette.
  1135  type Paletted struct {
  1136  	// Pix holds the image's pixels, as palette indices. The pixel at
  1137  	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
  1138  	Pix []uint8
  1139  	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
  1140  	Stride int
  1141  	// Rect is the image's bounds.
  1142  	Rect Rectangle
  1143  	// Palette is the image's palette.
  1144  	Palette color.Palette
  1145  }
  1146  
  1147  func (p *Paletted) ColorModel() color.Model { return p.Palette }
  1148  
  1149  func (p *Paletted) Bounds() Rectangle { return p.Rect }
  1150  
  1151  func (p *Paletted) At(x, y int) color.Color {
  1152  	if len(p.Palette) == 0 {
  1153  		return nil
  1154  	}
  1155  	if !(Point{x, y}.In(p.Rect)) {
  1156  		return p.Palette[0]
  1157  	}
  1158  	i := p.PixOffset(x, y)
  1159  	return p.Palette[p.Pix[i]]
  1160  }
  1161  
  1162  func (p *Paletted) RGBA64At(x, y int) color.RGBA64 {
  1163  	if len(p.Palette) == 0 {
  1164  		return color.RGBA64{}
  1165  	}
  1166  	c := color.Color(nil)
  1167  	if !(Point{x, y}.In(p.Rect)) {
  1168  		c = p.Palette[0]
  1169  	} else {
  1170  		i := p.PixOffset(x, y)
  1171  		c = p.Palette[p.Pix[i]]
  1172  	}
  1173  	r, g, b, a := c.RGBA()
  1174  	return color.RGBA64{
  1175  		uint16(r),
  1176  		uint16(g),
  1177  		uint16(b),
  1178  		uint16(a),
  1179  	}
  1180  }
  1181  
  1182  // PixOffset returns the index of the first element of Pix that corresponds to
  1183  // the pixel at (x, y).
  1184  func (p *Paletted) PixOffset(x, y int) int {
  1185  	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
  1186  }
  1187  
  1188  func (p *Paletted) Set(x, y int, c color.Color) {
  1189  	if !(Point{x, y}.In(p.Rect)) {
  1190  		return
  1191  	}
  1192  	i := p.PixOffset(x, y)
  1193  	p.Pix[i] = uint8(p.Palette.Index(c))
  1194  }
  1195  
  1196  func (p *Paletted) SetRGBA64(x, y int, c color.RGBA64) {
  1197  	if !(Point{x, y}.In(p.Rect)) {
  1198  		return
  1199  	}
  1200  	i := p.PixOffset(x, y)
  1201  	p.Pix[i] = uint8(p.Palette.Index(c))
  1202  }
  1203  
  1204  func (p *Paletted) ColorIndexAt(x, y int) uint8 {
  1205  	if !(Point{x, y}.In(p.Rect)) {
  1206  		return 0
  1207  	}
  1208  	i := p.PixOffset(x, y)
  1209  	return p.Pix[i]
  1210  }
  1211  
  1212  func (p *Paletted) SetColorIndex(x, y int, index uint8) {
  1213  	if !(Point{x, y}.In(p.Rect)) {
  1214  		return
  1215  	}
  1216  	i := p.PixOffset(x, y)
  1217  	p.Pix[i] = index
  1218  }
  1219  
  1220  // SubImage returns an image representing the portion of the image p visible
  1221  // through r. The returned value shares pixels with the original image.
  1222  func (p *Paletted) SubImage(r Rectangle) Image {
  1223  	r = r.Intersect(p.Rect)
  1224  	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
  1225  	// either r1 or r2 if the intersection is empty. Without explicitly checking for
  1226  	// this, the Pix[i:] expression below can panic.
  1227  	if r.Empty() {
  1228  		return &Paletted{
  1229  			Palette: p.Palette,
  1230  		}
  1231  	}
  1232  	i := p.PixOffset(r.Min.X, r.Min.Y)
  1233  	return &Paletted{
  1234  		Pix:     p.Pix[i:],
  1235  		Stride:  p.Stride,
  1236  		Rect:    p.Rect.Intersect(r),
  1237  		Palette: p.Palette,
  1238  	}
  1239  }
  1240  
  1241  // Opaque scans the entire image and reports whether it is fully opaque.
  1242  func (p *Paletted) Opaque() bool {
  1243  	var present [256]bool
  1244  	i0, i1 := 0, p.Rect.Dx()
  1245  	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
  1246  		for _, c := range p.Pix[i0:i1] {
  1247  			present[c] = true
  1248  		}
  1249  		i0 += p.Stride
  1250  		i1 += p.Stride
  1251  	}
  1252  	for i, c := range p.Palette {
  1253  		if !present[i] {
  1254  			continue
  1255  		}
  1256  		_, _, _, a := c.RGBA()
  1257  		if a != 0xffff {
  1258  			return false
  1259  		}
  1260  	}
  1261  	return true
  1262  }
  1263  
  1264  // NewPaletted returns a new Paletted image with the given width, height and
  1265  // palette.
  1266  func NewPaletted(r Rectangle, p color.Palette) *Paletted {
  1267  	return &Paletted{
  1268  		Pix:     make([]uint8, pixelBufferLength(1, r, "Paletted")),
  1269  		Stride:  1 * r.Dx(),
  1270  		Rect:    r,
  1271  		Palette: p,
  1272  	}
  1273  }
  1274  

View as plain text