github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/image/image.go (about) 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 }