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