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