github.com/freddyisaac/sicortex-golang@v0.0.0-20231019035217-e03519e66f60/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 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 if d.useTransparent { 616 // Match error from Go 1.7 and earlier. 617 // Go 1.9 will decode this properly. 618 return nil, chunkOrderError 619 } 620 copy(gray.Pix[pixOffset:], cdat) 621 pixOffset += gray.Stride 622 case cbGA8: 623 for x := 0; x < width; x++ { 624 ycol := cdat[2*x+0] 625 nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]}) 626 } 627 case cbTC8: 628 if d.useTransparent { 629 pix, i, j := nrgba.Pix, pixOffset, 0 630 tr, tg, tb := d.transparent[1], d.transparent[3], d.transparent[5] 631 for x := 0; x < width; x++ { 632 r := cdat[j+0] 633 g := cdat[j+1] 634 b := cdat[j+2] 635 a := uint8(0xff) 636 if r == tr && g == tg && b == tb { 637 a = 0x00 638 } 639 pix[i+0] = r 640 pix[i+1] = g 641 pix[i+2] = b 642 pix[i+3] = a 643 i += 4 644 j += 3 645 } 646 pixOffset += nrgba.Stride 647 } else { 648 pix, i, j := rgba.Pix, pixOffset, 0 649 for x := 0; x < width; x++ { 650 pix[i+0] = cdat[j+0] 651 pix[i+1] = cdat[j+1] 652 pix[i+2] = cdat[j+2] 653 pix[i+3] = 0xff 654 i += 4 655 j += 3 656 } 657 pixOffset += rgba.Stride 658 } 659 case cbP1: 660 for x := 0; x < width; x += 8 { 661 b := cdat[x/8] 662 for x2 := 0; x2 < 8 && x+x2 < width; x2++ { 663 idx := b >> 7 664 if len(paletted.Palette) <= int(idx) { 665 paletted.Palette = paletted.Palette[:int(idx)+1] 666 } 667 paletted.SetColorIndex(x+x2, y, idx) 668 b <<= 1 669 } 670 } 671 case cbP2: 672 for x := 0; x < width; x += 4 { 673 b := cdat[x/4] 674 for x2 := 0; x2 < 4 && x+x2 < width; x2++ { 675 idx := b >> 6 676 if len(paletted.Palette) <= int(idx) { 677 paletted.Palette = paletted.Palette[:int(idx)+1] 678 } 679 paletted.SetColorIndex(x+x2, y, idx) 680 b <<= 2 681 } 682 } 683 case cbP4: 684 for x := 0; x < width; x += 2 { 685 b := cdat[x/2] 686 for x2 := 0; x2 < 2 && x+x2 < width; x2++ { 687 idx := b >> 4 688 if len(paletted.Palette) <= int(idx) { 689 paletted.Palette = paletted.Palette[:int(idx)+1] 690 } 691 paletted.SetColorIndex(x+x2, y, idx) 692 b <<= 4 693 } 694 } 695 case cbP8: 696 if len(paletted.Palette) != 255 { 697 for x := 0; x < width; x++ { 698 if len(paletted.Palette) <= int(cdat[x]) { 699 paletted.Palette = paletted.Palette[:int(cdat[x])+1] 700 } 701 } 702 } 703 copy(paletted.Pix[pixOffset:], cdat) 704 pixOffset += paletted.Stride 705 case cbTCA8: 706 copy(nrgba.Pix[pixOffset:], cdat) 707 pixOffset += nrgba.Stride 708 case cbG16: 709 if d.useTransparent { 710 ty := uint16(d.transparent[0])<<8 | uint16(d.transparent[1]) 711 for x := 0; x < width; x++ { 712 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1]) 713 acol := uint16(0xffff) 714 if ycol == ty { 715 acol = 0x0000 716 } 717 nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol}) 718 } 719 } else { 720 for x := 0; x < width; x++ { 721 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1]) 722 gray16.SetGray16(x, y, color.Gray16{ycol}) 723 } 724 } 725 case cbGA16: 726 for x := 0; x < width; x++ { 727 ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1]) 728 acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3]) 729 nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol}) 730 } 731 case cbTC16: 732 if d.useTransparent { 733 tr := uint16(d.transparent[0])<<8 | uint16(d.transparent[1]) 734 tg := uint16(d.transparent[2])<<8 | uint16(d.transparent[3]) 735 tb := uint16(d.transparent[4])<<8 | uint16(d.transparent[5]) 736 for x := 0; x < width; x++ { 737 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1]) 738 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3]) 739 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5]) 740 acol := uint16(0xffff) 741 if rcol == tr && gcol == tg && bcol == tb { 742 acol = 0x0000 743 } 744 nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol}) 745 } 746 } else { 747 for x := 0; x < width; x++ { 748 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1]) 749 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3]) 750 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5]) 751 rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff}) 752 } 753 } 754 case cbTCA16: 755 for x := 0; x < width; x++ { 756 rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1]) 757 gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3]) 758 bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5]) 759 acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7]) 760 nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol}) 761 } 762 } 763 764 // The current row for y is the previous row for y+1. 765 pr, cr = cr, pr 766 } 767 768 return img, nil 769 } 770 771 // mergePassInto merges a single pass into a full sized image. 772 func (d *decoder) mergePassInto(dst image.Image, src image.Image, pass int) { 773 p := interlacing[pass] 774 var ( 775 srcPix []uint8 776 dstPix []uint8 777 stride int 778 rect image.Rectangle 779 bytesPerPixel int 780 ) 781 switch target := dst.(type) { 782 case *image.Alpha: 783 srcPix = src.(*image.Alpha).Pix 784 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 785 bytesPerPixel = 1 786 case *image.Alpha16: 787 srcPix = src.(*image.Alpha16).Pix 788 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 789 bytesPerPixel = 2 790 case *image.Gray: 791 srcPix = src.(*image.Gray).Pix 792 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 793 bytesPerPixel = 1 794 case *image.Gray16: 795 srcPix = src.(*image.Gray16).Pix 796 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 797 bytesPerPixel = 2 798 case *image.NRGBA: 799 srcPix = src.(*image.NRGBA).Pix 800 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 801 bytesPerPixel = 4 802 case *image.NRGBA64: 803 srcPix = src.(*image.NRGBA64).Pix 804 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 805 bytesPerPixel = 8 806 case *image.Paletted: 807 srcPix = src.(*image.Paletted).Pix 808 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 809 bytesPerPixel = 1 810 case *image.RGBA: 811 srcPix = src.(*image.RGBA).Pix 812 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 813 bytesPerPixel = 4 814 case *image.RGBA64: 815 srcPix = src.(*image.RGBA64).Pix 816 dstPix, stride, rect = target.Pix, target.Stride, target.Rect 817 bytesPerPixel = 8 818 } 819 s, bounds := 0, src.Bounds() 820 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { 821 dBase := (y*p.yFactor+p.yOffset-rect.Min.Y)*stride + (p.xOffset-rect.Min.X)*bytesPerPixel 822 for x := bounds.Min.X; x < bounds.Max.X; x++ { 823 d := dBase + x*p.xFactor*bytesPerPixel 824 copy(dstPix[d:], srcPix[s:s+bytesPerPixel]) 825 s += bytesPerPixel 826 } 827 } 828 } 829 830 func (d *decoder) parseIDAT(length uint32) (err error) { 831 d.idatLength = length 832 d.img, err = d.decode() 833 if err != nil { 834 return err 835 } 836 return d.verifyChecksum() 837 } 838 839 func (d *decoder) parseIEND(length uint32) error { 840 if length != 0 { 841 return FormatError("bad IEND length") 842 } 843 return d.verifyChecksum() 844 } 845 846 func (d *decoder) parseChunk() error { 847 // Read the length and chunk type. 848 n, err := io.ReadFull(d.r, d.tmp[:8]) 849 if err != nil { 850 return err 851 } 852 length := binary.BigEndian.Uint32(d.tmp[:4]) 853 d.crc.Reset() 854 d.crc.Write(d.tmp[4:8]) 855 856 // Read the chunk data. 857 switch string(d.tmp[4:8]) { 858 case "IHDR": 859 if d.stage != dsStart { 860 return chunkOrderError 861 } 862 d.stage = dsSeenIHDR 863 return d.parseIHDR(length) 864 case "PLTE": 865 if d.stage != dsSeenIHDR { 866 return chunkOrderError 867 } 868 d.stage = dsSeenPLTE 869 return d.parsePLTE(length) 870 case "tRNS": 871 if cbPaletted(d.cb) { 872 if d.stage != dsSeenPLTE { 873 return chunkOrderError 874 } 875 } else if d.stage != dsSeenIHDR { 876 return chunkOrderError 877 } 878 d.stage = dsSeentRNS 879 return d.parsetRNS(length) 880 case "IDAT": 881 if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.stage == dsSeenIHDR && cbPaletted(d.cb)) { 882 return chunkOrderError 883 } else if d.stage == dsSeenIDAT { 884 // Ignore trailing zero-length or garbage IDAT chunks. 885 // 886 // This does not affect valid PNG images that contain multiple IDAT 887 // chunks, since the first call to parseIDAT below will consume all 888 // consecutive IDAT chunks required for decoding the image. 889 break 890 } 891 d.stage = dsSeenIDAT 892 return d.parseIDAT(length) 893 case "IEND": 894 if d.stage != dsSeenIDAT { 895 return chunkOrderError 896 } 897 d.stage = dsSeenIEND 898 return d.parseIEND(length) 899 } 900 if length > 0x7fffffff { 901 return FormatError(fmt.Sprintf("Bad chunk length: %d", length)) 902 } 903 // Ignore this chunk (of a known length). 904 var ignored [4096]byte 905 for length > 0 { 906 n, err = io.ReadFull(d.r, ignored[:min(len(ignored), int(length))]) 907 if err != nil { 908 return err 909 } 910 d.crc.Write(ignored[:n]) 911 length -= uint32(n) 912 } 913 return d.verifyChecksum() 914 } 915 916 func (d *decoder) verifyChecksum() error { 917 if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil { 918 return err 919 } 920 if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() { 921 return FormatError("invalid checksum") 922 } 923 return nil 924 } 925 926 func (d *decoder) checkHeader() error { 927 _, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)]) 928 if err != nil { 929 return err 930 } 931 if string(d.tmp[:len(pngHeader)]) != pngHeader { 932 return FormatError("not a PNG file") 933 } 934 return nil 935 } 936 937 // Decode reads a PNG image from r and returns it as an image.Image. 938 // The type of Image returned depends on the PNG contents. 939 func Decode(r io.Reader) (image.Image, error) { 940 d := &decoder{ 941 r: r, 942 crc: crc32.NewIEEE(), 943 } 944 if err := d.checkHeader(); err != nil { 945 if err == io.EOF { 946 err = io.ErrUnexpectedEOF 947 } 948 return nil, err 949 } 950 for d.stage != dsSeenIEND { 951 if err := d.parseChunk(); err != nil { 952 if err == io.EOF { 953 err = io.ErrUnexpectedEOF 954 } 955 return nil, err 956 } 957 } 958 return d.img, nil 959 } 960 961 // DecodeConfig returns the color model and dimensions of a PNG image without 962 // decoding the entire image. 963 func DecodeConfig(r io.Reader) (image.Config, error) { 964 d := &decoder{ 965 r: r, 966 crc: crc32.NewIEEE(), 967 } 968 if err := d.checkHeader(); err != nil { 969 if err == io.EOF { 970 err = io.ErrUnexpectedEOF 971 } 972 return image.Config{}, err 973 } 974 for { 975 if err := d.parseChunk(); err != nil { 976 if err == io.EOF { 977 err = io.ErrUnexpectedEOF 978 } 979 return image.Config{}, err 980 } 981 paletted := cbPaletted(d.cb) 982 if d.stage == dsSeenIHDR && !paletted { 983 break 984 } 985 if d.stage == dsSeenPLTE && paletted { 986 break 987 } 988 } 989 var cm color.Model 990 switch d.cb { 991 case cbG1, cbG2, cbG4, cbG8: 992 cm = color.GrayModel 993 case cbGA8: 994 cm = color.NRGBAModel 995 case cbTC8: 996 cm = color.RGBAModel 997 case cbP1, cbP2, cbP4, cbP8: 998 cm = d.palette 999 case cbTCA8: 1000 cm = color.NRGBAModel 1001 case cbG16: 1002 cm = color.Gray16Model 1003 case cbGA16: 1004 cm = color.NRGBA64Model 1005 case cbTC16: 1006 cm = color.RGBA64Model 1007 case cbTCA16: 1008 cm = color.NRGBA64Model 1009 } 1010 return image.Config{ 1011 ColorModel: cm, 1012 Width: d.width, 1013 Height: d.height, 1014 }, nil 1015 } 1016 1017 func init() { 1018 image.RegisterFormat("png", pngHeader, Decode, DecodeConfig) 1019 }