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