...

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

View as plain text