Black Lives Matter. Support the Equal Justice Initiative.

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

View as plain text