github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/pkg/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 // Filter type, as per the PNG spec. 51 const ( 52 ftNone = 0 53 ftSub = 1 54 ftUp = 2 55 ftAverage = 3 56 ftPaeth = 4 57 nFilter = 5 58 ) 59 60 // Decoding stage. 61 // The PNG specification says that the IHDR, PLTE (if present), IDAT and IEND 62 // chunks must appear in that order. There may be multiple IDAT chunks, and 63 // IDAT chunks must be sequential (i.e. they may not have any other chunks 64 // between them). 65 // http://www.w3.org/TR/PNG/#5ChunkOrdering 66 const ( 67 dsStart = iota 68 dsSeenIHDR 69 dsSeenPLTE 70 dsSeenIDAT 71 dsSeenIEND 72 ) 73 74 const pngHeader = "\x89PNG\r\n\x1a\n" 75 76 type decoder struct { 77 r io.Reader 78 img image.Image 79 crc hash.Hash32 80 width, height int 81 depth int 82 palette color.Palette 83 cb int 84 stage int 85 idatLength uint32 86 tmp [3 * 256]byte 87 } 88 89 // A FormatError reports that the input is not a valid PNG. 90 type FormatError string 91 92 func (e FormatError) Error() string { return "png: invalid format: " + string(e) } 93 94 var chunkOrderError = FormatError("chunk out of order") 95 96 // An UnsupportedError reports that the input uses a valid but unimplemented PNG feature. 97 type UnsupportedError string 98 99 func (e UnsupportedError) Error() string { return "png: unsupported feature: " + string(e) } 100 101 func min(a, b int) int { 102 if a < b { 103 return a 104 } 105 return b 106 } 107 108 func (d *decoder) parseIHDR(length uint32) error { 109 if length != 13 { 110 return FormatError("bad IHDR length") 111 } 112 if _, err := io.ReadFull(d.r, d.tmp[:13]); err != nil { 113 return err 114 } 115 d.crc.Write(d.tmp[:13]) 116 if d.tmp[10] != 0 || d.tmp[11] != 0 || d.tmp[12] != 0 { 117 return UnsupportedError("compression, filter or interlace method") 118 } 119 w := int32(binary.BigEndian.Uint32(d.tmp[0:4])) 120 h := int32(binary.BigEndian.Uint32(d.tmp[4:8])) 121 if w < 0 || h < 0 { 122 return FormatError("negative dimension") 123 } 124 nPixels := int64(w) * int64(h) 125 if nPixels != int64(int(nPixels)) { 126 return UnsupportedError("dimension overflow") 127 } 128 d.cb = cbInvalid 129 d.depth = int(d.tmp[8]) 130 switch d.depth { 131 case 1: 132 switch d.tmp[9] { 133 case ctGrayscale: 134 d.cb = cbG1 135 case ctPaletted: 136 d.cb = cbP1 137 } 138 case 2: 139 switch d.tmp[9] { 140 case ctGrayscale: 141 d.cb = cbG2 142 case ctPaletted: 143 d.cb = cbP2 144 } 145 case 4: 146 switch d.tmp[9] { 147 case ctGrayscale: 148 d.cb = cbG4 149 case ctPaletted: 150 d.cb = cbP4 151 } 152 case 8: 153 switch d.tmp[9] { 154 case ctGrayscale: 155 d.cb = cbG8 156 case ctTrueColor: 157 d.cb = cbTC8 158 case ctPaletted: 159 d.cb = cbP8 160 case ctGrayscaleAlpha: 161 d.cb = cbGA8 162 case ctTrueColorAlpha: 163 d.cb = cbTCA8 164 } 165 case 16: 166 switch d.tmp[9] { 167 case ctGrayscale: 168 d.cb = cbG16 169 case ctTrueColor: 170 d.cb = cbTC16 171 case ctGrayscaleAlpha: 172 d.cb = cbGA16 173 case ctTrueColorAlpha: 174 d.cb = cbTCA16 175 } 176 } 177 if d.cb == cbInvalid { 178 return UnsupportedError(fmt.Sprintf("bit depth %d, color type %d", d.tmp[8], d.tmp[9])) 179 } 180 d.width, d.height = int(w), int(h) 181 return d.verifyChecksum() 182 } 183 184 func (d *decoder) parsePLTE(length uint32) error { 185 np := int(length / 3) // The number of palette entries. 186 if length%3 != 0 || np <= 0 || np > 256 || np > 1<<uint(d.depth) { 187 return FormatError("bad PLTE length") 188 } 189 n, err := io.ReadFull(d.r, d.tmp[:3*np]) 190 if err != nil { 191 return err 192 } 193 d.crc.Write(d.tmp[:n]) 194 switch d.cb { 195 case cbP1, cbP2, cbP4, cbP8: 196 d.palette = make(color.Palette, 256) 197 for i := 0; i < np; i++ { 198 d.palette[i] = color.RGBA{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff} 199 } 200 for i := np; i < 256; i++ { 201 // Initialize the rest of the palette to opaque black. The spec (section 202 // 11.2.3) says that "any out-of-range pixel value found in the image data 203 // is an error", but some real-world PNG files have out-of-range pixel 204 // values. We fall back to opaque black, the same as libpng 1.5.13; 205 // ImageMagick 6.5.7 returns an error. 206 d.palette[i] = color.RGBA{0x00, 0x00, 0x00, 0xff} 207 } 208 d.palette = d.palette[:np] 209 case cbTC8, cbTCA8, cbTC16, cbTCA16: 210 // As per the PNG spec, a PLTE chunk is optional (and for practical purposes, 211 // ignorable) for the ctTrueColor and ctTrueColorAlpha color types (section 4.1.2). 212 default: 213 return FormatError("PLTE, color type mismatch") 214 } 215 return d.verifyChecksum() 216 } 217 218 func (d *decoder) parsetRNS(length uint32) error { 219 if length > 256 { 220 return FormatError("bad tRNS length") 221 } 222 n, err := io.ReadFull(d.r, d.tmp[:length]) 223 if err != nil { 224 return err 225 } 226 d.crc.Write(d.tmp[:n]) 227 switch d.cb { 228 case cbG8, cbG16: 229 return UnsupportedError("grayscale transparency") 230 case cbTC8, cbTC16: 231 return UnsupportedError("truecolor transparency") 232 case cbP1, cbP2, cbP4, cbP8: 233 if len(d.palette) < n { 234 d.palette = d.palette[:n] 235 } 236 for i := 0; i < n; i++ { 237 rgba := d.palette[i].(color.RGBA) 238 d.palette[i] = color.NRGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]} 239 } 240 case cbGA8, cbGA16, cbTCA8, cbTCA16: 241 return FormatError("tRNS, color type mismatch") 242 } 243 return d.verifyChecksum() 244 } 245 246 // Read presents one or more IDAT chunks as one continuous stream (minus the 247 // intermediate chunk headers and footers). If the PNG data looked like: 248 // ... len0 IDAT xxx crc0 len1 IDAT yy crc1 len2 IEND crc2 249 // then this reader presents xxxyy. For well-formed PNG data, the decoder state 250 // immediately before the first Read call is that d.r is positioned between the 251 // first IDAT and xxx, and the decoder state immediately after the last Read 252 // call is that d.r is positioned between yy and crc1. 253 func (d *decoder) Read(p []byte) (int, error) { 254 if len(p) == 0 { 255 return 0, nil 256 } 257 for d.idatLength == 0 { 258 // We have exhausted an IDAT chunk. Verify the checksum of that chunk. 259 if err := d.verifyChecksum(); err != nil { 260 return 0, err 261 } 262 // Read the length and chunk type of the next chunk, and check that 263 // it is an IDAT chunk. 264 if _, err := io.ReadFull(d.r, d.tmp[:8]); err != nil { 265 return 0, err 266 } 267 d.idatLength = binary.BigEndian.Uint32(d.tmp[:4]) 268 if string(d.tmp[4:8]) != "IDAT" { 269 return 0, FormatError("not enough pixel data") 270 } 271 d.crc.Reset() 272 d.crc.Write(d.tmp[4:8]) 273 } 274 if int(d.idatLength) < 0 { 275 return 0, UnsupportedError("IDAT chunk length overflow") 276 } 277 n, err := d.r.Read(p[:min(len(p), int(d.idatLength))]) 278 d.crc.Write(p[:n]) 279 d.idatLength -= uint32(n) 280 return n, err 281 } 282 283 // decode decodes the IDAT data into an image. 284 func (d *decoder) decode() (image.Image, error) { 285 r, err := zlib.NewReader(d) 286 if err != nil { 287 return nil, err 288 } 289 defer r.Close() 290 bitsPerPixel := 0 291 pixOffset := 0 292 var ( 293 gray *image.Gray 294 rgba *image.RGBA 295 paletted *image.Paletted 296 nrgba *image.NRGBA 297 gray16 *image.Gray16 298 rgba64 *image.RGBA64 299 nrgba64 *image.NRGBA64 300 img image.Image 301 ) 302 switch d.cb { 303 case cbG1, cbG2, cbG4, cbG8: 304 bitsPerPixel = d.depth 305 gray = image.NewGray(image.Rect(0, 0, d.width, d.height)) 306 img = gray 307 case cbGA8: 308 bitsPerPixel = 16 309 nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height)) 310 img = nrgba 311 case cbTC8: 312 bitsPerPixel = 24 313 rgba = image.NewRGBA(image.Rect(0, 0, d.width, d.height)) 314 img = rgba 315 case cbP1, cbP2, cbP4, cbP8: 316 bitsPerPixel = d.depth 317 paletted = image.NewPaletted(image.Rect(0, 0, d.width, d.height), d.palette) 318 img = paletted 319 case cbTCA8: 320 bitsPerPixel = 32 321 nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height)) 322 img = nrgba 323 case cbG16: 324 bitsPerPixel = 16 325 gray16 = image.NewGray16(image.Rect(0, 0, d.width, d.height)) 326 img = gray16 327 case cbGA16: 328 bitsPerPixel = 32 329 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height)) 330 img = nrgba64 331 case cbTC16: 332 bitsPerPixel = 48 333 rgba64 = image.NewRGBA64(image.Rect(0, 0, d.width, d.height)) 334 img = rgba64 335 case cbTCA16: 336 bitsPerPixel = 64 337 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height)) 338 img = nrgba64 339 } 340 bytesPerPixel := (bitsPerPixel + 7) / 8 341 342 // cr and pr are the bytes for the current and previous row. 343 // The +1 is for the per-row filter type, which is at cr[0]. 344 cr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8) 345 pr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8) 346 347 for y := 0; y < d.height; y++ { 348 // Read the decompressed bytes. 349 _, err := io.ReadFull(r, cr) 350 if err != nil { 351 return nil, err 352 } 353 354 // Apply the filter. 355 cdat := cr[1:] 356 pdat := pr[1:] 357 switch cr[0] { 358 case ftNone: 359 // No-op. 360 case ftSub: 361 for i := bytesPerPixel; i < len(cdat); i++ { 362 cdat[i] += cdat[i-bytesPerPixel] 363 } 364 case ftUp: 365 for i, p := range pdat { 366 cdat[i] += p 367 } 368 case ftAverage: 369 for i := 0; i < bytesPerPixel; i++ { 370 cdat[i] += pdat[i] / 2 371 } 372 for i := bytesPerPixel; i < len(cdat); i++ { 373 cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2) 374 } 375 case ftPaeth: 376 filterPaeth(cdat, pdat, bytesPerPixel) 377 default: 378 return nil, FormatError("bad filter type") 379 } 380 381 // Convert from bytes to colors. 382 switch d.cb { 383 case cbG1: 384 for x := 0; x < d.width; x += 8 { 385 b := cdat[x/8] 386 for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ { 387 gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff}) 388 b <<= 1 389 } 390 } 391 case cbG2: 392 for x := 0; x < d.width; x += 4 { 393 b := cdat[x/4] 394 for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ { 395 gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55}) 396 b <<= 2 397 } 398 } 399 case cbG4: 400 for x := 0; x < d.width; x += 2 { 401 b := cdat[x/2] 402 for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ { 403 gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11}) 404 b <<= 4 405 } 406 } 407 case cbG8: 408 copy(gray.Pix[pixOffset:], cdat) 409 pixOffset += gray.Stride 410 case cbGA8: 411 for x := 0; x < d.width; x++ { 412 ycol := cdat[2*x+0] 413 nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]}) 414 } 415 case cbTC8: 416 pix, i, j := rgba.Pix, pixOffset, 0 417 for x := 0; x < d.width; x++ { 418 pix[i+0] = cdat[j+0] 419 pix[i+1] = cdat[j+1] 420 pix[i+2] = cdat[j+2] 421 pix[i+3] = 0xff 422 i += 4 423 j += 3 424 } 425 pixOffset += rgba.Stride 426 case cbP1: 427 for x := 0; x < d.width; x += 8 { 428 b := cdat[x/8] 429 for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ { 430 idx := b >> 7 431 if len(paletted.Palette) <= int(idx) { 432 paletted.Palette = paletted.Palette[:int(idx)+1] 433 } 434 paletted.SetColorIndex(x+x2, y, idx) 435 b <<= 1 436 } 437 } 438 case cbP2: 439 for x := 0; x < d.width; x += 4 { 440 b := cdat[x/4] 441 for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ { 442 idx := b >> 6 443 if len(paletted.Palette) <= int(idx) { 444 paletted.Palette = paletted.Palette[:int(idx)+1] 445 } 446 paletted.SetColorIndex(x+x2, y, idx) 447 b <<= 2 448 } 449 } 450 case cbP4: 451 for x := 0; x < d.width; x += 2 { 452 b := cdat[x/2] 453 for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ { 454 idx := b >> 4 455 if len(paletted.Palette) <= int(idx) { 456 paletted.Palette = paletted.Palette[:int(idx)+1] 457 } 458 paletted.SetColorIndex(x+x2, y, idx) 459 b <<= 4 460 } 461 } 462 case cbP8: 463 if len(paletted.Palette) != 255 { 464 for x := 0; x < d.width; x++ { 465 if len(paletted.Palette) <= int(cdat[x]) { 466 paletted.Palette = paletted.Palette[:int(cdat[x])+1] 467 } 468 } 469 } 470 copy(paletted.Pix[pixOffset:], cdat) 471 pixOffset += paletted.Stride 472 case cbTCA8: 473 copy(nrgba.Pix[pixOffset:], cdat) 474 pixOffset += nrgba.Stride 475 case cbG16: 476 for x := 0; x < d.width; x++ { 477 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1]) 478 gray16.SetGray16(x, y, color.Gray16{ycol}) 479 } 480 case cbGA16: 481 for x := 0; x < d.width; x++ { 482 ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1]) 483 acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3]) 484 nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol}) 485 } 486 case cbTC16: 487 for x := 0; x < d.width; x++ { 488 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1]) 489 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3]) 490 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5]) 491 rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff}) 492 } 493 case cbTCA16: 494 for x := 0; x < d.width; x++ { 495 rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1]) 496 gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3]) 497 bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5]) 498 acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7]) 499 nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol}) 500 } 501 } 502 503 // The current row for y is the previous row for y+1. 504 pr, cr = cr, pr 505 } 506 507 // Check for EOF, to verify the zlib checksum. 508 n := 0 509 for i := 0; n == 0 && err == nil; i++ { 510 if i == 100 { 511 return nil, io.ErrNoProgress 512 } 513 n, err = r.Read(pr[:1]) 514 } 515 if err != nil && err != io.EOF { 516 return nil, FormatError(err.Error()) 517 } 518 if n != 0 || d.idatLength != 0 { 519 return nil, FormatError("too much pixel data") 520 } 521 522 return img, nil 523 } 524 525 func (d *decoder) parseIDAT(length uint32) (err error) { 526 d.idatLength = length 527 d.img, err = d.decode() 528 if err != nil { 529 return err 530 } 531 return d.verifyChecksum() 532 } 533 534 func (d *decoder) parseIEND(length uint32) error { 535 if length != 0 { 536 return FormatError("bad IEND length") 537 } 538 return d.verifyChecksum() 539 } 540 541 func (d *decoder) parseChunk() error { 542 // Read the length and chunk type. 543 n, err := io.ReadFull(d.r, d.tmp[:8]) 544 if err != nil { 545 return err 546 } 547 length := binary.BigEndian.Uint32(d.tmp[:4]) 548 d.crc.Reset() 549 d.crc.Write(d.tmp[4:8]) 550 551 // Read the chunk data. 552 switch string(d.tmp[4:8]) { 553 case "IHDR": 554 if d.stage != dsStart { 555 return chunkOrderError 556 } 557 d.stage = dsSeenIHDR 558 return d.parseIHDR(length) 559 case "PLTE": 560 if d.stage != dsSeenIHDR { 561 return chunkOrderError 562 } 563 d.stage = dsSeenPLTE 564 return d.parsePLTE(length) 565 case "tRNS": 566 if d.stage != dsSeenPLTE { 567 return chunkOrderError 568 } 569 return d.parsetRNS(length) 570 case "IDAT": 571 if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.cb == cbP8 && d.stage == dsSeenIHDR) { 572 return chunkOrderError 573 } 574 d.stage = dsSeenIDAT 575 return d.parseIDAT(length) 576 case "IEND": 577 if d.stage != dsSeenIDAT { 578 return chunkOrderError 579 } 580 d.stage = dsSeenIEND 581 return d.parseIEND(length) 582 } 583 // Ignore this chunk (of a known length). 584 var ignored [4096]byte 585 for length > 0 { 586 n, err = io.ReadFull(d.r, ignored[:min(len(ignored), int(length))]) 587 if err != nil { 588 return err 589 } 590 d.crc.Write(ignored[:n]) 591 length -= uint32(n) 592 } 593 return d.verifyChecksum() 594 } 595 596 func (d *decoder) verifyChecksum() error { 597 if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil { 598 return err 599 } 600 if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() { 601 return FormatError("invalid checksum") 602 } 603 return nil 604 } 605 606 func (d *decoder) checkHeader() error { 607 _, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)]) 608 if err != nil { 609 return err 610 } 611 if string(d.tmp[:len(pngHeader)]) != pngHeader { 612 return FormatError("not a PNG file") 613 } 614 return nil 615 } 616 617 // Decode reads a PNG image from r and returns it as an image.Image. 618 // The type of Image returned depends on the PNG contents. 619 func Decode(r io.Reader) (image.Image, error) { 620 d := &decoder{ 621 r: r, 622 crc: crc32.NewIEEE(), 623 } 624 if err := d.checkHeader(); err != nil { 625 if err == io.EOF { 626 err = io.ErrUnexpectedEOF 627 } 628 return nil, err 629 } 630 for d.stage != dsSeenIEND { 631 if err := d.parseChunk(); err != nil { 632 if err == io.EOF { 633 err = io.ErrUnexpectedEOF 634 } 635 return nil, err 636 } 637 } 638 return d.img, nil 639 } 640 641 // DecodeConfig returns the color model and dimensions of a PNG image without 642 // decoding the entire image. 643 func DecodeConfig(r io.Reader) (image.Config, error) { 644 d := &decoder{ 645 r: r, 646 crc: crc32.NewIEEE(), 647 } 648 if err := d.checkHeader(); err != nil { 649 if err == io.EOF { 650 err = io.ErrUnexpectedEOF 651 } 652 return image.Config{}, err 653 } 654 for { 655 if err := d.parseChunk(); err != nil { 656 if err == io.EOF { 657 err = io.ErrUnexpectedEOF 658 } 659 return image.Config{}, err 660 } 661 paletted := d.cb == cbP8 || d.cb == cbP4 || d.cb == cbP2 || d.cb == cbP1 662 if d.stage == dsSeenIHDR && !paletted { 663 break 664 } 665 if d.stage == dsSeenPLTE && paletted { 666 break 667 } 668 } 669 var cm color.Model 670 switch d.cb { 671 case cbG1, cbG2, cbG4, cbG8: 672 cm = color.GrayModel 673 case cbGA8: 674 cm = color.NRGBAModel 675 case cbTC8: 676 cm = color.RGBAModel 677 case cbP1, cbP2, cbP4, cbP8: 678 cm = d.palette 679 case cbTCA8: 680 cm = color.NRGBAModel 681 case cbG16: 682 cm = color.Gray16Model 683 case cbGA16: 684 cm = color.NRGBA64Model 685 case cbTC16: 686 cm = color.RGBA64Model 687 case cbTCA16: 688 cm = color.NRGBA64Model 689 } 690 return image.Config{ 691 ColorModel: cm, 692 Width: d.width, 693 Height: d.height, 694 }, nil 695 } 696 697 func init() { 698 image.RegisterFormat("png", pngHeader, Decode, DecodeConfig) 699 }