github.com/c9s/go@v0.0.0-20180120015821-984e81f64e0c/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 http://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 http://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 // http://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 nPixels := int64(w) * int64(h) 167 if nPixels != int64(int(nPixels)) { 168 return UnsupportedError("dimension overflow") 169 } 170 // There can be up to 8 bytes per pixel, for 16 bits per channel RGBA. 171 if nPixels != (nPixels*8)/8 { 172 return UnsupportedError("dimension overflow") 173 } 174 175 d.cb = cbInvalid 176 d.depth = int(d.tmp[8]) 177 switch d.depth { 178 case 1: 179 switch d.tmp[9] { 180 case ctGrayscale: 181 d.cb = cbG1 182 case ctPaletted: 183 d.cb = cbP1 184 } 185 case 2: 186 switch d.tmp[9] { 187 case ctGrayscale: 188 d.cb = cbG2 189 case ctPaletted: 190 d.cb = cbP2 191 } 192 case 4: 193 switch d.tmp[9] { 194 case ctGrayscale: 195 d.cb = cbG4 196 case ctPaletted: 197 d.cb = cbP4 198 } 199 case 8: 200 switch d.tmp[9] { 201 case ctGrayscale: 202 d.cb = cbG8 203 case ctTrueColor: 204 d.cb = cbTC8 205 case ctPaletted: 206 d.cb = cbP8 207 case ctGrayscaleAlpha: 208 d.cb = cbGA8 209 case ctTrueColorAlpha: 210 d.cb = cbTCA8 211 } 212 case 16: 213 switch d.tmp[9] { 214 case ctGrayscale: 215 d.cb = cbG16 216 case ctTrueColor: 217 d.cb = cbTC16 218 case ctGrayscaleAlpha: 219 d.cb = cbGA16 220 case ctTrueColorAlpha: 221 d.cb = cbTCA16 222 } 223 } 224 if d.cb == cbInvalid { 225 return UnsupportedError(fmt.Sprintf("bit depth %d, color type %d", d.tmp[8], d.tmp[9])) 226 } 227 d.width, d.height = int(w), int(h) 228 return d.verifyChecksum() 229 } 230 231 func (d *decoder) parsePLTE(length uint32) error { 232 np := int(length / 3) // The number of palette entries. 233 if length%3 != 0 || np <= 0 || np > 256 || np > 1<<uint(d.depth) { 234 return FormatError("bad PLTE length") 235 } 236 n, err := io.ReadFull(d.r, d.tmp[:3*np]) 237 if err != nil { 238 return err 239 } 240 d.crc.Write(d.tmp[:n]) 241 switch d.cb { 242 case cbP1, cbP2, cbP4, cbP8: 243 d.palette = make(color.Palette, 256) 244 for i := 0; i < np; i++ { 245 d.palette[i] = color.RGBA{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff} 246 } 247 for i := np; i < 256; i++ { 248 // Initialize the rest of the palette to opaque black. The spec (section 249 // 11.2.3) says that "any out-of-range pixel value found in the image data 250 // is an error", but some real-world PNG files have out-of-range pixel 251 // values. We fall back to opaque black, the same as libpng 1.5.13; 252 // ImageMagick 6.5.7 returns an error. 253 d.palette[i] = color.RGBA{0x00, 0x00, 0x00, 0xff} 254 } 255 d.palette = d.palette[:np] 256 case cbTC8, cbTCA8, cbTC16, cbTCA16: 257 // As per the PNG spec, a PLTE chunk is optional (and for practical purposes, 258 // ignorable) for the ctTrueColor and ctTrueColorAlpha color types (section 4.1.2). 259 default: 260 return FormatError("PLTE, color type mismatch") 261 } 262 return d.verifyChecksum() 263 } 264 265 func (d *decoder) parsetRNS(length uint32) error { 266 switch d.cb { 267 case cbG1, cbG2, cbG4, cbG8, cbG16: 268 if length != 2 { 269 return FormatError("bad tRNS length") 270 } 271 n, err := io.ReadFull(d.r, d.tmp[:length]) 272 if err != nil { 273 return err 274 } 275 d.crc.Write(d.tmp[:n]) 276 277 copy(d.transparent[:], d.tmp[:length]) 278 switch d.cb { 279 case cbG1: 280 d.transparent[1] *= 0xff 281 case cbG2: 282 d.transparent[1] *= 0x55 283 case cbG4: 284 d.transparent[1] *= 0x11 285 } 286 d.useTransparent = true 287 288 case cbTC8, cbTC16: 289 if length != 6 { 290 return FormatError("bad tRNS length") 291 } 292 n, err := io.ReadFull(d.r, d.tmp[:length]) 293 if err != nil { 294 return err 295 } 296 d.crc.Write(d.tmp[:n]) 297 298 copy(d.transparent[:], d.tmp[:length]) 299 d.useTransparent = true 300 301 case cbP1, cbP2, cbP4, cbP8: 302 if length > 256 { 303 return FormatError("bad tRNS length") 304 } 305 n, err := io.ReadFull(d.r, d.tmp[:length]) 306 if err != nil { 307 return err 308 } 309 d.crc.Write(d.tmp[:n]) 310 311 if len(d.palette) < n { 312 d.palette = d.palette[:n] 313 } 314 for i := 0; i < n; i++ { 315 rgba := d.palette[i].(color.RGBA) 316 d.palette[i] = color.NRGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]} 317 } 318 319 default: 320 return FormatError("tRNS, color type mismatch") 321 } 322 return d.verifyChecksum() 323 } 324 325 // Read presents one or more IDAT chunks as one continuous stream (minus the 326 // intermediate chunk headers and footers). If the PNG data looked like: 327 // ... len0 IDAT xxx crc0 len1 IDAT yy crc1 len2 IEND crc2 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 + (bitsPerPixel*width+7)/8 502 // cr and pr are the bytes for the current and previous row. 503 cr := make([]uint8, rowSize) 504 pr := make([]uint8, rowSize) 505 506 for y := 0; y < height; y++ { 507 // Read the decompressed bytes. 508 _, err := io.ReadFull(r, cr) 509 if err != nil { 510 if err == io.EOF || err == io.ErrUnexpectedEOF { 511 return nil, FormatError("not enough pixel data") 512 } 513 return nil, err 514 } 515 516 // Apply the filter. 517 cdat := cr[1:] 518 pdat := pr[1:] 519 switch cr[0] { 520 case ftNone: 521 // No-op. 522 case ftSub: 523 for i := bytesPerPixel; i < len(cdat); i++ { 524 cdat[i] += cdat[i-bytesPerPixel] 525 } 526 case ftUp: 527 for i, p := range pdat { 528 cdat[i] += p 529 } 530 case ftAverage: 531 // The first column has no column to the left of it, so it is a 532 // special case. We know that the first column exists because we 533 // check above that width != 0, and so len(cdat) != 0. 534 for i := 0; i < bytesPerPixel; i++ { 535 cdat[i] += pdat[i] / 2 536 } 537 for i := bytesPerPixel; i < len(cdat); i++ { 538 cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2) 539 } 540 case ftPaeth: 541 filterPaeth(cdat, pdat, bytesPerPixel) 542 default: 543 return nil, FormatError("bad filter type") 544 } 545 546 // Convert from bytes to colors. 547 switch d.cb { 548 case cbG1: 549 if d.useTransparent { 550 ty := d.transparent[1] 551 for x := 0; x < width; x += 8 { 552 b := cdat[x/8] 553 for x2 := 0; x2 < 8 && x+x2 < width; x2++ { 554 ycol := (b >> 7) * 0xff 555 acol := uint8(0xff) 556 if ycol == ty { 557 acol = 0x00 558 } 559 nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol}) 560 b <<= 1 561 } 562 } 563 } else { 564 for x := 0; x < width; x += 8 { 565 b := cdat[x/8] 566 for x2 := 0; x2 < 8 && x+x2 < width; x2++ { 567 gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff}) 568 b <<= 1 569 } 570 } 571 } 572 case cbG2: 573 if d.useTransparent { 574 ty := d.transparent[1] 575 for x := 0; x < width; x += 4 { 576 b := cdat[x/4] 577 for x2 := 0; x2 < 4 && x+x2 < width; x2++ { 578 ycol := (b >> 6) * 0x55 579 acol := uint8(0xff) 580 if ycol == ty { 581 acol = 0x00 582 } 583 nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol}) 584 b <<= 2 585 } 586 } 587 } else { 588 for x := 0; x < width; x += 4 { 589 b := cdat[x/4] 590 for x2 := 0; x2 < 4 && x+x2 < width; x2++ { 591 gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55}) 592 b <<= 2 593 } 594 } 595 } 596 case cbG4: 597 if d.useTransparent { 598 ty := d.transparent[1] 599 for x := 0; x < width; x += 2 { 600 b := cdat[x/2] 601 for x2 := 0; x2 < 2 && x+x2 < width; x2++ { 602 ycol := (b >> 4) * 0x11 603 acol := uint8(0xff) 604 if ycol == ty { 605 acol = 0x00 606 } 607 nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol}) 608 b <<= 4 609 } 610 } 611 } else { 612 for x := 0; x < width; x += 2 { 613 b := cdat[x/2] 614 for x2 := 0; x2 < 2 && x+x2 < width; x2++ { 615 gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11}) 616 b <<= 4 617 } 618 } 619 } 620 case cbG8: 621 if d.useTransparent { 622 ty := d.transparent[1] 623 for x := 0; x < width; x++ { 624 ycol := cdat[x] 625 acol := uint8(0xff) 626 if ycol == ty { 627 acol = 0x00 628 } 629 nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, acol}) 630 } 631 } else { 632 copy(gray.Pix[pixOffset:], cdat) 633 pixOffset += gray.Stride 634 } 635 case cbGA8: 636 for x := 0; x < width; x++ { 637 ycol := cdat[2*x+0] 638 nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]}) 639 } 640 case cbTC8: 641 if d.useTransparent { 642 pix, i, j := nrgba.Pix, pixOffset, 0 643 tr, tg, tb := d.transparent[1], d.transparent[3], d.transparent[5] 644 for x := 0; x < width; x++ { 645 r := cdat[j+0] 646 g := cdat[j+1] 647 b := cdat[j+2] 648 a := uint8(0xff) 649 if r == tr && g == tg && b == tb { 650 a = 0x00 651 } 652 pix[i+0] = r 653 pix[i+1] = g 654 pix[i+2] = b 655 pix[i+3] = a 656 i += 4 657 j += 3 658 } 659 pixOffset += nrgba.Stride 660 } else { 661 pix, i, j := rgba.Pix, pixOffset, 0 662 for x := 0; x < width; x++ { 663 pix[i+0] = cdat[j+0] 664 pix[i+1] = cdat[j+1] 665 pix[i+2] = cdat[j+2] 666 pix[i+3] = 0xff 667 i += 4 668 j += 3 669 } 670 pixOffset += rgba.Stride 671 } 672 case cbP1: 673 for x := 0; x < width; x += 8 { 674 b := cdat[x/8] 675 for x2 := 0; x2 < 8 && x+x2 < width; x2++ { 676 idx := b >> 7 677 if len(paletted.Palette) <= int(idx) { 678 paletted.Palette = paletted.Palette[:int(idx)+1] 679 } 680 paletted.SetColorIndex(x+x2, y, idx) 681 b <<= 1 682 } 683 } 684 case cbP2: 685 for x := 0; x < width; x += 4 { 686 b := cdat[x/4] 687 for x2 := 0; x2 < 4 && x+x2 < width; x2++ { 688 idx := b >> 6 689 if len(paletted.Palette) <= int(idx) { 690 paletted.Palette = paletted.Palette[:int(idx)+1] 691 } 692 paletted.SetColorIndex(x+x2, y, idx) 693 b <<= 2 694 } 695 } 696 case cbP4: 697 for x := 0; x < width; x += 2 { 698 b := cdat[x/2] 699 for x2 := 0; x2 < 2 && x+x2 < width; x2++ { 700 idx := b >> 4 701 if len(paletted.Palette) <= int(idx) { 702 paletted.Palette = paletted.Palette[:int(idx)+1] 703 } 704 paletted.SetColorIndex(x+x2, y, idx) 705 b <<= 4 706 } 707 } 708 case cbP8: 709 if len(paletted.Palette) != 255 { 710 for x := 0; x < width; x++ { 711 if len(paletted.Palette) <= int(cdat[x]) { 712 paletted.Palette = paletted.Palette[:int(cdat[x])+1] 713 } 714 } 715 } 716 copy(paletted.Pix[pixOffset:], cdat) 717 pixOffset += paletted.Stride 718 case cbTCA8: 719 copy(nrgba.Pix[pixOffset:], cdat) 720 pixOffset += nrgba.Stride 721 case cbG16: 722 if d.useTransparent { 723 ty := uint16(d.transparent[0])<<8 | uint16(d.transparent[1]) 724 for x := 0; x < width; x++ { 725 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1]) 726 acol := uint16(0xffff) 727 if ycol == ty { 728 acol = 0x0000 729 } 730 nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol}) 731 } 732 } else { 733 for x := 0; x < width; x++ { 734 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1]) 735 gray16.SetGray16(x, y, color.Gray16{ycol}) 736 } 737 } 738 case cbGA16: 739 for x := 0; x < width; x++ { 740 ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1]) 741 acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3]) 742 nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol}) 743 } 744 case cbTC16: 745 if d.useTransparent { 746 tr := uint16(d.transparent[0])<<8 | uint16(d.transparent[1]) 747 tg := uint16(d.transparent[2])<<8 | uint16(d.transparent[3]) 748 tb := uint16(d.transparent[4])<<8 | uint16(d.transparent[5]) 749 for x := 0; x < width; x++ { 750 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1]) 751 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3]) 752 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5]) 753 acol := uint16(0xffff) 754 if rcol == tr && gcol == tg && bcol == tb { 755 acol = 0x0000 756 } 757 nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol}) 758 } 759 } else { 760 for x := 0; x < width; x++ { 761 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1]) 762 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3]) 763 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5]) 764 rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff}) 765 } 766 } 767 case cbTCA16: 768 for x := 0; x < width; x++ { 769 rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1]) 770 gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3]) 771 bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5]) 772 acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7]) 773 nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol}) 774 } 775 } 776 777 // The current row for y is the previous row for y+1. 778 pr, cr = cr, pr 779 } 780 781 return img, nil 782 } 783 784 // mergePassInto merges a single pass into a full sized image. 785 func (d *decoder) mergePassInto(dst image.Image, src image.Image, pass int) { 786 p := interlacing[pass] 787 var ( 788 srcPix []uint8 789 dstPix []uint8 790 stride int 791 rect image.Rectangle 792 bytesPerPixel int 793 ) 794 switch target := dst.(type) { 795 case *image.Alpha: 796 srcPix = src.(*image.Alpha).Pix 797 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 798 bytesPerPixel = 1 799 case *image.Alpha16: 800 srcPix = src.(*image.Alpha16).Pix 801 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 802 bytesPerPixel = 2 803 case *image.Gray: 804 srcPix = src.(*image.Gray).Pix 805 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 806 bytesPerPixel = 1 807 case *image.Gray16: 808 srcPix = src.(*image.Gray16).Pix 809 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 810 bytesPerPixel = 2 811 case *image.NRGBA: 812 srcPix = src.(*image.NRGBA).Pix 813 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 814 bytesPerPixel = 4 815 case *image.NRGBA64: 816 srcPix = src.(*image.NRGBA64).Pix 817 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 818 bytesPerPixel = 8 819 case *image.Paletted: 820 srcPix = src.(*image.Paletted).Pix 821 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 822 bytesPerPixel = 1 823 case *image.RGBA: 824 srcPix = src.(*image.RGBA).Pix 825 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 826 bytesPerPixel = 4 827 case *image.RGBA64: 828 srcPix = src.(*image.RGBA64).Pix 829 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 830 bytesPerPixel = 8 831 } 832 s, bounds := 0, src.Bounds() 833 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { 834 dBase := (y*p.yFactor+p.yOffset-rect.Min.Y)*stride + (p.xOffset-rect.Min.X)*bytesPerPixel 835 for x := bounds.Min.X; x < bounds.Max.X; x++ { 836 d := dBase + x*p.xFactor*bytesPerPixel 837 copy(dstPix[d:], srcPix[s:s+bytesPerPixel]) 838 s += bytesPerPixel 839 } 840 } 841 } 842 843 func (d *decoder) parseIDAT(length uint32) (err error) { 844 d.idatLength = length 845 d.img, err = d.decode() 846 if err != nil { 847 return err 848 } 849 return d.verifyChecksum() 850 } 851 852 func (d *decoder) parseIEND(length uint32) error { 853 if length != 0 { 854 return FormatError("bad IEND length") 855 } 856 return d.verifyChecksum() 857 } 858 859 func (d *decoder) parseChunk() error { 860 // Read the length and chunk type. 861 n, err := io.ReadFull(d.r, d.tmp[:8]) 862 if err != nil { 863 return err 864 } 865 length := binary.BigEndian.Uint32(d.tmp[:4]) 866 d.crc.Reset() 867 d.crc.Write(d.tmp[4:8]) 868 869 // Read the chunk data. 870 switch string(d.tmp[4:8]) { 871 case "IHDR": 872 if d.stage != dsStart { 873 return chunkOrderError 874 } 875 d.stage = dsSeenIHDR 876 return d.parseIHDR(length) 877 case "PLTE": 878 if d.stage != dsSeenIHDR { 879 return chunkOrderError 880 } 881 d.stage = dsSeenPLTE 882 return d.parsePLTE(length) 883 case "tRNS": 884 if cbPaletted(d.cb) { 885 if d.stage != dsSeenPLTE { 886 return chunkOrderError 887 } 888 } else if d.stage != dsSeenIHDR { 889 return chunkOrderError 890 } 891 d.stage = dsSeentRNS 892 return d.parsetRNS(length) 893 case "IDAT": 894 if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.stage == dsSeenIHDR && cbPaletted(d.cb)) { 895 return chunkOrderError 896 } else if d.stage == dsSeenIDAT { 897 // Ignore trailing zero-length or garbage IDAT chunks. 898 // 899 // This does not affect valid PNG images that contain multiple IDAT 900 // chunks, since the first call to parseIDAT below will consume all 901 // consecutive IDAT chunks required for decoding the image. 902 break 903 } 904 d.stage = dsSeenIDAT 905 return d.parseIDAT(length) 906 case "IEND": 907 if d.stage != dsSeenIDAT { 908 return chunkOrderError 909 } 910 d.stage = dsSeenIEND 911 return d.parseIEND(length) 912 } 913 if length > 0x7fffffff { 914 return FormatError(fmt.Sprintf("Bad chunk length: %d", length)) 915 } 916 // Ignore this chunk (of a known length). 917 var ignored [4096]byte 918 for length > 0 { 919 n, err = io.ReadFull(d.r, ignored[:min(len(ignored), int(length))]) 920 if err != nil { 921 return err 922 } 923 d.crc.Write(ignored[:n]) 924 length -= uint32(n) 925 } 926 return d.verifyChecksum() 927 } 928 929 func (d *decoder) verifyChecksum() error { 930 if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil { 931 return err 932 } 933 if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() { 934 return FormatError("invalid checksum") 935 } 936 return nil 937 } 938 939 func (d *decoder) checkHeader() error { 940 _, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)]) 941 if err != nil { 942 return err 943 } 944 if string(d.tmp[:len(pngHeader)]) != pngHeader { 945 return FormatError("not a PNG file") 946 } 947 return nil 948 } 949 950 // Decode reads a PNG image from r and returns it as an image.Image. 951 // The type of Image returned depends on the PNG contents. 952 func Decode(r io.Reader) (image.Image, error) { 953 d := &decoder{ 954 r: r, 955 crc: crc32.NewIEEE(), 956 } 957 if err := d.checkHeader(); err != nil { 958 if err == io.EOF { 959 err = io.ErrUnexpectedEOF 960 } 961 return nil, err 962 } 963 for d.stage != dsSeenIEND { 964 if err := d.parseChunk(); err != nil { 965 if err == io.EOF { 966 err = io.ErrUnexpectedEOF 967 } 968 return nil, err 969 } 970 } 971 return d.img, nil 972 } 973 974 // DecodeConfig returns the color model and dimensions of a PNG image without 975 // decoding the entire image. 976 func DecodeConfig(r io.Reader) (image.Config, 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 image.Config{}, err 986 } 987 for { 988 if err := d.parseChunk(); err != nil { 989 if err == io.EOF { 990 err = io.ErrUnexpectedEOF 991 } 992 return image.Config{}, err 993 } 994 paletted := cbPaletted(d.cb) 995 if d.stage == dsSeenIHDR && !paletted { 996 break 997 } 998 if d.stage == dsSeenPLTE && paletted { 999 break 1000 } 1001 } 1002 var cm color.Model 1003 switch d.cb { 1004 case cbG1, cbG2, cbG4, cbG8: 1005 cm = color.GrayModel 1006 case cbGA8: 1007 cm = color.NRGBAModel 1008 case cbTC8: 1009 cm = color.RGBAModel 1010 case cbP1, cbP2, cbP4, cbP8: 1011 cm = d.palette 1012 case cbTCA8: 1013 cm = color.NRGBAModel 1014 case cbG16: 1015 cm = color.Gray16Model 1016 case cbGA16: 1017 cm = color.NRGBA64Model 1018 case cbTC16: 1019 cm = color.RGBA64Model 1020 case cbTCA16: 1021 cm = color.NRGBA64Model 1022 } 1023 return image.Config{ 1024 ColorModel: cm, 1025 Width: d.width, 1026 Height: d.height, 1027 }, nil 1028 } 1029 1030 func init() { 1031 image.RegisterFormat("png", pngHeader, Decode, DecodeConfig) 1032 }