...
Run Format

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

View as plain text