github.com/comwrg/go/src@v0.0.0-20220319063731-c238d0440370/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 // RGBA64Image is an Image whose pixels can be converted directly to a 49 // color.RGBA64. 50 type RGBA64Image interface { 51 // RGBA64At returns the RGBA64 color of the pixel at (x, y). It is 52 // equivalent to calling At(x, y).RGBA() and converting the resulting 53 // 32-bit return values to a color.RGBA64, but it can avoid allocations 54 // from converting concrete color types to the color.Color interface type. 55 RGBA64At(x, y int) color.RGBA64 56 Image 57 } 58 59 // PalettedImage is an image whose colors may come from a limited palette. 60 // If m is a PalettedImage and m.ColorModel() returns a color.Palette p, 61 // then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's 62 // color model is not a color.Palette, then ColorIndexAt's behavior is 63 // undefined. 64 type PalettedImage interface { 65 // ColorIndexAt returns the palette index of the pixel at (x, y). 66 ColorIndexAt(x, y int) uint8 67 Image 68 } 69 70 // pixelBufferLength returns the length of the []uint8 typed Pix slice field 71 // for the NewXxx functions. Conceptually, this is just (bpp * width * height), 72 // but this function panics if at least one of those is negative or if the 73 // computation would overflow the int type. 74 // 75 // This panics instead of returning an error because of backwards 76 // compatibility. The NewXxx functions do not return an error. 77 func pixelBufferLength(bytesPerPixel int, r Rectangle, imageTypeName string) int { 78 totalLength := mul3NonNeg(bytesPerPixel, r.Dx(), r.Dy()) 79 if totalLength < 0 { 80 panic("image: New" + imageTypeName + " Rectangle has huge or negative dimensions") 81 } 82 return totalLength 83 } 84 85 // RGBA is an in-memory image whose At method returns color.RGBA values. 86 type RGBA struct { 87 // Pix holds the image's pixels, in R, G, B, A order. The pixel at 88 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4]. 89 Pix []uint8 90 // Stride is the Pix stride (in bytes) between vertically adjacent pixels. 91 Stride int 92 // Rect is the image's bounds. 93 Rect Rectangle 94 } 95 96 func (p *RGBA) ColorModel() color.Model { return color.RGBAModel } 97 98 func (p *RGBA) Bounds() Rectangle { return p.Rect } 99 100 func (p *RGBA) At(x, y int) color.Color { 101 return p.RGBAAt(x, y) 102 } 103 104 func (p *RGBA) RGBA64At(x, y int) color.RGBA64 { 105 if !(Point{x, y}.In(p.Rect)) { 106 return color.RGBA64{} 107 } 108 i := p.PixOffset(x, y) 109 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 110 r := uint16(s[0]) 111 g := uint16(s[1]) 112 b := uint16(s[2]) 113 a := uint16(s[3]) 114 return color.RGBA64{ 115 (r << 8) | r, 116 (g << 8) | g, 117 (b << 8) | b, 118 (a << 8) | a, 119 } 120 } 121 122 func (p *RGBA) RGBAAt(x, y int) color.RGBA { 123 if !(Point{x, y}.In(p.Rect)) { 124 return color.RGBA{} 125 } 126 i := p.PixOffset(x, y) 127 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 128 return color.RGBA{s[0], s[1], s[2], s[3]} 129 } 130 131 // PixOffset returns the index of the first element of Pix that corresponds to 132 // the pixel at (x, y). 133 func (p *RGBA) PixOffset(x, y int) int { 134 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4 135 } 136 137 func (p *RGBA) Set(x, y int, c color.Color) { 138 if !(Point{x, y}.In(p.Rect)) { 139 return 140 } 141 i := p.PixOffset(x, y) 142 c1 := color.RGBAModel.Convert(c).(color.RGBA) 143 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 144 s[0] = c1.R 145 s[1] = c1.G 146 s[2] = c1.B 147 s[3] = c1.A 148 } 149 150 func (p *RGBA) SetRGBA64(x, y int, c color.RGBA64) { 151 if !(Point{x, y}.In(p.Rect)) { 152 return 153 } 154 i := p.PixOffset(x, y) 155 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 156 s[0] = uint8(c.R >> 8) 157 s[1] = uint8(c.G >> 8) 158 s[2] = uint8(c.B >> 8) 159 s[3] = uint8(c.A >> 8) 160 } 161 162 func (p *RGBA) SetRGBA(x, y int, c color.RGBA) { 163 if !(Point{x, y}.In(p.Rect)) { 164 return 165 } 166 i := p.PixOffset(x, y) 167 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 168 s[0] = c.R 169 s[1] = c.G 170 s[2] = c.B 171 s[3] = c.A 172 } 173 174 // SubImage returns an image representing the portion of the image p visible 175 // through r. The returned value shares pixels with the original image. 176 func (p *RGBA) SubImage(r Rectangle) Image { 177 r = r.Intersect(p.Rect) 178 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside 179 // either r1 or r2 if the intersection is empty. Without explicitly checking for 180 // this, the Pix[i:] expression below can panic. 181 if r.Empty() { 182 return &RGBA{} 183 } 184 i := p.PixOffset(r.Min.X, r.Min.Y) 185 return &RGBA{ 186 Pix: p.Pix[i:], 187 Stride: p.Stride, 188 Rect: r, 189 } 190 } 191 192 // Opaque scans the entire image and reports whether it is fully opaque. 193 func (p *RGBA) Opaque() bool { 194 if p.Rect.Empty() { 195 return true 196 } 197 i0, i1 := 3, p.Rect.Dx()*4 198 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ { 199 for i := i0; i < i1; i += 4 { 200 if p.Pix[i] != 0xff { 201 return false 202 } 203 } 204 i0 += p.Stride 205 i1 += p.Stride 206 } 207 return true 208 } 209 210 // NewRGBA returns a new RGBA image with the given bounds. 211 func NewRGBA(r Rectangle) *RGBA { 212 return &RGBA{ 213 Pix: make([]uint8, pixelBufferLength(4, r, "RGBA")), 214 Stride: 4 * r.Dx(), 215 Rect: r, 216 } 217 } 218 219 // RGBA64 is an in-memory image whose At method returns color.RGBA64 values. 220 type RGBA64 struct { 221 // Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at 222 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8]. 223 Pix []uint8 224 // Stride is the Pix stride (in bytes) between vertically adjacent pixels. 225 Stride int 226 // Rect is the image's bounds. 227 Rect Rectangle 228 } 229 230 func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model } 231 232 func (p *RGBA64) Bounds() Rectangle { return p.Rect } 233 234 func (p *RGBA64) At(x, y int) color.Color { 235 return p.RGBA64At(x, y) 236 } 237 238 func (p *RGBA64) RGBA64At(x, y int) color.RGBA64 { 239 if !(Point{x, y}.In(p.Rect)) { 240 return color.RGBA64{} 241 } 242 i := p.PixOffset(x, y) 243 s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857 244 return color.RGBA64{ 245 uint16(s[0])<<8 | uint16(s[1]), 246 uint16(s[2])<<8 | uint16(s[3]), 247 uint16(s[4])<<8 | uint16(s[5]), 248 uint16(s[6])<<8 | uint16(s[7]), 249 } 250 } 251 252 // PixOffset returns the index of the first element of Pix that corresponds to 253 // the pixel at (x, y). 254 func (p *RGBA64) PixOffset(x, y int) int { 255 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8 256 } 257 258 func (p *RGBA64) Set(x, y int, c color.Color) { 259 if !(Point{x, y}.In(p.Rect)) { 260 return 261 } 262 i := p.PixOffset(x, y) 263 c1 := color.RGBA64Model.Convert(c).(color.RGBA64) 264 s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857 265 s[0] = uint8(c1.R >> 8) 266 s[1] = uint8(c1.R) 267 s[2] = uint8(c1.G >> 8) 268 s[3] = uint8(c1.G) 269 s[4] = uint8(c1.B >> 8) 270 s[5] = uint8(c1.B) 271 s[6] = uint8(c1.A >> 8) 272 s[7] = uint8(c1.A) 273 } 274 275 func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) { 276 if !(Point{x, y}.In(p.Rect)) { 277 return 278 } 279 i := p.PixOffset(x, y) 280 s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857 281 s[0] = uint8(c.R >> 8) 282 s[1] = uint8(c.R) 283 s[2] = uint8(c.G >> 8) 284 s[3] = uint8(c.G) 285 s[4] = uint8(c.B >> 8) 286 s[5] = uint8(c.B) 287 s[6] = uint8(c.A >> 8) 288 s[7] = uint8(c.A) 289 } 290 291 // SubImage returns an image representing the portion of the image p visible 292 // through r. The returned value shares pixels with the original image. 293 func (p *RGBA64) SubImage(r Rectangle) Image { 294 r = r.Intersect(p.Rect) 295 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside 296 // either r1 or r2 if the intersection is empty. Without explicitly checking for 297 // this, the Pix[i:] expression below can panic. 298 if r.Empty() { 299 return &RGBA64{} 300 } 301 i := p.PixOffset(r.Min.X, r.Min.Y) 302 return &RGBA64{ 303 Pix: p.Pix[i:], 304 Stride: p.Stride, 305 Rect: r, 306 } 307 } 308 309 // Opaque scans the entire image and reports whether it is fully opaque. 310 func (p *RGBA64) Opaque() bool { 311 if p.Rect.Empty() { 312 return true 313 } 314 i0, i1 := 6, p.Rect.Dx()*8 315 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ { 316 for i := i0; i < i1; i += 8 { 317 if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff { 318 return false 319 } 320 } 321 i0 += p.Stride 322 i1 += p.Stride 323 } 324 return true 325 } 326 327 // NewRGBA64 returns a new RGBA64 image with the given bounds. 328 func NewRGBA64(r Rectangle) *RGBA64 { 329 return &RGBA64{ 330 Pix: make([]uint8, pixelBufferLength(8, r, "RGBA64")), 331 Stride: 8 * r.Dx(), 332 Rect: r, 333 } 334 } 335 336 // NRGBA is an in-memory image whose At method returns color.NRGBA values. 337 type NRGBA struct { 338 // Pix holds the image's pixels, in R, G, B, A order. The pixel at 339 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4]. 340 Pix []uint8 341 // Stride is the Pix stride (in bytes) between vertically adjacent pixels. 342 Stride int 343 // Rect is the image's bounds. 344 Rect Rectangle 345 } 346 347 func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel } 348 349 func (p *NRGBA) Bounds() Rectangle { return p.Rect } 350 351 func (p *NRGBA) At(x, y int) color.Color { 352 return p.NRGBAAt(x, y) 353 } 354 355 func (p *NRGBA) RGBA64At(x, y int) color.RGBA64 { 356 r, g, b, a := p.NRGBAAt(x, y).RGBA() 357 return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} 358 } 359 360 func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA { 361 if !(Point{x, y}.In(p.Rect)) { 362 return color.NRGBA{} 363 } 364 i := p.PixOffset(x, y) 365 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 366 return color.NRGBA{s[0], s[1], s[2], s[3]} 367 } 368 369 // PixOffset returns the index of the first element of Pix that corresponds to 370 // the pixel at (x, y). 371 func (p *NRGBA) PixOffset(x, y int) int { 372 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4 373 } 374 375 func (p *NRGBA) Set(x, y int, c color.Color) { 376 if !(Point{x, y}.In(p.Rect)) { 377 return 378 } 379 i := p.PixOffset(x, y) 380 c1 := color.NRGBAModel.Convert(c).(color.NRGBA) 381 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 382 s[0] = c1.R 383 s[1] = c1.G 384 s[2] = c1.B 385 s[3] = c1.A 386 } 387 388 func (p *NRGBA) SetRGBA64(x, y int, c color.RGBA64) { 389 if !(Point{x, y}.In(p.Rect)) { 390 return 391 } 392 r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A) 393 if (a != 0) && (a != 0xffff) { 394 r = (r * 0xffff) / a 395 g = (g * 0xffff) / a 396 b = (b * 0xffff) / a 397 } 398 i := p.PixOffset(x, y) 399 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 400 s[0] = uint8(r >> 8) 401 s[1] = uint8(g >> 8) 402 s[2] = uint8(b >> 8) 403 s[3] = uint8(a >> 8) 404 } 405 406 func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) { 407 if !(Point{x, y}.In(p.Rect)) { 408 return 409 } 410 i := p.PixOffset(x, y) 411 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 412 s[0] = c.R 413 s[1] = c.G 414 s[2] = c.B 415 s[3] = c.A 416 } 417 418 // SubImage returns an image representing the portion of the image p visible 419 // through r. The returned value shares pixels with the original image. 420 func (p *NRGBA) SubImage(r Rectangle) Image { 421 r = r.Intersect(p.Rect) 422 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside 423 // either r1 or r2 if the intersection is empty. Without explicitly checking for 424 // this, the Pix[i:] expression below can panic. 425 if r.Empty() { 426 return &NRGBA{} 427 } 428 i := p.PixOffset(r.Min.X, r.Min.Y) 429 return &NRGBA{ 430 Pix: p.Pix[i:], 431 Stride: p.Stride, 432 Rect: r, 433 } 434 } 435 436 // Opaque scans the entire image and reports whether it is fully opaque. 437 func (p *NRGBA) Opaque() bool { 438 if p.Rect.Empty() { 439 return true 440 } 441 i0, i1 := 3, p.Rect.Dx()*4 442 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ { 443 for i := i0; i < i1; i += 4 { 444 if p.Pix[i] != 0xff { 445 return false 446 } 447 } 448 i0 += p.Stride 449 i1 += p.Stride 450 } 451 return true 452 } 453 454 // NewNRGBA returns a new NRGBA image with the given bounds. 455 func NewNRGBA(r Rectangle) *NRGBA { 456 return &NRGBA{ 457 Pix: make([]uint8, pixelBufferLength(4, r, "NRGBA")), 458 Stride: 4 * r.Dx(), 459 Rect: r, 460 } 461 } 462 463 // NRGBA64 is an in-memory image whose At method returns color.NRGBA64 values. 464 type NRGBA64 struct { 465 // Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at 466 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8]. 467 Pix []uint8 468 // Stride is the Pix stride (in bytes) between vertically adjacent pixels. 469 Stride int 470 // Rect is the image's bounds. 471 Rect Rectangle 472 } 473 474 func (p *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model } 475 476 func (p *NRGBA64) Bounds() Rectangle { return p.Rect } 477 478 func (p *NRGBA64) At(x, y int) color.Color { 479 return p.NRGBA64At(x, y) 480 } 481 482 func (p *NRGBA64) RGBA64At(x, y int) color.RGBA64 { 483 r, g, b, a := p.NRGBA64At(x, y).RGBA() 484 return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} 485 } 486 487 func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 { 488 if !(Point{x, y}.In(p.Rect)) { 489 return color.NRGBA64{} 490 } 491 i := p.PixOffset(x, y) 492 s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857 493 return color.NRGBA64{ 494 uint16(s[0])<<8 | uint16(s[1]), 495 uint16(s[2])<<8 | uint16(s[3]), 496 uint16(s[4])<<8 | uint16(s[5]), 497 uint16(s[6])<<8 | uint16(s[7]), 498 } 499 } 500 501 // PixOffset returns the index of the first element of Pix that corresponds to 502 // the pixel at (x, y). 503 func (p *NRGBA64) PixOffset(x, y int) int { 504 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8 505 } 506 507 func (p *NRGBA64) Set(x, y int, c color.Color) { 508 if !(Point{x, y}.In(p.Rect)) { 509 return 510 } 511 i := p.PixOffset(x, y) 512 c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64) 513 s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857 514 s[0] = uint8(c1.R >> 8) 515 s[1] = uint8(c1.R) 516 s[2] = uint8(c1.G >> 8) 517 s[3] = uint8(c1.G) 518 s[4] = uint8(c1.B >> 8) 519 s[5] = uint8(c1.B) 520 s[6] = uint8(c1.A >> 8) 521 s[7] = uint8(c1.A) 522 } 523 524 func (p *NRGBA64) SetRGBA64(x, y int, c color.RGBA64) { 525 if !(Point{x, y}.In(p.Rect)) { 526 return 527 } 528 r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A) 529 if (a != 0) && (a != 0xffff) { 530 r = (r * 0xffff) / a 531 g = (g * 0xffff) / a 532 b = (b * 0xffff) / a 533 } 534 i := p.PixOffset(x, y) 535 s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857 536 s[0] = uint8(r >> 8) 537 s[1] = uint8(r) 538 s[2] = uint8(g >> 8) 539 s[3] = uint8(g) 540 s[4] = uint8(b >> 8) 541 s[5] = uint8(b) 542 s[6] = uint8(a >> 8) 543 s[7] = uint8(a) 544 } 545 546 func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) { 547 if !(Point{x, y}.In(p.Rect)) { 548 return 549 } 550 i := p.PixOffset(x, y) 551 s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857 552 s[0] = uint8(c.R >> 8) 553 s[1] = uint8(c.R) 554 s[2] = uint8(c.G >> 8) 555 s[3] = uint8(c.G) 556 s[4] = uint8(c.B >> 8) 557 s[5] = uint8(c.B) 558 s[6] = uint8(c.A >> 8) 559 s[7] = uint8(c.A) 560 } 561 562 // SubImage returns an image representing the portion of the image p visible 563 // through r. The returned value shares pixels with the original image. 564 func (p *NRGBA64) SubImage(r Rectangle) Image { 565 r = r.Intersect(p.Rect) 566 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside 567 // either r1 or r2 if the intersection is empty. Without explicitly checking for 568 // this, the Pix[i:] expression below can panic. 569 if r.Empty() { 570 return &NRGBA64{} 571 } 572 i := p.PixOffset(r.Min.X, r.Min.Y) 573 return &NRGBA64{ 574 Pix: p.Pix[i:], 575 Stride: p.Stride, 576 Rect: r, 577 } 578 } 579 580 // Opaque scans the entire image and reports whether it is fully opaque. 581 func (p *NRGBA64) Opaque() bool { 582 if p.Rect.Empty() { 583 return true 584 } 585 i0, i1 := 6, p.Rect.Dx()*8 586 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ { 587 for i := i0; i < i1; i += 8 { 588 if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff { 589 return false 590 } 591 } 592 i0 += p.Stride 593 i1 += p.Stride 594 } 595 return true 596 } 597 598 // NewNRGBA64 returns a new NRGBA64 image with the given bounds. 599 func NewNRGBA64(r Rectangle) *NRGBA64 { 600 return &NRGBA64{ 601 Pix: make([]uint8, pixelBufferLength(8, r, "NRGBA64")), 602 Stride: 8 * r.Dx(), 603 Rect: r, 604 } 605 } 606 607 // Alpha is an in-memory image whose At method returns color.Alpha values. 608 type Alpha struct { 609 // Pix holds the image's pixels, as alpha values. The pixel at 610 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1]. 611 Pix []uint8 612 // Stride is the Pix stride (in bytes) between vertically adjacent pixels. 613 Stride int 614 // Rect is the image's bounds. 615 Rect Rectangle 616 } 617 618 func (p *Alpha) ColorModel() color.Model { return color.AlphaModel } 619 620 func (p *Alpha) Bounds() Rectangle { return p.Rect } 621 622 func (p *Alpha) At(x, y int) color.Color { 623 return p.AlphaAt(x, y) 624 } 625 626 func (p *Alpha) RGBA64At(x, y int) color.RGBA64 { 627 a := uint16(p.AlphaAt(x, y).A) 628 a |= a << 8 629 return color.RGBA64{a, a, a, a} 630 } 631 632 func (p *Alpha) AlphaAt(x, y int) color.Alpha { 633 if !(Point{x, y}.In(p.Rect)) { 634 return color.Alpha{} 635 } 636 i := p.PixOffset(x, y) 637 return color.Alpha{p.Pix[i]} 638 } 639 640 // PixOffset returns the index of the first element of Pix that corresponds to 641 // the pixel at (x, y). 642 func (p *Alpha) PixOffset(x, y int) int { 643 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1 644 } 645 646 func (p *Alpha) Set(x, y int, c color.Color) { 647 if !(Point{x, y}.In(p.Rect)) { 648 return 649 } 650 i := p.PixOffset(x, y) 651 p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A 652 } 653 654 func (p *Alpha) SetRGBA64(x, y int, c color.RGBA64) { 655 if !(Point{x, y}.In(p.Rect)) { 656 return 657 } 658 i := p.PixOffset(x, y) 659 p.Pix[i] = uint8(c.A >> 8) 660 } 661 662 func (p *Alpha) SetAlpha(x, y int, c color.Alpha) { 663 if !(Point{x, y}.In(p.Rect)) { 664 return 665 } 666 i := p.PixOffset(x, y) 667 p.Pix[i] = c.A 668 } 669 670 // SubImage returns an image representing the portion of the image p visible 671 // through r. The returned value shares pixels with the original image. 672 func (p *Alpha) SubImage(r Rectangle) Image { 673 r = r.Intersect(p.Rect) 674 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside 675 // either r1 or r2 if the intersection is empty. Without explicitly checking for 676 // this, the Pix[i:] expression below can panic. 677 if r.Empty() { 678 return &Alpha{} 679 } 680 i := p.PixOffset(r.Min.X, r.Min.Y) 681 return &Alpha{ 682 Pix: p.Pix[i:], 683 Stride: p.Stride, 684 Rect: r, 685 } 686 } 687 688 // Opaque scans the entire image and reports whether it is fully opaque. 689 func (p *Alpha) Opaque() bool { 690 if p.Rect.Empty() { 691 return true 692 } 693 i0, i1 := 0, p.Rect.Dx() 694 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ { 695 for i := i0; i < i1; i++ { 696 if p.Pix[i] != 0xff { 697 return false 698 } 699 } 700 i0 += p.Stride 701 i1 += p.Stride 702 } 703 return true 704 } 705 706 // NewAlpha returns a new Alpha image with the given bounds. 707 func NewAlpha(r Rectangle) *Alpha { 708 return &Alpha{ 709 Pix: make([]uint8, pixelBufferLength(1, r, "Alpha")), 710 Stride: 1 * r.Dx(), 711 Rect: r, 712 } 713 } 714 715 // Alpha16 is an in-memory image whose At method returns color.Alpha16 values. 716 type Alpha16 struct { 717 // Pix holds the image's pixels, as alpha values in big-endian format. The pixel at 718 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2]. 719 Pix []uint8 720 // Stride is the Pix stride (in bytes) between vertically adjacent pixels. 721 Stride int 722 // Rect is the image's bounds. 723 Rect Rectangle 724 } 725 726 func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model } 727 728 func (p *Alpha16) Bounds() Rectangle { return p.Rect } 729 730 func (p *Alpha16) At(x, y int) color.Color { 731 return p.Alpha16At(x, y) 732 } 733 734 func (p *Alpha16) RGBA64At(x, y int) color.RGBA64 { 735 a := p.Alpha16At(x, y).A 736 return color.RGBA64{a, a, a, a} 737 } 738 739 func (p *Alpha16) Alpha16At(x, y int) color.Alpha16 { 740 if !(Point{x, y}.In(p.Rect)) { 741 return color.Alpha16{} 742 } 743 i := p.PixOffset(x, y) 744 return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])} 745 } 746 747 // PixOffset returns the index of the first element of Pix that corresponds to 748 // the pixel at (x, y). 749 func (p *Alpha16) PixOffset(x, y int) int { 750 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2 751 } 752 753 func (p *Alpha16) Set(x, y int, c color.Color) { 754 if !(Point{x, y}.In(p.Rect)) { 755 return 756 } 757 i := p.PixOffset(x, y) 758 c1 := color.Alpha16Model.Convert(c).(color.Alpha16) 759 p.Pix[i+0] = uint8(c1.A >> 8) 760 p.Pix[i+1] = uint8(c1.A) 761 } 762 763 func (p *Alpha16) SetRGBA64(x, y int, c color.RGBA64) { 764 if !(Point{x, y}.In(p.Rect)) { 765 return 766 } 767 i := p.PixOffset(x, y) 768 p.Pix[i+0] = uint8(c.A >> 8) 769 p.Pix[i+1] = uint8(c.A) 770 } 771 772 func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) { 773 if !(Point{x, y}.In(p.Rect)) { 774 return 775 } 776 i := p.PixOffset(x, y) 777 p.Pix[i+0] = uint8(c.A >> 8) 778 p.Pix[i+1] = uint8(c.A) 779 } 780 781 // SubImage returns an image representing the portion of the image p visible 782 // through r. The returned value shares pixels with the original image. 783 func (p *Alpha16) SubImage(r Rectangle) Image { 784 r = r.Intersect(p.Rect) 785 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside 786 // either r1 or r2 if the intersection is empty. Without explicitly checking for 787 // this, the Pix[i:] expression below can panic. 788 if r.Empty() { 789 return &Alpha16{} 790 } 791 i := p.PixOffset(r.Min.X, r.Min.Y) 792 return &Alpha16{ 793 Pix: p.Pix[i:], 794 Stride: p.Stride, 795 Rect: r, 796 } 797 } 798 799 // Opaque scans the entire image and reports whether it is fully opaque. 800 func (p *Alpha16) Opaque() bool { 801 if p.Rect.Empty() { 802 return true 803 } 804 i0, i1 := 0, p.Rect.Dx()*2 805 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ { 806 for i := i0; i < i1; i += 2 { 807 if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff { 808 return false 809 } 810 } 811 i0 += p.Stride 812 i1 += p.Stride 813 } 814 return true 815 } 816 817 // NewAlpha16 returns a new Alpha16 image with the given bounds. 818 func NewAlpha16(r Rectangle) *Alpha16 { 819 return &Alpha16{ 820 Pix: make([]uint8, pixelBufferLength(2, r, "Alpha16")), 821 Stride: 2 * r.Dx(), 822 Rect: r, 823 } 824 } 825 826 // Gray is an in-memory image whose At method returns color.Gray values. 827 type Gray struct { 828 // Pix holds the image's pixels, as gray values. The pixel at 829 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1]. 830 Pix []uint8 831 // Stride is the Pix stride (in bytes) between vertically adjacent pixels. 832 Stride int 833 // Rect is the image's bounds. 834 Rect Rectangle 835 } 836 837 func (p *Gray) ColorModel() color.Model { return color.GrayModel } 838 839 func (p *Gray) Bounds() Rectangle { return p.Rect } 840 841 func (p *Gray) At(x, y int) color.Color { 842 return p.GrayAt(x, y) 843 } 844 845 func (p *Gray) RGBA64At(x, y int) color.RGBA64 { 846 gray := uint16(p.GrayAt(x, y).Y) 847 gray |= gray << 8 848 return color.RGBA64{gray, gray, gray, 0xffff} 849 } 850 851 func (p *Gray) GrayAt(x, y int) color.Gray { 852 if !(Point{x, y}.In(p.Rect)) { 853 return color.Gray{} 854 } 855 i := p.PixOffset(x, y) 856 return color.Gray{p.Pix[i]} 857 } 858 859 // PixOffset returns the index of the first element of Pix that corresponds to 860 // the pixel at (x, y). 861 func (p *Gray) PixOffset(x, y int) int { 862 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1 863 } 864 865 func (p *Gray) Set(x, y int, c color.Color) { 866 if !(Point{x, y}.In(p.Rect)) { 867 return 868 } 869 i := p.PixOffset(x, y) 870 p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y 871 } 872 873 func (p *Gray) SetRGBA64(x, y int, c color.RGBA64) { 874 if !(Point{x, y}.In(p.Rect)) { 875 return 876 } 877 // This formula is the same as in color.grayModel. 878 gray := (19595*uint32(c.R) + 38470*uint32(c.G) + 7471*uint32(c.B) + 1<<15) >> 24 879 i := p.PixOffset(x, y) 880 p.Pix[i] = uint8(gray) 881 } 882 883 func (p *Gray) SetGray(x, y int, c color.Gray) { 884 if !(Point{x, y}.In(p.Rect)) { 885 return 886 } 887 i := p.PixOffset(x, y) 888 p.Pix[i] = c.Y 889 } 890 891 // SubImage returns an image representing the portion of the image p visible 892 // through r. The returned value shares pixels with the original image. 893 func (p *Gray) SubImage(r Rectangle) Image { 894 r = r.Intersect(p.Rect) 895 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside 896 // either r1 or r2 if the intersection is empty. Without explicitly checking for 897 // this, the Pix[i:] expression below can panic. 898 if r.Empty() { 899 return &Gray{} 900 } 901 i := p.PixOffset(r.Min.X, r.Min.Y) 902 return &Gray{ 903 Pix: p.Pix[i:], 904 Stride: p.Stride, 905 Rect: r, 906 } 907 } 908 909 // Opaque scans the entire image and reports whether it is fully opaque. 910 func (p *Gray) Opaque() bool { 911 return true 912 } 913 914 // NewGray returns a new Gray image with the given bounds. 915 func NewGray(r Rectangle) *Gray { 916 return &Gray{ 917 Pix: make([]uint8, pixelBufferLength(1, r, "Gray")), 918 Stride: 1 * r.Dx(), 919 Rect: r, 920 } 921 } 922 923 // Gray16 is an in-memory image whose At method returns color.Gray16 values. 924 type Gray16 struct { 925 // Pix holds the image's pixels, as gray values in big-endian format. The pixel at 926 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2]. 927 Pix []uint8 928 // Stride is the Pix stride (in bytes) between vertically adjacent pixels. 929 Stride int 930 // Rect is the image's bounds. 931 Rect Rectangle 932 } 933 934 func (p *Gray16) ColorModel() color.Model { return color.Gray16Model } 935 936 func (p *Gray16) Bounds() Rectangle { return p.Rect } 937 938 func (p *Gray16) At(x, y int) color.Color { 939 return p.Gray16At(x, y) 940 } 941 942 func (p *Gray16) RGBA64At(x, y int) color.RGBA64 { 943 gray := p.Gray16At(x, y).Y 944 return color.RGBA64{gray, gray, gray, 0xffff} 945 } 946 947 func (p *Gray16) Gray16At(x, y int) color.Gray16 { 948 if !(Point{x, y}.In(p.Rect)) { 949 return color.Gray16{} 950 } 951 i := p.PixOffset(x, y) 952 return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])} 953 } 954 955 // PixOffset returns the index of the first element of Pix that corresponds to 956 // the pixel at (x, y). 957 func (p *Gray16) PixOffset(x, y int) int { 958 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2 959 } 960 961 func (p *Gray16) Set(x, y int, c color.Color) { 962 if !(Point{x, y}.In(p.Rect)) { 963 return 964 } 965 i := p.PixOffset(x, y) 966 c1 := color.Gray16Model.Convert(c).(color.Gray16) 967 p.Pix[i+0] = uint8(c1.Y >> 8) 968 p.Pix[i+1] = uint8(c1.Y) 969 } 970 971 func (p *Gray16) SetRGBA64(x, y int, c color.RGBA64) { 972 if !(Point{x, y}.In(p.Rect)) { 973 return 974 } 975 // This formula is the same as in color.gray16Model. 976 gray := (19595*uint32(c.R) + 38470*uint32(c.G) + 7471*uint32(c.B) + 1<<15) >> 16 977 i := p.PixOffset(x, y) 978 p.Pix[i+0] = uint8(gray >> 8) 979 p.Pix[i+1] = uint8(gray) 980 } 981 982 func (p *Gray16) SetGray16(x, y int, c color.Gray16) { 983 if !(Point{x, y}.In(p.Rect)) { 984 return 985 } 986 i := p.PixOffset(x, y) 987 p.Pix[i+0] = uint8(c.Y >> 8) 988 p.Pix[i+1] = uint8(c.Y) 989 } 990 991 // SubImage returns an image representing the portion of the image p visible 992 // through r. The returned value shares pixels with the original image. 993 func (p *Gray16) SubImage(r Rectangle) Image { 994 r = r.Intersect(p.Rect) 995 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside 996 // either r1 or r2 if the intersection is empty. Without explicitly checking for 997 // this, the Pix[i:] expression below can panic. 998 if r.Empty() { 999 return &Gray16{} 1000 } 1001 i := p.PixOffset(r.Min.X, r.Min.Y) 1002 return &Gray16{ 1003 Pix: p.Pix[i:], 1004 Stride: p.Stride, 1005 Rect: r, 1006 } 1007 } 1008 1009 // Opaque scans the entire image and reports whether it is fully opaque. 1010 func (p *Gray16) Opaque() bool { 1011 return true 1012 } 1013 1014 // NewGray16 returns a new Gray16 image with the given bounds. 1015 func NewGray16(r Rectangle) *Gray16 { 1016 return &Gray16{ 1017 Pix: make([]uint8, pixelBufferLength(2, r, "Gray16")), 1018 Stride: 2 * r.Dx(), 1019 Rect: r, 1020 } 1021 } 1022 1023 // CMYK is an in-memory image whose At method returns color.CMYK values. 1024 type CMYK struct { 1025 // Pix holds the image's pixels, in C, M, Y, K order. The pixel at 1026 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4]. 1027 Pix []uint8 1028 // Stride is the Pix stride (in bytes) between vertically adjacent pixels. 1029 Stride int 1030 // Rect is the image's bounds. 1031 Rect Rectangle 1032 } 1033 1034 func (p *CMYK) ColorModel() color.Model { return color.CMYKModel } 1035 1036 func (p *CMYK) Bounds() Rectangle { return p.Rect } 1037 1038 func (p *CMYK) At(x, y int) color.Color { 1039 return p.CMYKAt(x, y) 1040 } 1041 1042 func (p *CMYK) RGBA64At(x, y int) color.RGBA64 { 1043 r, g, b, a := p.CMYKAt(x, y).RGBA() 1044 return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} 1045 } 1046 1047 func (p *CMYK) CMYKAt(x, y int) color.CMYK { 1048 if !(Point{x, y}.In(p.Rect)) { 1049 return color.CMYK{} 1050 } 1051 i := p.PixOffset(x, y) 1052 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 1053 return color.CMYK{s[0], s[1], s[2], s[3]} 1054 } 1055 1056 // PixOffset returns the index of the first element of Pix that corresponds to 1057 // the pixel at (x, y). 1058 func (p *CMYK) PixOffset(x, y int) int { 1059 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4 1060 } 1061 1062 func (p *CMYK) Set(x, y int, c color.Color) { 1063 if !(Point{x, y}.In(p.Rect)) { 1064 return 1065 } 1066 i := p.PixOffset(x, y) 1067 c1 := color.CMYKModel.Convert(c).(color.CMYK) 1068 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 1069 s[0] = c1.C 1070 s[1] = c1.M 1071 s[2] = c1.Y 1072 s[3] = c1.K 1073 } 1074 1075 func (p *CMYK) SetRGBA64(x, y int, c color.RGBA64) { 1076 if !(Point{x, y}.In(p.Rect)) { 1077 return 1078 } 1079 cc, mm, yy, kk := color.RGBToCMYK(uint8(c.R>>8), uint8(c.G>>8), uint8(c.B>>8)) 1080 i := p.PixOffset(x, y) 1081 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 1082 s[0] = cc 1083 s[1] = mm 1084 s[2] = yy 1085 s[3] = kk 1086 } 1087 1088 func (p *CMYK) SetCMYK(x, y int, c color.CMYK) { 1089 if !(Point{x, y}.In(p.Rect)) { 1090 return 1091 } 1092 i := p.PixOffset(x, y) 1093 s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 1094 s[0] = c.C 1095 s[1] = c.M 1096 s[2] = c.Y 1097 s[3] = c.K 1098 } 1099 1100 // SubImage returns an image representing the portion of the image p visible 1101 // through r. The returned value shares pixels with the original image. 1102 func (p *CMYK) SubImage(r Rectangle) Image { 1103 r = r.Intersect(p.Rect) 1104 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside 1105 // either r1 or r2 if the intersection is empty. Without explicitly checking for 1106 // this, the Pix[i:] expression below can panic. 1107 if r.Empty() { 1108 return &CMYK{} 1109 } 1110 i := p.PixOffset(r.Min.X, r.Min.Y) 1111 return &CMYK{ 1112 Pix: p.Pix[i:], 1113 Stride: p.Stride, 1114 Rect: r, 1115 } 1116 } 1117 1118 // Opaque scans the entire image and reports whether it is fully opaque. 1119 func (p *CMYK) Opaque() bool { 1120 return true 1121 } 1122 1123 // NewCMYK returns a new CMYK image with the given bounds. 1124 func NewCMYK(r Rectangle) *CMYK { 1125 return &CMYK{ 1126 Pix: make([]uint8, pixelBufferLength(4, r, "CMYK")), 1127 Stride: 4 * r.Dx(), 1128 Rect: r, 1129 } 1130 } 1131 1132 // Paletted is an in-memory image of uint8 indices into a given palette. 1133 type Paletted struct { 1134 // Pix holds the image's pixels, as palette indices. The pixel at 1135 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1]. 1136 Pix []uint8 1137 // Stride is the Pix stride (in bytes) between vertically adjacent pixels. 1138 Stride int 1139 // Rect is the image's bounds. 1140 Rect Rectangle 1141 // Palette is the image's palette. 1142 Palette color.Palette 1143 } 1144 1145 func (p *Paletted) ColorModel() color.Model { return p.Palette } 1146 1147 func (p *Paletted) Bounds() Rectangle { return p.Rect } 1148 1149 func (p *Paletted) At(x, y int) color.Color { 1150 if len(p.Palette) == 0 { 1151 return nil 1152 } 1153 if !(Point{x, y}.In(p.Rect)) { 1154 return p.Palette[0] 1155 } 1156 i := p.PixOffset(x, y) 1157 return p.Palette[p.Pix[i]] 1158 } 1159 1160 func (p *Paletted) RGBA64At(x, y int) color.RGBA64 { 1161 if len(p.Palette) == 0 { 1162 return color.RGBA64{} 1163 } 1164 c := color.Color(nil) 1165 if !(Point{x, y}.In(p.Rect)) { 1166 c = p.Palette[0] 1167 } else { 1168 i := p.PixOffset(x, y) 1169 c = p.Palette[p.Pix[i]] 1170 } 1171 r, g, b, a := c.RGBA() 1172 return color.RGBA64{ 1173 uint16(r), 1174 uint16(g), 1175 uint16(b), 1176 uint16(a), 1177 } 1178 } 1179 1180 // PixOffset returns the index of the first element of Pix that corresponds to 1181 // the pixel at (x, y). 1182 func (p *Paletted) PixOffset(x, y int) int { 1183 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1 1184 } 1185 1186 func (p *Paletted) Set(x, y int, c color.Color) { 1187 if !(Point{x, y}.In(p.Rect)) { 1188 return 1189 } 1190 i := p.PixOffset(x, y) 1191 p.Pix[i] = uint8(p.Palette.Index(c)) 1192 } 1193 1194 func (p *Paletted) SetRGBA64(x, y int, c color.RGBA64) { 1195 if !(Point{x, y}.In(p.Rect)) { 1196 return 1197 } 1198 i := p.PixOffset(x, y) 1199 p.Pix[i] = uint8(p.Palette.Index(c)) 1200 } 1201 1202 func (p *Paletted) ColorIndexAt(x, y int) uint8 { 1203 if !(Point{x, y}.In(p.Rect)) { 1204 return 0 1205 } 1206 i := p.PixOffset(x, y) 1207 return p.Pix[i] 1208 } 1209 1210 func (p *Paletted) SetColorIndex(x, y int, index uint8) { 1211 if !(Point{x, y}.In(p.Rect)) { 1212 return 1213 } 1214 i := p.PixOffset(x, y) 1215 p.Pix[i] = index 1216 } 1217 1218 // SubImage returns an image representing the portion of the image p visible 1219 // through r. The returned value shares pixels with the original image. 1220 func (p *Paletted) SubImage(r Rectangle) Image { 1221 r = r.Intersect(p.Rect) 1222 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside 1223 // either r1 or r2 if the intersection is empty. Without explicitly checking for 1224 // this, the Pix[i:] expression below can panic. 1225 if r.Empty() { 1226 return &Paletted{ 1227 Palette: p.Palette, 1228 } 1229 } 1230 i := p.PixOffset(r.Min.X, r.Min.Y) 1231 return &Paletted{ 1232 Pix: p.Pix[i:], 1233 Stride: p.Stride, 1234 Rect: p.Rect.Intersect(r), 1235 Palette: p.Palette, 1236 } 1237 } 1238 1239 // Opaque scans the entire image and reports whether it is fully opaque. 1240 func (p *Paletted) Opaque() bool { 1241 var present [256]bool 1242 i0, i1 := 0, p.Rect.Dx() 1243 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ { 1244 for _, c := range p.Pix[i0:i1] { 1245 present[c] = true 1246 } 1247 i0 += p.Stride 1248 i1 += p.Stride 1249 } 1250 for i, c := range p.Palette { 1251 if !present[i] { 1252 continue 1253 } 1254 _, _, _, a := c.RGBA() 1255 if a != 0xffff { 1256 return false 1257 } 1258 } 1259 return true 1260 } 1261 1262 // NewPaletted returns a new Paletted image with the given width, height and 1263 // palette. 1264 func NewPaletted(r Rectangle, p color.Palette) *Paletted { 1265 return &Paletted{ 1266 Pix: make([]uint8, pixelBufferLength(1, r, "Paletted")), 1267 Stride: 1 * r.Dx(), 1268 Rect: r, 1269 Palette: p, 1270 } 1271 }