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