github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/image/png/reader.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 png implements a PNG image decoder and encoder. 6 // 7 // The PNG specification is at https://www.w3.org/TR/PNG/. 8 package png 9 10 import ( 11 "compress/zlib" 12 "encoding/binary" 13 "fmt" 14 "hash" 15 "hash/crc32" 16 "image" 17 "image/color" 18 "io" 19 ) 20 21 // Color type, as per the PNG spec. 22 const ( 23 ctGrayscale = 0 24 ctTrueColor = 2 25 ctPaletted = 3 26 ctGrayscaleAlpha = 4 27 ctTrueColorAlpha = 6 28 ) 29 30 // A cb is a combination of color type and bit depth. 31 const ( 32 cbInvalid = iota 33 cbG1 34 cbG2 35 cbG4 36 cbG8 37 cbGA8 38 cbTC8 39 cbP1 40 cbP2 41 cbP4 42 cbP8 43 cbTCA8 44 cbG16 45 cbGA16 46 cbTC16 47 cbTCA16 48 ) 49 50 func cbPaletted(cb int) bool { 51 return cbP1 <= cb && cb <= cbP8 52 } 53 54 func cbTrueColor(cb int) bool { 55 return cb == cbTC8 || cb == cbTC16 56 } 57 58 // Filter type, as per the PNG spec. 59 const ( 60 ftNone = 0 61 ftSub = 1 62 ftUp = 2 63 ftAverage = 3 64 ftPaeth = 4 65 nFilter = 5 66 ) 67 68 // Interlace type. 69 const ( 70 itNone = 0 71 itAdam7 = 1 72 ) 73 74 // interlaceScan defines the placement and size of a pass for Adam7 interlacing. 75 type interlaceScan struct { 76 xFactor, yFactor, xOffset, yOffset int 77 } 78 79 // interlacing defines Adam7 interlacing, with 7 passes of reduced images. 80 // See https://www.w3.org/TR/PNG/#8Interlace 81 var interlacing = []interlaceScan{ 82 {8, 8, 0, 0}, 83 {8, 8, 4, 0}, 84 {4, 8, 0, 4}, 85 {4, 4, 2, 0}, 86 {2, 4, 0, 2}, 87 {2, 2, 1, 0}, 88 {1, 2, 0, 1}, 89 } 90 91 // Decoding stage. 92 // The PNG specification says that the IHDR, PLTE (if present), tRNS (if 93 // present), IDAT and IEND chunks must appear in that order. There may be 94 // multiple IDAT chunks, and IDAT chunks must be sequential (i.e. they may not 95 // have any other chunks between them). 96 // https://www.w3.org/TR/PNG/#5ChunkOrdering 97 const ( 98 dsStart = iota 99 dsSeenIHDR 100 dsSeenPLTE 101 dsSeentRNS 102 dsSeenIDAT 103 dsSeenIEND 104 ) 105 106 const pngHeader = "\x89PNG\r\n\x1a\n" 107 108 type decoder struct { 109 r io.Reader 110 img image.Image 111 crc hash.Hash32 112 width, height int 113 depth int 114 palette color.Palette 115 cb int 116 stage int 117 idatLength uint32 118 tmp [3 * 256]byte 119 interlace int 120 121 // useTransparent and transparent are used for grayscale and truecolor 122 // transparency, as opposed to palette transparency. 123 useTransparent bool 124 transparent [6]byte 125 } 126 127 // A FormatError reports that the input is not a valid PNG. 128 type FormatError string 129 130 func (e FormatError) Error() string { return "png: invalid format: " + string(e) } 131 132 var chunkOrderError = FormatError("chunk out of order") 133 134 // An UnsupportedError reports that the input uses a valid but unimplemented PNG feature. 135 type UnsupportedError string 136 137 func (e UnsupportedError) Error() string { return "png: unsupported feature: " + string(e) } 138 139 func (d *decoder) parseIHDR(length uint32) error { 140 if length != 13 { 141 return FormatError("bad IHDR length") 142 } 143 if _, err := io.ReadFull(d.r, d.tmp[:13]); err != nil { 144 return err 145 } 146 d.crc.Write(d.tmp[:13]) 147 if d.tmp[10] != 0 { 148 return UnsupportedError("compression method") 149 } 150 if d.tmp[11] != 0 { 151 return UnsupportedError("filter method") 152 } 153 if d.tmp[12] != itNone && d.tmp[12] != itAdam7 { 154 return FormatError("invalid interlace method") 155 } 156 d.interlace = int(d.tmp[12]) 157 158 w := int32(binary.BigEndian.Uint32(d.tmp[0:4])) 159 h := int32(binary.BigEndian.Uint32(d.tmp[4:8])) 160 if w <= 0 || h <= 0 { 161 return FormatError("non-positive dimension") 162 } 163 nPixels64 := int64(w) * int64(h) 164 nPixels := int(nPixels64) 165 if nPixels64 != int64(nPixels) { 166 return UnsupportedError("dimension overflow") 167 } 168 // There can be up to 8 bytes per pixel, for 16 bits per channel RGBA. 169 if nPixels != (nPixels*8)/8 { 170 return UnsupportedError("dimension overflow") 171 } 172 173 d.cb = cbInvalid 174 d.depth = int(d.tmp[8]) 175 switch d.depth { 176 case 1: 177 switch d.tmp[9] { 178 case ctGrayscale: 179 d.cb = cbG1 180 case ctPaletted: 181 d.cb = cbP1 182 } 183 case 2: 184 switch d.tmp[9] { 185 case ctGrayscale: 186 d.cb = cbG2 187 case ctPaletted: 188 d.cb = cbP2 189 } 190 case 4: 191 switch d.tmp[9] { 192 case ctGrayscale: 193 d.cb = cbG4 194 case ctPaletted: 195 d.cb = cbP4 196 } 197 case 8: 198 switch d.tmp[9] { 199 case ctGrayscale: 200 d.cb = cbG8 201 case ctTrueColor: 202 d.cb = cbTC8 203 case ctPaletted: 204 d.cb = cbP8 205 case ctGrayscaleAlpha: 206 d.cb = cbGA8 207 case ctTrueColorAlpha: 208 d.cb = cbTCA8 209 } 210 case 16: 211 switch d.tmp[9] { 212 case ctGrayscale: 213 d.cb = cbG16 214 case ctTrueColor: 215 d.cb = cbTC16 216 case ctGrayscaleAlpha: 217 d.cb = cbGA16 218 case ctTrueColorAlpha: 219 d.cb = cbTCA16 220 } 221 } 222 if d.cb == cbInvalid { 223 return UnsupportedError(fmt.Sprintf("bit depth %d, color type %d", d.tmp[8], d.tmp[9])) 224 } 225 d.width, d.height = int(w), int(h) 226 return d.verifyChecksum() 227 } 228 229 func (d *decoder) parsePLTE(length uint32) error { 230 np := int(length / 3) // The number of palette entries. 231 if length%3 != 0 || np <= 0 || np > 256 || np > 1<<uint(d.depth) { 232 return FormatError("bad PLTE length") 233 } 234 n, err := io.ReadFull(d.r, d.tmp[:3*np]) 235 if err != nil { 236 return err 237 } 238 d.crc.Write(d.tmp[:n]) 239 switch d.cb { 240 case cbP1, cbP2, cbP4, cbP8: 241 d.palette = make(color.Palette, 256) 242 for i := 0; i < np; i++ { 243 d.palette[i] = color.RGBA{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff} 244 } 245 for i := np; i < 256; i++ { 246 // Initialize the rest of the palette to opaque black. The spec (section 247 // 11.2.3) says that "any out-of-range pixel value found in the image data 248 // is an error", but some real-world PNG files have out-of-range pixel 249 // values. We fall back to opaque black, the same as libpng 1.5.13; 250 // ImageMagick 6.5.7 returns an error. 251 d.palette[i] = color.RGBA{0x00, 0x00, 0x00, 0xff} 252 } 253 d.palette = d.palette[:np] 254 case cbTC8, cbTCA8, cbTC16, cbTCA16: 255 // As per the PNG spec, a PLTE chunk is optional (and for practical purposes, 256 // ignorable) for the ctTrueColor and ctTrueColorAlpha color types (section 4.1.2). 257 default: 258 return FormatError("PLTE, color type mismatch") 259 } 260 return d.verifyChecksum() 261 } 262 263 func (d *decoder) parsetRNS(length uint32) error { 264 switch d.cb { 265 case cbG1, cbG2, cbG4, cbG8, cbG16: 266 if length != 2 { 267 return FormatError("bad tRNS length") 268 } 269 n, err := io.ReadFull(d.r, d.tmp[:length]) 270 if err != nil { 271 return err 272 } 273 d.crc.Write(d.tmp[:n]) 274 275 copy(d.transparent[:], d.tmp[:length]) 276 switch d.cb { 277 case cbG1: 278 d.transparent[1] *= 0xff 279 case cbG2: 280 d.transparent[1] *= 0x55 281 case cbG4: 282 d.transparent[1] *= 0x11 283 } 284 d.useTransparent = true 285 286 case cbTC8, cbTC16: 287 if length != 6 { 288 return FormatError("bad tRNS length") 289 } 290 n, err := io.ReadFull(d.r, d.tmp[:length]) 291 if err != nil { 292 return err 293 } 294 d.crc.Write(d.tmp[:n]) 295 296 copy(d.transparent[:], d.tmp[:length]) 297 d.useTransparent = true 298 299 case cbP1, cbP2, cbP4, cbP8: 300 if length > 256 { 301 return FormatError("bad tRNS length") 302 } 303 n, err := io.ReadFull(d.r, d.tmp[:length]) 304 if err != nil { 305 return err 306 } 307 d.crc.Write(d.tmp[:n]) 308 309 if len(d.palette) < n { 310 d.palette = d.palette[:n] 311 } 312 for i := 0; i < n; i++ { 313 rgba := d.palette[i].(color.RGBA) 314 d.palette[i] = color.NRGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]} 315 } 316 317 default: 318 return FormatError("tRNS, color type mismatch") 319 } 320 return d.verifyChecksum() 321 } 322 323 // Read presents one or more IDAT chunks as one continuous stream (minus the 324 // intermediate chunk headers and footers). If the PNG data looked like: 325 // 326 // ... len0 IDAT xxx crc0 len1 IDAT yy crc1 len2 IEND crc2 327 // 328 // then this reader presents xxxyy. For well-formed PNG data, the decoder state 329 // immediately before the first Read call is that d.r is positioned between the 330 // first IDAT and xxx, and the decoder state immediately after the last Read 331 // call is that d.r is positioned between yy and crc1. 332 func (d *decoder) Read(p []byte) (int, error) { 333 if len(p) == 0 { 334 return 0, nil 335 } 336 for d.idatLength == 0 { 337 // We have exhausted an IDAT chunk. Verify the checksum of that chunk. 338 if err := d.verifyChecksum(); err != nil { 339 return 0, err 340 } 341 // Read the length and chunk type of the next chunk, and check that 342 // it is an IDAT chunk. 343 if _, err := io.ReadFull(d.r, d.tmp[:8]); err != nil { 344 return 0, err 345 } 346 d.idatLength = binary.BigEndian.Uint32(d.tmp[:4]) 347 if string(d.tmp[4:8]) != "IDAT" { 348 return 0, FormatError("not enough pixel data") 349 } 350 d.crc.Reset() 351 d.crc.Write(d.tmp[4:8]) 352 } 353 if int(d.idatLength) < 0 { 354 return 0, UnsupportedError("IDAT chunk length overflow") 355 } 356 n, err := d.r.Read(p[:min(len(p), int(d.idatLength))]) 357 d.crc.Write(p[:n]) 358 d.idatLength -= uint32(n) 359 return n, err 360 } 361 362 // decode decodes the IDAT data into an image. 363 func (d *decoder) decode() (image.Image, error) { 364 r, err := zlib.NewReader(d) 365 if err != nil { 366 return nil, err 367 } 368 defer r.Close() 369 var img image.Image 370 if d.interlace == itNone { 371 img, err = d.readImagePass(r, 0, false) 372 if err != nil { 373 return nil, err 374 } 375 } else if d.interlace == itAdam7 { 376 // Allocate a blank image of the full size. 377 img, err = d.readImagePass(nil, 0, true) 378 if err != nil { 379 return nil, err 380 } 381 for pass := 0; pass < 7; pass++ { 382 imagePass, err := d.readImagePass(r, pass, false) 383 if err != nil { 384 return nil, err 385 } 386 if imagePass != nil { 387 d.mergePassInto(img, imagePass, pass) 388 } 389 } 390 } 391 392 // Check for EOF, to verify the zlib checksum. 393 n := 0 394 for i := 0; n == 0 && err == nil; i++ { 395 if i == 100 { 396 return nil, io.ErrNoProgress 397 } 398 n, err = r.Read(d.tmp[:1]) 399 } 400 if err != nil && err != io.EOF { 401 return nil, FormatError(err.Error()) 402 } 403 if n != 0 || d.idatLength != 0 { 404 return nil, FormatError("too much pixel data") 405 } 406 407 return img, nil 408 } 409 410 // readImagePass reads a single image pass, sized according to the pass number. 411 func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image.Image, error) { 412 bitsPerPixel := 0 413 pixOffset := 0 414 var ( 415 gray *image.Gray 416 rgba *image.RGBA 417 paletted *image.Paletted 418 nrgba *image.NRGBA 419 gray16 *image.Gray16 420 rgba64 *image.RGBA64 421 nrgba64 *image.NRGBA64 422 img image.Image 423 ) 424 width, height := d.width, d.height 425 if d.interlace == itAdam7 && !allocateOnly { 426 p := interlacing[pass] 427 // Add the multiplication factor and subtract one, effectively rounding up. 428 width = (width - p.xOffset + p.xFactor - 1) / p.xFactor 429 height = (height - p.yOffset + p.yFactor - 1) / p.yFactor 430 // A PNG image can't have zero width or height, but for an interlaced 431 // image, an individual pass might have zero width or height. If so, we 432 // shouldn't even read a per-row filter type byte, so return early. 433 if width == 0 || height == 0 { 434 return nil, nil 435 } 436 } 437 switch d.cb { 438 case cbG1, cbG2, cbG4, cbG8: 439 bitsPerPixel = d.depth 440 if d.useTransparent { 441 nrgba = image.NewNRGBA(image.Rect(0, 0, width, height)) 442 img = nrgba 443 } else { 444 gray = image.NewGray(image.Rect(0, 0, width, height)) 445 img = gray 446 } 447 case cbGA8: 448 bitsPerPixel = 16 449 nrgba = image.NewNRGBA(image.Rect(0, 0, width, height)) 450 img = nrgba 451 case cbTC8: 452 bitsPerPixel = 24 453 if d.useTransparent { 454 nrgba = image.NewNRGBA(image.Rect(0, 0, width, height)) 455 img = nrgba 456 } else { 457 rgba = image.NewRGBA(image.Rect(0, 0, width, height)) 458 img = rgba 459 } 460 case cbP1, cbP2, cbP4, cbP8: 461 bitsPerPixel = d.depth 462 paletted = image.NewPaletted(image.Rect(0, 0, width, height), d.palette) 463 img = paletted 464 case cbTCA8: 465 bitsPerPixel = 32 466 nrgba = image.NewNRGBA(image.Rect(0, 0, width, height)) 467 img = nrgba 468 case cbG16: 469 bitsPerPixel = 16 470 if d.useTransparent { 471 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height)) 472 img = nrgba64 473 } else { 474 gray16 = image.NewGray16(image.Rect(0, 0, width, height)) 475 img = gray16 476 } 477 case cbGA16: 478 bitsPerPixel = 32 479 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height)) 480 img = nrgba64 481 case cbTC16: 482 bitsPerPixel = 48 483 if d.useTransparent { 484 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height)) 485 img = nrgba64 486 } else { 487 rgba64 = image.NewRGBA64(image.Rect(0, 0, width, height)) 488 img = rgba64 489 } 490 case cbTCA16: 491 bitsPerPixel = 64 492 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height)) 493 img = nrgba64 494 } 495 if allocateOnly { 496 return img, nil 497 } 498 bytesPerPixel := (bitsPerPixel + 7) / 8 499 500 // The +1 is for the per-row filter type, which is at cr[0]. 501 rowSize := 1 + (int64(bitsPerPixel)*int64(width)+7)/8 502 if rowSize != int64(int(rowSize)) { 503 return nil, UnsupportedError("dimension overflow") 504 } 505 // cr and pr are the bytes for the current and previous row. 506 cr := make([]uint8, rowSize) 507 pr := make([]uint8, rowSize) 508 509 for y := 0; y < height; y++ { 510 // Read the decompressed bytes. 511 _, err := io.ReadFull(r, cr) 512 if err != nil { 513 if err == io.EOF || err == io.ErrUnexpectedEOF { 514 return nil, FormatError("not enough pixel data") 515 } 516 return nil, err 517 } 518 519 // Apply the filter. 520 cdat := cr[1:] 521 pdat := pr[1:] 522 switch cr[0] { 523 case ftNone: 524 // No-op. 525 case ftSub: 526 for i := bytesPerPixel; i < len(cdat); i++ { 527 cdat[i] += cdat[i-bytesPerPixel] 528 } 529 case ftUp: 530 for i, p := range pdat { 531 cdat[i] += p 532 } 533 case ftAverage: 534 // The first column has no column to the left of it, so it is a 535 // special case. We know that the first column exists because we 536 // check above that width != 0, and so len(cdat) != 0. 537 for i := 0; i < bytesPerPixel; i++ { 538 cdat[i] += pdat[i] / 2 539 } 540 for i := bytesPerPixel; i < len(cdat); i++ { 541 cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2) 542 } 543 case ftPaeth: 544 filterPaeth(cdat, pdat, bytesPerPixel) 545 default: 546 return nil, FormatError("bad filter type") 547 } 548 549 // Convert from bytes to colors. 550 switch d.cb { 551 case cbG1: 552 if d.useTransparent { 553 ty := d.transparent[1] 554 for x := 0; x < width; x += 8 { 555 b := cdat[x/8] 556 for x2 := 0; x2 < 8 && x+x2 < width; x2++ { 557 ycol := (b >> 7) * 0xff 558 acol := uint8(0xff) 559 if ycol == ty { 560 acol = 0x00 561 } 562 nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol}) 563 b <<= 1 564 } 565 } 566 } else { 567 for x := 0; x < width; x += 8 { 568 b := cdat[x/8] 569 for x2 := 0; x2 < 8 && x+x2 < width; x2++ { 570 gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff}) 571 b <<= 1 572 } 573 } 574 } 575 case cbG2: 576 if d.useTransparent { 577 ty := d.transparent[1] 578 for x := 0; x < width; x += 4 { 579 b := cdat[x/4] 580 for x2 := 0; x2 < 4 && x+x2 < width; x2++ { 581 ycol := (b >> 6) * 0x55 582 acol := uint8(0xff) 583 if ycol == ty { 584 acol = 0x00 585 } 586 nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol}) 587 b <<= 2 588 } 589 } 590 } else { 591 for x := 0; x < width; x += 4 { 592 b := cdat[x/4] 593 for x2 := 0; x2 < 4 && x+x2 < width; x2++ { 594 gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55}) 595 b <<= 2 596 } 597 } 598 } 599 case cbG4: 600 if d.useTransparent { 601 ty := d.transparent[1] 602 for x := 0; x < width; x += 2 { 603 b := cdat[x/2] 604 for x2 := 0; x2 < 2 && x+x2 < width; x2++ { 605 ycol := (b >> 4) * 0x11 606 acol := uint8(0xff) 607 if ycol == ty { 608 acol = 0x00 609 } 610 nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol}) 611 b <<= 4 612 } 613 } 614 } else { 615 for x := 0; x < width; x += 2 { 616 b := cdat[x/2] 617 for x2 := 0; x2 < 2 && x+x2 < width; x2++ { 618 gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11}) 619 b <<= 4 620 } 621 } 622 } 623 case cbG8: 624 if d.useTransparent { 625 ty := d.transparent[1] 626 for x := 0; x < width; x++ { 627 ycol := cdat[x] 628 acol := uint8(0xff) 629 if ycol == ty { 630 acol = 0x00 631 } 632 nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, acol}) 633 } 634 } else { 635 copy(gray.Pix[pixOffset:], cdat) 636 pixOffset += gray.Stride 637 } 638 case cbGA8: 639 for x := 0; x < width; x++ { 640 ycol := cdat[2*x+0] 641 nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]}) 642 } 643 case cbTC8: 644 if d.useTransparent { 645 pix, i, j := nrgba.Pix, pixOffset, 0 646 tr, tg, tb := d.transparent[1], d.transparent[3], d.transparent[5] 647 for x := 0; x < width; x++ { 648 r := cdat[j+0] 649 g := cdat[j+1] 650 b := cdat[j+2] 651 a := uint8(0xff) 652 if r == tr && g == tg && b == tb { 653 a = 0x00 654 } 655 pix[i+0] = r 656 pix[i+1] = g 657 pix[i+2] = b 658 pix[i+3] = a 659 i += 4 660 j += 3 661 } 662 pixOffset += nrgba.Stride 663 } else { 664 pix, i, j := rgba.Pix, pixOffset, 0 665 for x := 0; x < width; x++ { 666 pix[i+0] = cdat[j+0] 667 pix[i+1] = cdat[j+1] 668 pix[i+2] = cdat[j+2] 669 pix[i+3] = 0xff 670 i += 4 671 j += 3 672 } 673 pixOffset += rgba.Stride 674 } 675 case cbP1: 676 for x := 0; x < width; x += 8 { 677 b := cdat[x/8] 678 for x2 := 0; x2 < 8 && x+x2 < width; x2++ { 679 idx := b >> 7 680 if len(paletted.Palette) <= int(idx) { 681 paletted.Palette = paletted.Palette[:int(idx)+1] 682 } 683 paletted.SetColorIndex(x+x2, y, idx) 684 b <<= 1 685 } 686 } 687 case cbP2: 688 for x := 0; x < width; x += 4 { 689 b := cdat[x/4] 690 for x2 := 0; x2 < 4 && x+x2 < width; x2++ { 691 idx := b >> 6 692 if len(paletted.Palette) <= int(idx) { 693 paletted.Palette = paletted.Palette[:int(idx)+1] 694 } 695 paletted.SetColorIndex(x+x2, y, idx) 696 b <<= 2 697 } 698 } 699 case cbP4: 700 for x := 0; x < width; x += 2 { 701 b := cdat[x/2] 702 for x2 := 0; x2 < 2 && x+x2 < width; x2++ { 703 idx := b >> 4 704 if len(paletted.Palette) <= int(idx) { 705 paletted.Palette = paletted.Palette[:int(idx)+1] 706 } 707 paletted.SetColorIndex(x+x2, y, idx) 708 b <<= 4 709 } 710 } 711 case cbP8: 712 if len(paletted.Palette) != 256 { 713 for x := 0; x < width; x++ { 714 if len(paletted.Palette) <= int(cdat[x]) { 715 paletted.Palette = paletted.Palette[:int(cdat[x])+1] 716 } 717 } 718 } 719 copy(paletted.Pix[pixOffset:], cdat) 720 pixOffset += paletted.Stride 721 case cbTCA8: 722 copy(nrgba.Pix[pixOffset:], cdat) 723 pixOffset += nrgba.Stride 724 case cbG16: 725 if d.useTransparent { 726 ty := uint16(d.transparent[0])<<8 | uint16(d.transparent[1]) 727 for x := 0; x < width; x++ { 728 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1]) 729 acol := uint16(0xffff) 730 if ycol == ty { 731 acol = 0x0000 732 } 733 nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol}) 734 } 735 } else { 736 for x := 0; x < width; x++ { 737 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1]) 738 gray16.SetGray16(x, y, color.Gray16{ycol}) 739 } 740 } 741 case cbGA16: 742 for x := 0; x < width; x++ { 743 ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1]) 744 acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3]) 745 nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol}) 746 } 747 case cbTC16: 748 if d.useTransparent { 749 tr := uint16(d.transparent[0])<<8 | uint16(d.transparent[1]) 750 tg := uint16(d.transparent[2])<<8 | uint16(d.transparent[3]) 751 tb := uint16(d.transparent[4])<<8 | uint16(d.transparent[5]) 752 for x := 0; x < width; x++ { 753 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1]) 754 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3]) 755 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5]) 756 acol := uint16(0xffff) 757 if rcol == tr && gcol == tg && bcol == tb { 758 acol = 0x0000 759 } 760 nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol}) 761 } 762 } else { 763 for x := 0; x < width; x++ { 764 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1]) 765 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3]) 766 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5]) 767 rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff}) 768 } 769 } 770 case cbTCA16: 771 for x := 0; x < width; x++ { 772 rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1]) 773 gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3]) 774 bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5]) 775 acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7]) 776 nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol}) 777 } 778 } 779 780 // The current row for y is the previous row for y+1. 781 pr, cr = cr, pr 782 } 783 784 return img, nil 785 } 786 787 // mergePassInto merges a single pass into a full sized image. 788 func (d *decoder) mergePassInto(dst image.Image, src image.Image, pass int) { 789 p := interlacing[pass] 790 var ( 791 srcPix []uint8 792 dstPix []uint8 793 stride int 794 rect image.Rectangle 795 bytesPerPixel int 796 ) 797 switch target := dst.(type) { 798 case *image.Alpha: 799 srcPix = src.(*image.Alpha).Pix 800 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 801 bytesPerPixel = 1 802 case *image.Alpha16: 803 srcPix = src.(*image.Alpha16).Pix 804 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 805 bytesPerPixel = 2 806 case *image.Gray: 807 srcPix = src.(*image.Gray).Pix 808 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 809 bytesPerPixel = 1 810 case *image.Gray16: 811 srcPix = src.(*image.Gray16).Pix 812 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 813 bytesPerPixel = 2 814 case *image.NRGBA: 815 srcPix = src.(*image.NRGBA).Pix 816 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 817 bytesPerPixel = 4 818 case *image.NRGBA64: 819 srcPix = src.(*image.NRGBA64).Pix 820 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 821 bytesPerPixel = 8 822 case *image.Paletted: 823 source := src.(*image.Paletted) 824 srcPix = source.Pix 825 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 826 bytesPerPixel = 1 827 if len(target.Palette) < len(source.Palette) { 828 // readImagePass can return a paletted image whose implicit palette 829 // length (one more than the maximum Pix value) is larger than the 830 // explicit palette length (what's in the PLTE chunk). Make the 831 // same adjustment here. 832 target.Palette = source.Palette 833 } 834 case *image.RGBA: 835 srcPix = src.(*image.RGBA).Pix 836 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 837 bytesPerPixel = 4 838 case *image.RGBA64: 839 srcPix = src.(*image.RGBA64).Pix 840 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 841 bytesPerPixel = 8 842 } 843 s, bounds := 0, src.Bounds() 844 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { 845 dBase := (y*p.yFactor+p.yOffset-rect.Min.Y)*stride + (p.xOffset-rect.Min.X)*bytesPerPixel 846 for x := bounds.Min.X; x < bounds.Max.X; x++ { 847 d := dBase + x*p.xFactor*bytesPerPixel 848 copy(dstPix[d:], srcPix[s:s+bytesPerPixel]) 849 s += bytesPerPixel 850 } 851 } 852 } 853 854 func (d *decoder) parseIDAT(length uint32) (err error) { 855 d.idatLength = length 856 d.img, err = d.decode() 857 if err != nil { 858 return err 859 } 860 return d.verifyChecksum() 861 } 862 863 func (d *decoder) parseIEND(length uint32) error { 864 if length != 0 { 865 return FormatError("bad IEND length") 866 } 867 return d.verifyChecksum() 868 } 869 870 func (d *decoder) parseChunk(configOnly bool) error { 871 // Read the length and chunk type. 872 if _, err := io.ReadFull(d.r, d.tmp[:8]); err != nil { 873 return err 874 } 875 length := binary.BigEndian.Uint32(d.tmp[:4]) 876 d.crc.Reset() 877 d.crc.Write(d.tmp[4:8]) 878 879 // Read the chunk data. 880 switch string(d.tmp[4:8]) { 881 case "IHDR": 882 if d.stage != dsStart { 883 return chunkOrderError 884 } 885 d.stage = dsSeenIHDR 886 return d.parseIHDR(length) 887 case "PLTE": 888 if d.stage != dsSeenIHDR { 889 return chunkOrderError 890 } 891 d.stage = dsSeenPLTE 892 return d.parsePLTE(length) 893 case "tRNS": 894 if cbPaletted(d.cb) { 895 if d.stage != dsSeenPLTE { 896 return chunkOrderError 897 } 898 } else if cbTrueColor(d.cb) { 899 if d.stage != dsSeenIHDR && d.stage != dsSeenPLTE { 900 return chunkOrderError 901 } 902 } else if d.stage != dsSeenIHDR { 903 return chunkOrderError 904 } 905 d.stage = dsSeentRNS 906 return d.parsetRNS(length) 907 case "IDAT": 908 if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.stage == dsSeenIHDR && cbPaletted(d.cb)) { 909 return chunkOrderError 910 } else if d.stage == dsSeenIDAT { 911 // Ignore trailing zero-length or garbage IDAT chunks. 912 // 913 // This does not affect valid PNG images that contain multiple IDAT 914 // chunks, since the first call to parseIDAT below will consume all 915 // consecutive IDAT chunks required for decoding the image. 916 break 917 } 918 d.stage = dsSeenIDAT 919 if configOnly { 920 return nil 921 } 922 return d.parseIDAT(length) 923 case "IEND": 924 if d.stage != dsSeenIDAT { 925 return chunkOrderError 926 } 927 d.stage = dsSeenIEND 928 return d.parseIEND(length) 929 } 930 if length > 0x7fffffff { 931 return FormatError(fmt.Sprintf("Bad chunk length: %d", length)) 932 } 933 // Ignore this chunk (of a known length). 934 var ignored [4096]byte 935 for length > 0 { 936 n, err := io.ReadFull(d.r, ignored[:min(len(ignored), int(length))]) 937 if err != nil { 938 return err 939 } 940 d.crc.Write(ignored[:n]) 941 length -= uint32(n) 942 } 943 return d.verifyChecksum() 944 } 945 946 func (d *decoder) verifyChecksum() error { 947 if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil { 948 return err 949 } 950 if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() { 951 return FormatError("invalid checksum") 952 } 953 return nil 954 } 955 956 func (d *decoder) checkHeader() error { 957 _, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)]) 958 if err != nil { 959 return err 960 } 961 if string(d.tmp[:len(pngHeader)]) != pngHeader { 962 return FormatError("not a PNG file") 963 } 964 return nil 965 } 966 967 // Decode reads a PNG image from r and returns it as an [image.Image]. 968 // The type of Image returned depends on the PNG contents. 969 func Decode(r io.Reader) (image.Image, error) { 970 d := &decoder{ 971 r: r, 972 crc: crc32.NewIEEE(), 973 } 974 if err := d.checkHeader(); err != nil { 975 if err == io.EOF { 976 err = io.ErrUnexpectedEOF 977 } 978 return nil, err 979 } 980 for d.stage != dsSeenIEND { 981 if err := d.parseChunk(false); err != nil { 982 if err == io.EOF { 983 err = io.ErrUnexpectedEOF 984 } 985 return nil, err 986 } 987 } 988 return d.img, nil 989 } 990 991 // DecodeConfig returns the color model and dimensions of a PNG image without 992 // decoding the entire image. 993 func DecodeConfig(r io.Reader) (image.Config, error) { 994 d := &decoder{ 995 r: r, 996 crc: crc32.NewIEEE(), 997 } 998 if err := d.checkHeader(); err != nil { 999 if err == io.EOF { 1000 err = io.ErrUnexpectedEOF 1001 } 1002 return image.Config{}, err 1003 } 1004 1005 for { 1006 if err := d.parseChunk(true); err != nil { 1007 if err == io.EOF { 1008 err = io.ErrUnexpectedEOF 1009 } 1010 return image.Config{}, err 1011 } 1012 1013 if cbPaletted(d.cb) { 1014 if d.stage >= dsSeentRNS { 1015 break 1016 } 1017 } else { 1018 if d.stage >= dsSeenIHDR { 1019 break 1020 } 1021 } 1022 } 1023 1024 var cm color.Model 1025 switch d.cb { 1026 case cbG1, cbG2, cbG4, cbG8: 1027 cm = color.GrayModel 1028 case cbGA8: 1029 cm = color.NRGBAModel 1030 case cbTC8: 1031 cm = color.RGBAModel 1032 case cbP1, cbP2, cbP4, cbP8: 1033 cm = d.palette 1034 case cbTCA8: 1035 cm = color.NRGBAModel 1036 case cbG16: 1037 cm = color.Gray16Model 1038 case cbGA16: 1039 cm = color.NRGBA64Model 1040 case cbTC16: 1041 cm = color.RGBA64Model 1042 case cbTCA16: 1043 cm = color.NRGBA64Model 1044 } 1045 return image.Config{ 1046 ColorModel: cm, 1047 Width: d.width, 1048 Height: d.height, 1049 }, nil 1050 } 1051 1052 func init() { 1053 image.RegisterFormat("png", pngHeader, Decode, DecodeConfig) 1054 }