The Go Programming Language

Source file src/pkg/image/image.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// Package image implements a basic 2-D image library.
     6	//
     7	// See "The Go image package" for an introduction to this package:
     8	// http://blog.golang.org/2011/09/go-image-package.html
     9	package image
    10	
    11	// Config holds an image's color model and dimensions.
    12	type Config struct {
    13		ColorModel    ColorModel
    14		Width, Height int
    15	}
    16	
    17	// Image is a finite rectangular grid of Colors drawn from a ColorModel.
    18	type Image interface {
    19		// ColorModel returns the Image's ColorModel.
    20		ColorModel() ColorModel
    21		// Bounds returns the domain for which At can return non-zero color.
    22		// The bounds do not necessarily contain the point (0, 0).
    23		Bounds() Rectangle
    24		// At returns the color of the pixel at (x, y).
    25		// At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
    26		// At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
    27		At(x, y int) Color
    28	}
    29	
    30	// RGBA is an in-memory image of RGBAColor values.
    31	type RGBA struct {
    32		// Pix holds the image's pixels, in R, G, B, A order. The pixel at
    33		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
    34		Pix []uint8
    35		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
    36		Stride int
    37		// Rect is the image's bounds.
    38		Rect Rectangle
    39	}
    40	
    41	func (p *RGBA) ColorModel() ColorModel { return RGBAColorModel }
    42	
    43	func (p *RGBA) Bounds() Rectangle { return p.Rect }
    44	
    45	func (p *RGBA) At(x, y int) Color {
    46		if !(Point{x, y}.In(p.Rect)) {
    47			return RGBAColor{}
    48		}
    49		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
    50		return RGBAColor{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
    51	}
    52	
    53	func (p *RGBA) Set(x, y int, c Color) {
    54		if !(Point{x, y}.In(p.Rect)) {
    55			return
    56		}
    57		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
    58		c1 := toRGBAColor(c).(RGBAColor)
    59		p.Pix[i+0] = c1.R
    60		p.Pix[i+1] = c1.G
    61		p.Pix[i+2] = c1.B
    62		p.Pix[i+3] = c1.A
    63	}
    64	
    65	func (p *RGBA) SetRGBA(x, y int, c RGBAColor) {
    66		if !(Point{x, y}.In(p.Rect)) {
    67			return
    68		}
    69		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
    70		p.Pix[i+0] = c.R
    71		p.Pix[i+1] = c.G
    72		p.Pix[i+2] = c.B
    73		p.Pix[i+3] = c.A
    74	}
    75	
    76	// SubImage returns an image representing the portion of the image p visible
    77	// through r. The returned value shares pixels with the original image.
    78	func (p *RGBA) SubImage(r Rectangle) Image {
    79		r = r.Intersect(p.Rect)
    80		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
    81		// either r1 or r2 if the intersection is empty. Without explicitly checking for
    82		// this, the Pix[i:] expression below can panic.
    83		if r.Empty() {
    84			return &RGBA{}
    85		}
    86		i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*4
    87		return &RGBA{
    88			Pix:    p.Pix[i:],
    89			Stride: p.Stride,
    90			Rect:   r,
    91		}
    92	}
    93	
    94	// Opaque scans the entire image and returns whether or not it is fully opaque.
    95	func (p *RGBA) Opaque() bool {
    96		if p.Rect.Empty() {
    97			return true
    98		}
    99		i0, i1 := 3, p.Rect.Dx()*4
   100		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   101			for i := i0; i < i1; i += 4 {
   102				if p.Pix[i] != 0xff {
   103					return false
   104				}
   105			}
   106			i0 += p.Stride
   107			i1 += p.Stride
   108		}
   109		return true
   110	}
   111	
   112	// NewRGBA returns a new RGBA with the given width and height.
   113	func NewRGBA(w, h int) *RGBA {
   114		buf := make([]uint8, 4*w*h)
   115		return &RGBA{buf, 4 * w, Rectangle{ZP, Point{w, h}}}
   116	}
   117	
   118	// RGBA64 is an in-memory image of RGBA64Color values.
   119	type RGBA64 struct {
   120		// Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
   121		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
   122		Pix []uint8
   123		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   124		Stride int
   125		// Rect is the image's bounds.
   126		Rect Rectangle
   127	}
   128	
   129	func (p *RGBA64) ColorModel() ColorModel { return RGBA64ColorModel }
   130	
   131	func (p *RGBA64) Bounds() Rectangle { return p.Rect }
   132	
   133	func (p *RGBA64) At(x, y int) Color {
   134		if !(Point{x, y}.In(p.Rect)) {
   135			return RGBA64Color{}
   136		}
   137		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
   138		return RGBA64Color{
   139			uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
   140			uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
   141			uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
   142			uint16(p.Pix[i+6])<<8 | uint16(p.Pix[i+7]),
   143		}
   144	}
   145	
   146	func (p *RGBA64) Set(x, y int, c Color) {
   147		if !(Point{x, y}.In(p.Rect)) {
   148			return
   149		}
   150		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
   151		c1 := toRGBA64Color(c).(RGBA64Color)
   152		p.Pix[i+0] = uint8(c1.R >> 8)
   153		p.Pix[i+1] = uint8(c1.R)
   154		p.Pix[i+2] = uint8(c1.G >> 8)
   155		p.Pix[i+3] = uint8(c1.G)
   156		p.Pix[i+4] = uint8(c1.B >> 8)
   157		p.Pix[i+5] = uint8(c1.B)
   158		p.Pix[i+6] = uint8(c1.A >> 8)
   159		p.Pix[i+7] = uint8(c1.A)
   160	}
   161	
   162	func (p *RGBA64) SetRGBA64(x, y int, c RGBA64Color) {
   163		if !(Point{x, y}.In(p.Rect)) {
   164			return
   165		}
   166		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
   167		p.Pix[i+0] = uint8(c.R >> 8)
   168		p.Pix[i+1] = uint8(c.R)
   169		p.Pix[i+2] = uint8(c.G >> 8)
   170		p.Pix[i+3] = uint8(c.G)
   171		p.Pix[i+4] = uint8(c.B >> 8)
   172		p.Pix[i+5] = uint8(c.B)
   173		p.Pix[i+6] = uint8(c.A >> 8)
   174		p.Pix[i+7] = uint8(c.A)
   175	}
   176	
   177	// SubImage returns an image representing the portion of the image p visible
   178	// through r. The returned value shares pixels with the original image.
   179	func (p *RGBA64) SubImage(r Rectangle) Image {
   180		r = r.Intersect(p.Rect)
   181		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   182		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   183		// this, the Pix[i:] expression below can panic.
   184		if r.Empty() {
   185			return &RGBA64{}
   186		}
   187		i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*8
   188		return &RGBA64{
   189			Pix:    p.Pix[i:],
   190			Stride: p.Stride,
   191			Rect:   r,
   192		}
   193	}
   194	
   195	// Opaque scans the entire image and returns whether or not it is fully opaque.
   196	func (p *RGBA64) Opaque() bool {
   197		if p.Rect.Empty() {
   198			return true
   199		}
   200		i0, i1 := 6, p.Rect.Dx()*8
   201		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   202			for i := i0; i < i1; i += 8 {
   203				if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
   204					return false
   205				}
   206			}
   207			i0 += p.Stride
   208			i1 += p.Stride
   209		}
   210		return true
   211	}
   212	
   213	// NewRGBA64 returns a new RGBA64 with the given width and height.
   214	func NewRGBA64(w, h int) *RGBA64 {
   215		pix := make([]uint8, 8*w*h)
   216		return &RGBA64{pix, 8 * w, Rectangle{ZP, Point{w, h}}}
   217	}
   218	
   219	// NRGBA is an in-memory image of NRGBAColor values.
   220	type NRGBA struct {
   221		// Pix holds the image's pixels, in R, G, B, A order. The pixel at
   222		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
   223		Pix []uint8
   224		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   225		Stride int
   226		// Rect is the image's bounds.
   227		Rect Rectangle
   228	}
   229	
   230	func (p *NRGBA) ColorModel() ColorModel { return NRGBAColorModel }
   231	
   232	func (p *NRGBA) Bounds() Rectangle { return p.Rect }
   233	
   234	func (p *NRGBA) At(x, y int) Color {
   235		if !(Point{x, y}.In(p.Rect)) {
   236			return NRGBAColor{}
   237		}
   238		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
   239		return NRGBAColor{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
   240	}
   241	
   242	func (p *NRGBA) Set(x, y int, c Color) {
   243		if !(Point{x, y}.In(p.Rect)) {
   244			return
   245		}
   246		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
   247		c1 := toNRGBAColor(c).(NRGBAColor)
   248		p.Pix[i+0] = c1.R
   249		p.Pix[i+1] = c1.G
   250		p.Pix[i+2] = c1.B
   251		p.Pix[i+3] = c1.A
   252	}
   253	
   254	func (p *NRGBA) SetNRGBA(x, y int, c NRGBAColor) {
   255		if !(Point{x, y}.In(p.Rect)) {
   256			return
   257		}
   258		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
   259		p.Pix[i+0] = c.R
   260		p.Pix[i+1] = c.G
   261		p.Pix[i+2] = c.B
   262		p.Pix[i+3] = c.A
   263	}
   264	
   265	// SubImage returns an image representing the portion of the image p visible
   266	// through r. The returned value shares pixels with the original image.
   267	func (p *NRGBA) SubImage(r Rectangle) Image {
   268		r = r.Intersect(p.Rect)
   269		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   270		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   271		// this, the Pix[i:] expression below can panic.
   272		if r.Empty() {
   273			return &NRGBA{}
   274		}
   275		i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*4
   276		return &NRGBA{
   277			Pix:    p.Pix[i:],
   278			Stride: p.Stride,
   279			Rect:   r,
   280		}
   281	}
   282	
   283	// Opaque scans the entire image and returns whether or not it is fully opaque.
   284	func (p *NRGBA) Opaque() bool {
   285		if p.Rect.Empty() {
   286			return true
   287		}
   288		i0, i1 := 3, p.Rect.Dx()*4
   289		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   290			for i := i0; i < i1; i += 4 {
   291				if p.Pix[i] != 0xff {
   292					return false
   293				}
   294			}
   295			i0 += p.Stride
   296			i1 += p.Stride
   297		}
   298		return true
   299	}
   300	
   301	// NewNRGBA returns a new NRGBA with the given width and height.
   302	func NewNRGBA(w, h int) *NRGBA {
   303		pix := make([]uint8, 4*w*h)
   304		return &NRGBA{pix, 4 * w, Rectangle{ZP, Point{w, h}}}
   305	}
   306	
   307	// NRGBA64 is an in-memory image of NRGBA64Color values.
   308	type NRGBA64 struct {
   309		// Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
   310		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
   311		Pix []uint8
   312		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   313		Stride int
   314		// Rect is the image's bounds.
   315		Rect Rectangle
   316	}
   317	
   318	func (p *NRGBA64) ColorModel() ColorModel { return NRGBA64ColorModel }
   319	
   320	func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
   321	
   322	func (p *NRGBA64) At(x, y int) Color {
   323		if !(Point{x, y}.In(p.Rect)) {
   324			return NRGBA64Color{}
   325		}
   326		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
   327		return NRGBA64Color{
   328			uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
   329			uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
   330			uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
   331			uint16(p.Pix[i+6])<<8 | uint16(p.Pix[i+7]),
   332		}
   333	}
   334	
   335	func (p *NRGBA64) Set(x, y int, c Color) {
   336		if !(Point{x, y}.In(p.Rect)) {
   337			return
   338		}
   339		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
   340		c1 := toNRGBA64Color(c).(NRGBA64Color)
   341		p.Pix[i+0] = uint8(c1.R >> 8)
   342		p.Pix[i+1] = uint8(c1.R)
   343		p.Pix[i+2] = uint8(c1.G >> 8)
   344		p.Pix[i+3] = uint8(c1.G)
   345		p.Pix[i+4] = uint8(c1.B >> 8)
   346		p.Pix[i+5] = uint8(c1.B)
   347		p.Pix[i+6] = uint8(c1.A >> 8)
   348		p.Pix[i+7] = uint8(c1.A)
   349	}
   350	
   351	func (p *NRGBA64) SetNRGBA64(x, y int, c NRGBA64Color) {
   352		if !(Point{x, y}.In(p.Rect)) {
   353			return
   354		}
   355		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
   356		p.Pix[i+0] = uint8(c.R >> 8)
   357		p.Pix[i+1] = uint8(c.R)
   358		p.Pix[i+2] = uint8(c.G >> 8)
   359		p.Pix[i+3] = uint8(c.G)
   360		p.Pix[i+4] = uint8(c.B >> 8)
   361		p.Pix[i+5] = uint8(c.B)
   362		p.Pix[i+6] = uint8(c.A >> 8)
   363		p.Pix[i+7] = uint8(c.A)
   364	}
   365	
   366	// SubImage returns an image representing the portion of the image p visible
   367	// through r. The returned value shares pixels with the original image.
   368	func (p *NRGBA64) SubImage(r Rectangle) Image {
   369		r = r.Intersect(p.Rect)
   370		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   371		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   372		// this, the Pix[i:] expression below can panic.
   373		if r.Empty() {
   374			return &NRGBA64{}
   375		}
   376		i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*8
   377		return &NRGBA64{
   378			Pix:    p.Pix[i:],
   379			Stride: p.Stride,
   380			Rect:   r,
   381		}
   382	}
   383	
   384	// Opaque scans the entire image and returns whether or not it is fully opaque.
   385	func (p *NRGBA64) Opaque() bool {
   386		if p.Rect.Empty() {
   387			return true
   388		}
   389		i0, i1 := 6, p.Rect.Dx()*8
   390		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   391			for i := i0; i < i1; i += 8 {
   392				if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
   393					return false
   394				}
   395			}
   396			i0 += p.Stride
   397			i1 += p.Stride
   398		}
   399		return true
   400	}
   401	
   402	// NewNRGBA64 returns a new NRGBA64 with the given width and height.
   403	func NewNRGBA64(w, h int) *NRGBA64 {
   404		pix := make([]uint8, 8*w*h)
   405		return &NRGBA64{pix, 8 * w, Rectangle{ZP, Point{w, h}}}
   406	}
   407	
   408	// Alpha is an in-memory image of AlphaColor values.
   409	type Alpha struct {
   410		// Pix holds the image's pixels, as alpha values. The pixel at
   411		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
   412		Pix []uint8
   413		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   414		Stride int
   415		// Rect is the image's bounds.
   416		Rect Rectangle
   417	}
   418	
   419	func (p *Alpha) ColorModel() ColorModel { return AlphaColorModel }
   420	
   421	func (p *Alpha) Bounds() Rectangle { return p.Rect }
   422	
   423	func (p *Alpha) At(x, y int) Color {
   424		if !(Point{x, y}.In(p.Rect)) {
   425			return AlphaColor{}
   426		}
   427		i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
   428		return AlphaColor{p.Pix[i]}
   429	}
   430	
   431	func (p *Alpha) Set(x, y int, c Color) {
   432		if !(Point{x, y}.In(p.Rect)) {
   433			return
   434		}
   435		i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
   436		p.Pix[i] = toAlphaColor(c).(AlphaColor).A
   437	}
   438	
   439	func (p *Alpha) SetAlpha(x, y int, c AlphaColor) {
   440		if !(Point{x, y}.In(p.Rect)) {
   441			return
   442		}
   443		i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
   444		p.Pix[i] = c.A
   445	}
   446	
   447	// SubImage returns an image representing the portion of the image p visible
   448	// through r. The returned value shares pixels with the original image.
   449	func (p *Alpha) SubImage(r Rectangle) Image {
   450		r = r.Intersect(p.Rect)
   451		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   452		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   453		// this, the Pix[i:] expression below can panic.
   454		if r.Empty() {
   455			return &Alpha{}
   456		}
   457		i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*1
   458		return &Alpha{
   459			Pix:    p.Pix[i:],
   460			Stride: p.Stride,
   461			Rect:   r,
   462		}
   463	}
   464	
   465	// Opaque scans the entire image and returns whether or not it is fully opaque.
   466	func (p *Alpha) Opaque() bool {
   467		if p.Rect.Empty() {
   468			return true
   469		}
   470		i0, i1 := 0, p.Rect.Dx()
   471		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   472			for i := i0; i < i1; i++ {
   473				if p.Pix[i] != 0xff {
   474					return false
   475				}
   476			}
   477			i0 += p.Stride
   478			i1 += p.Stride
   479		}
   480		return true
   481	}
   482	
   483	// NewAlpha returns a new Alpha with the given width and height.
   484	func NewAlpha(w, h int) *Alpha {
   485		pix := make([]uint8, 1*w*h)
   486		return &Alpha{pix, 1 * w, Rectangle{ZP, Point{w, h}}}
   487	}
   488	
   489	// Alpha16 is an in-memory image of Alpha16Color values.
   490	type Alpha16 struct {
   491		// Pix holds the image's pixels, as alpha values in big-endian format. The pixel at
   492		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
   493		Pix []uint8
   494		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   495		Stride int
   496		// Rect is the image's bounds.
   497		Rect Rectangle
   498	}
   499	
   500	func (p *Alpha16) ColorModel() ColorModel { return Alpha16ColorModel }
   501	
   502	func (p *Alpha16) Bounds() Rectangle { return p.Rect }
   503	
   504	func (p *Alpha16) At(x, y int) Color {
   505		if !(Point{x, y}.In(p.Rect)) {
   506			return Alpha16Color{}
   507		}
   508		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
   509		return Alpha16Color{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
   510	}
   511	
   512	func (p *Alpha16) Set(x, y int, c Color) {
   513		if !(Point{x, y}.In(p.Rect)) {
   514			return
   515		}
   516		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
   517		c1 := toAlpha16Color(c).(Alpha16Color)
   518		p.Pix[i+0] = uint8(c1.A >> 8)
   519		p.Pix[i+1] = uint8(c1.A)
   520	}
   521	
   522	func (p *Alpha16) SetAlpha16(x, y int, c Alpha16Color) {
   523		if !(Point{x, y}.In(p.Rect)) {
   524			return
   525		}
   526		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
   527		p.Pix[i+0] = uint8(c.A >> 8)
   528		p.Pix[i+1] = uint8(c.A)
   529	}
   530	
   531	// SubImage returns an image representing the portion of the image p visible
   532	// through r. The returned value shares pixels with the original image.
   533	func (p *Alpha16) SubImage(r Rectangle) Image {
   534		r = r.Intersect(p.Rect)
   535		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   536		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   537		// this, the Pix[i:] expression below can panic.
   538		if r.Empty() {
   539			return &Alpha16{}
   540		}
   541		i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*2
   542		return &Alpha16{
   543			Pix:    p.Pix[i:],
   544			Stride: p.Stride,
   545			Rect:   r,
   546		}
   547	}
   548	
   549	// Opaque scans the entire image and returns whether or not it is fully opaque.
   550	func (p *Alpha16) Opaque() bool {
   551		if p.Rect.Empty() {
   552			return true
   553		}
   554		i0, i1 := 0, p.Rect.Dx()*2
   555		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   556			for i := i0; i < i1; i += 2 {
   557				if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
   558					return false
   559				}
   560			}
   561			i0 += p.Stride
   562			i1 += p.Stride
   563		}
   564		return true
   565	}
   566	
   567	// NewAlpha16 returns a new Alpha16 with the given width and height.
   568	func NewAlpha16(w, h int) *Alpha16 {
   569		pix := make([]uint8, 2*w*h)
   570		return &Alpha16{pix, 2 * w, Rectangle{ZP, Point{w, h}}}
   571	}
   572	
   573	// Gray is an in-memory image of GrayColor values.
   574	type Gray struct {
   575		// Pix holds the image's pixels, as gray values. The pixel at
   576		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
   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 *Gray) ColorModel() ColorModel { return GrayColorModel }
   585	
   586	func (p *Gray) Bounds() Rectangle { return p.Rect }
   587	
   588	func (p *Gray) At(x, y int) Color {
   589		if !(Point{x, y}.In(p.Rect)) {
   590			return GrayColor{}
   591		}
   592		i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
   593		return GrayColor{p.Pix[i]}
   594	}
   595	
   596	func (p *Gray) Set(x, y int, c Color) {
   597		if !(Point{x, y}.In(p.Rect)) {
   598			return
   599		}
   600		i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
   601		p.Pix[i] = toGrayColor(c).(GrayColor).Y
   602	}
   603	
   604	func (p *Gray) SetGray(x, y int, c GrayColor) {
   605		if !(Point{x, y}.In(p.Rect)) {
   606			return
   607		}
   608		i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
   609		p.Pix[i] = c.Y
   610	}
   611	
   612	// SubImage returns an image representing the portion of the image p visible
   613	// through r. The returned value shares pixels with the original image.
   614	func (p *Gray) SubImage(r Rectangle) Image {
   615		r = r.Intersect(p.Rect)
   616		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   617		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   618		// this, the Pix[i:] expression below can panic.
   619		if r.Empty() {
   620			return &Gray{}
   621		}
   622		i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*1
   623		return &Gray{
   624			Pix:    p.Pix[i:],
   625			Stride: p.Stride,
   626			Rect:   r,
   627		}
   628	}
   629	
   630	// Opaque scans the entire image and returns whether or not it is fully opaque.
   631	func (p *Gray) Opaque() bool {
   632		return true
   633	}
   634	
   635	// NewGray returns a new Gray with the given width and height.
   636	func NewGray(w, h int) *Gray {
   637		pix := make([]uint8, 1*w*h)
   638		return &Gray{pix, 1 * w, Rectangle{ZP, Point{w, h}}}
   639	}
   640	
   641	// Gray16 is an in-memory image of Gray16Color values.
   642	type Gray16 struct {
   643		// Pix holds the image's pixels, as gray values in big-endian format. The pixel at
   644		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
   645		Pix []uint8
   646		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   647		Stride int
   648		// Rect is the image's bounds.
   649		Rect Rectangle
   650	}
   651	
   652	func (p *Gray16) ColorModel() ColorModel { return Gray16ColorModel }
   653	
   654	func (p *Gray16) Bounds() Rectangle { return p.Rect }
   655	
   656	func (p *Gray16) At(x, y int) Color {
   657		if !(Point{x, y}.In(p.Rect)) {
   658			return Gray16Color{}
   659		}
   660		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
   661		return Gray16Color{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
   662	}
   663	
   664	func (p *Gray16) Set(x, y int, c Color) {
   665		if !(Point{x, y}.In(p.Rect)) {
   666			return
   667		}
   668		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
   669		c1 := toGray16Color(c).(Gray16Color)
   670		p.Pix[i+0] = uint8(c1.Y >> 8)
   671		p.Pix[i+1] = uint8(c1.Y)
   672	}
   673	
   674	func (p *Gray16) SetGray16(x, y int, c Gray16Color) {
   675		if !(Point{x, y}.In(p.Rect)) {
   676			return
   677		}
   678		i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
   679		p.Pix[i+0] = uint8(c.Y >> 8)
   680		p.Pix[i+1] = uint8(c.Y)
   681	}
   682	
   683	// SubImage returns an image representing the portion of the image p visible
   684	// through r. The returned value shares pixels with the original image.
   685	func (p *Gray16) SubImage(r Rectangle) Image {
   686		r = r.Intersect(p.Rect)
   687		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   688		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   689		// this, the Pix[i:] expression below can panic.
   690		if r.Empty() {
   691			return &Gray16{}
   692		}
   693		i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*2
   694		return &Gray16{
   695			Pix:    p.Pix[i:],
   696			Stride: p.Stride,
   697			Rect:   r,
   698		}
   699	}
   700	
   701	// Opaque scans the entire image and returns whether or not it is fully opaque.
   702	func (p *Gray16) Opaque() bool {
   703		return true
   704	}
   705	
   706	// NewGray16 returns a new Gray16 with the given width and height.
   707	func NewGray16(w, h int) *Gray16 {
   708		pix := make([]uint8, 2*w*h)
   709		return &Gray16{pix, 2 * w, Rectangle{ZP, Point{w, h}}}
   710	}
   711	
   712	// A PalettedColorModel represents a fixed palette of at most 256 colors.
   713	type PalettedColorModel []Color
   714	
   715	func diff(a, b uint32) uint32 {
   716		if a > b {
   717			return a - b
   718		}
   719		return b - a
   720	}
   721	
   722	// Convert returns the palette color closest to c in Euclidean R,G,B space.
   723	func (p PalettedColorModel) Convert(c Color) Color {
   724		if len(p) == 0 {
   725			return nil
   726		}
   727		return p[p.Index(c)]
   728	}
   729	
   730	// Index returns the index of the palette color closest to c in Euclidean
   731	// R,G,B space.
   732	func (p PalettedColorModel) Index(c Color) int {
   733		cr, cg, cb, _ := c.RGBA()
   734		// Shift by 1 bit to avoid potential uint32 overflow in sum-squared-difference.
   735		cr >>= 1
   736		cg >>= 1
   737		cb >>= 1
   738		ret, bestSSD := 0, uint32(1<<32-1)
   739		for i, v := range p {
   740			vr, vg, vb, _ := v.RGBA()
   741			vr >>= 1
   742			vg >>= 1
   743			vb >>= 1
   744			dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb)
   745			ssd := (dr * dr) + (dg * dg) + (db * db)
   746			if ssd < bestSSD {
   747				ret, bestSSD = i, ssd
   748			}
   749		}
   750		return ret
   751	}
   752	
   753	// Paletted is an in-memory image of uint8 indices into a given palette.
   754	type Paletted struct {
   755		// Pix holds the image's pixels, as palette indices. The pixel at
   756		// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
   757		Pix []uint8
   758		// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
   759		Stride int
   760		// Rect is the image's bounds.
   761		Rect Rectangle
   762		// Palette is the image's palette.
   763		Palette PalettedColorModel
   764	}
   765	
   766	func (p *Paletted) ColorModel() ColorModel { return p.Palette }
   767	
   768	func (p *Paletted) Bounds() Rectangle { return p.Rect }
   769	
   770	func (p *Paletted) At(x, y int) Color {
   771		if len(p.Palette) == 0 {
   772			return nil
   773		}
   774		if !(Point{x, y}.In(p.Rect)) {
   775			return p.Palette[0]
   776		}
   777		i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
   778		return p.Palette[p.Pix[i]]
   779	}
   780	
   781	func (p *Paletted) Set(x, y int, c Color) {
   782		if !(Point{x, y}.In(p.Rect)) {
   783			return
   784		}
   785		i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
   786		p.Pix[i] = uint8(p.Palette.Index(c))
   787	}
   788	
   789	func (p *Paletted) ColorIndexAt(x, y int) uint8 {
   790		if !(Point{x, y}.In(p.Rect)) {
   791			return 0
   792		}
   793		i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
   794		return p.Pix[i]
   795	}
   796	
   797	func (p *Paletted) SetColorIndex(x, y int, index uint8) {
   798		if !(Point{x, y}.In(p.Rect)) {
   799			return
   800		}
   801		i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
   802		p.Pix[i] = index
   803	}
   804	
   805	// SubImage returns an image representing the portion of the image p visible
   806	// through r. The returned value shares pixels with the original image.
   807	func (p *Paletted) SubImage(r Rectangle) Image {
   808		r = r.Intersect(p.Rect)
   809		// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
   810		// either r1 or r2 if the intersection is empty. Without explicitly checking for
   811		// this, the Pix[i:] expression below can panic.
   812		if r.Empty() {
   813			return &Paletted{
   814				Palette: p.Palette,
   815			}
   816		}
   817		i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*1
   818		return &Paletted{
   819			Pix:     p.Pix[i:],
   820			Stride:  p.Stride,
   821			Rect:    p.Rect.Intersect(r),
   822			Palette: p.Palette,
   823		}
   824	}
   825	
   826	// Opaque scans the entire image and returns whether or not it is fully opaque.
   827	func (p *Paletted) Opaque() bool {
   828		var present [256]bool
   829		i0, i1 := 0, p.Rect.Dx()
   830		for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
   831			for _, c := range p.Pix[i0:i1] {
   832				present[c] = true
   833			}
   834			i0 += p.Stride
   835			i1 += p.Stride
   836		}
   837		for i, c := range p.Palette {
   838			if !present[i] {
   839				continue
   840			}
   841			_, _, _, a := c.RGBA()
   842			if a != 0xffff {
   843				return false
   844			}
   845		}
   846		return true
   847	}
   848	
   849	// NewPaletted returns a new Paletted with the given width, height and palette.
   850	func NewPaletted(w, h int, m PalettedColorModel) *Paletted {
   851		pix := make([]uint8, 1*w*h)
   852		return &Paletted{pix, 1 * w, Rectangle{ZP, Point{w, h}}, m}
   853	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.