Home | History | Annotate | Download | only in 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