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