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