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