github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/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, err := r.Read(pr[:1]) 509 if err != io.EOF { 510 return nil, FormatError(err.Error()) 511 } 512 if n != 0 || d.idatLength != 0 { 513 return nil, FormatError("too much pixel data") 514 } 515 516 return img, nil 517 } 518 519 func (d *decoder) parseIDAT(length uint32) (err error) { 520 d.idatLength = length 521 d.img, err = d.decode() 522 if err != nil { 523 return err 524 } 525 return d.verifyChecksum() 526 } 527 528 func (d *decoder) parseIEND(length uint32) error { 529 if length != 0 { 530 return FormatError("bad IEND length") 531 } 532 return d.verifyChecksum() 533 } 534 535 func (d *decoder) parseChunk() error { 536 // Read the length and chunk type. 537 n, err := io.ReadFull(d.r, d.tmp[:8]) 538 if err != nil { 539 return err 540 } 541 length := binary.BigEndian.Uint32(d.tmp[:4]) 542 d.crc.Reset() 543 d.crc.Write(d.tmp[4:8]) 544 545 // Read the chunk data. 546 switch string(d.tmp[4:8]) { 547 case "IHDR": 548 if d.stage != dsStart { 549 return chunkOrderError 550 } 551 d.stage = dsSeenIHDR 552 return d.parseIHDR(length) 553 case "PLTE": 554 if d.stage != dsSeenIHDR { 555 return chunkOrderError 556 } 557 d.stage = dsSeenPLTE 558 return d.parsePLTE(length) 559 case "tRNS": 560 if d.stage != dsSeenPLTE { 561 return chunkOrderError 562 } 563 return d.parsetRNS(length) 564 case "IDAT": 565 if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.cb == cbP8 && d.stage == dsSeenIHDR) { 566 return chunkOrderError 567 } 568 d.stage = dsSeenIDAT 569 return d.parseIDAT(length) 570 case "IEND": 571 if d.stage != dsSeenIDAT { 572 return chunkOrderError 573 } 574 d.stage = dsSeenIEND 575 return d.parseIEND(length) 576 } 577 // Ignore this chunk (of a known length). 578 var ignored [4096]byte 579 for length > 0 { 580 n, err = io.ReadFull(d.r, ignored[:min(len(ignored), int(length))]) 581 if err != nil { 582 return err 583 } 584 d.crc.Write(ignored[:n]) 585 length -= uint32(n) 586 } 587 return d.verifyChecksum() 588 } 589 590 func (d *decoder) verifyChecksum() error { 591 if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil { 592 return err 593 } 594 if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() { 595 return FormatError("invalid checksum") 596 } 597 return nil 598 } 599 600 func (d *decoder) checkHeader() error { 601 _, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)]) 602 if err != nil { 603 return err 604 } 605 if string(d.tmp[:len(pngHeader)]) != pngHeader { 606 return FormatError("not a PNG file") 607 } 608 return nil 609 } 610 611 // Decode reads a PNG image from r and returns it as an image.Image. 612 // The type of Image returned depends on the PNG contents. 613 func Decode(r io.Reader) (image.Image, error) { 614 d := &decoder{ 615 r: r, 616 crc: crc32.NewIEEE(), 617 } 618 if err := d.checkHeader(); err != nil { 619 if err == io.EOF { 620 err = io.ErrUnexpectedEOF 621 } 622 return nil, err 623 } 624 for d.stage != dsSeenIEND { 625 if err := d.parseChunk(); err != nil { 626 if err == io.EOF { 627 err = io.ErrUnexpectedEOF 628 } 629 return nil, err 630 } 631 } 632 return d.img, nil 633 } 634 635 // DecodeConfig returns the color model and dimensions of a PNG image without 636 // decoding the entire image. 637 func DecodeConfig(r io.Reader) (image.Config, error) { 638 d := &decoder{ 639 r: r, 640 crc: crc32.NewIEEE(), 641 } 642 if err := d.checkHeader(); err != nil { 643 if err == io.EOF { 644 err = io.ErrUnexpectedEOF 645 } 646 return image.Config{}, err 647 } 648 for { 649 if err := d.parseChunk(); err != nil { 650 if err == io.EOF { 651 err = io.ErrUnexpectedEOF 652 } 653 return image.Config{}, err 654 } 655 paletted := d.cb == cbP8 || d.cb == cbP4 || d.cb == cbP2 || d.cb == cbP1 656 if d.stage == dsSeenIHDR && !paletted { 657 break 658 } 659 if d.stage == dsSeenPLTE && paletted { 660 break 661 } 662 } 663 var cm color.Model 664 switch d.cb { 665 case cbG1, cbG2, cbG4, cbG8: 666 cm = color.GrayModel 667 case cbGA8: 668 cm = color.NRGBAModel 669 case cbTC8: 670 cm = color.RGBAModel 671 case cbP1, cbP2, cbP4, cbP8: 672 cm = d.palette 673 case cbTCA8: 674 cm = color.NRGBAModel 675 case cbG16: 676 cm = color.Gray16Model 677 case cbGA16: 678 cm = color.NRGBA64Model 679 case cbTC16: 680 cm = color.RGBA64Model 681 case cbTCA16: 682 cm = color.NRGBA64Model 683 } 684 return image.Config{ 685 ColorModel: cm, 686 Width: d.width, 687 Height: d.height, 688 }, nil 689 } 690 691 func init() { 692 image.RegisterFormat("png", pngHeader, Decode, DecodeConfig) 693 }