reader.mx raw

   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  	"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  func cbTrueColor(cb int) bool {
  55  	return cb == cbTC8 || cb == cbTC16
  56  }
  57  
  58  // Filter type, as per the PNG spec.
  59  const (
  60  	ftNone    = 0
  61  	ftSub     = 1
  62  	ftUp      = 2
  63  	ftAverage = 3
  64  	ftPaeth   = 4
  65  	nFilter   = 5
  66  )
  67  
  68  // Interlace type.
  69  const (
  70  	itNone  = 0
  71  	itAdam7 = 1
  72  )
  73  
  74  // interlaceScan defines the placement and size of a pass for Adam7 interlacing.
  75  type interlaceScan struct {
  76  	xFactor, yFactor, xOffset, yOffset int
  77  }
  78  
  79  // interlacing defines Adam7 interlacing, with 7 passes of reduced images.
  80  // See https://www.w3.org/TR/PNG/#8Interlace
  81  var interlacing = []interlaceScan{
  82  	{8, 8, 0, 0},
  83  	{8, 8, 4, 0},
  84  	{4, 8, 0, 4},
  85  	{4, 4, 2, 0},
  86  	{2, 4, 0, 2},
  87  	{2, 2, 1, 0},
  88  	{1, 2, 0, 1},
  89  }
  90  
  91  // Decoding stage.
  92  // The PNG specification says that the IHDR, PLTE (if present), tRNS (if
  93  // present), IDAT and IEND chunks must appear in that order. There may be
  94  // multiple IDAT chunks, and IDAT chunks must be sequential (i.e. they may not
  95  // have any other chunks between them).
  96  // https://www.w3.org/TR/PNG/#5ChunkOrdering
  97  const (
  98  	dsStart = iota
  99  	dsSeenIHDR
 100  	dsSeenPLTE
 101  	dsSeentRNS
 102  	dsSeenIDAT
 103  	dsSeenIEND
 104  )
 105  
 106  const pngHeader = "\x89PNG\r\n\x1a\n"
 107  
 108  type decoder struct {
 109  	r             io.Reader
 110  	img           image.Image
 111  	crc           hash.Hash32
 112  	width, height int
 113  	depth         int
 114  	palette       color.Palette
 115  	cb            int
 116  	stage         int
 117  	idatLength    uint32
 118  	tmp           [3 * 256]byte
 119  	interlace     int
 120  
 121  	// useTransparent and transparent are used for grayscale and truecolor
 122  	// transparency, as opposed to palette transparency.
 123  	useTransparent bool
 124  	transparent    [6]byte
 125  }
 126  
 127  // A FormatError reports that the input is not a valid PNG.
 128  type FormatError []byte
 129  
 130  func (e FormatError) Error() string {
 131  	return string(append([]byte("png: invalid format: "), e...))
 132  }
 133  
 134  var chunkOrderError = FormatError("chunk out of order")
 135  
 136  // An UnsupportedError reports that the input uses a valid but unimplemented PNG feature.
 137  type UnsupportedError []byte
 138  
 139  func (e UnsupportedError) Error() string {
 140  	return string(append([]byte("png: unsupported feature: "), e...))
 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([]byte(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 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  	switch d.cb {
 442  	case cbG1, cbG2, cbG4, cbG8:
 443  		bitsPerPixel = d.depth
 444  		if d.useTransparent {
 445  			nrgba = image.NewNRGBA(image.Rect(0, 0, width, height))
 446  			img = nrgba
 447  		} else {
 448  			gray = image.NewGray(image.Rect(0, 0, width, height))
 449  			img = gray
 450  		}
 451  	case cbGA8:
 452  		bitsPerPixel = 16
 453  		nrgba = image.NewNRGBA(image.Rect(0, 0, width, height))
 454  		img = nrgba
 455  	case cbTC8:
 456  		bitsPerPixel = 24
 457  		if d.useTransparent {
 458  			nrgba = image.NewNRGBA(image.Rect(0, 0, width, height))
 459  			img = nrgba
 460  		} else {
 461  			rgba = image.NewRGBA(image.Rect(0, 0, width, height))
 462  			img = rgba
 463  		}
 464  	case cbP1, cbP2, cbP4, cbP8:
 465  		bitsPerPixel = d.depth
 466  		paletted = image.NewPaletted(image.Rect(0, 0, width, height), d.palette)
 467  		img = paletted
 468  	case cbTCA8:
 469  		bitsPerPixel = 32
 470  		nrgba = image.NewNRGBA(image.Rect(0, 0, width, height))
 471  		img = nrgba
 472  	case cbG16:
 473  		bitsPerPixel = 16
 474  		if d.useTransparent {
 475  			nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
 476  			img = nrgba64
 477  		} else {
 478  			gray16 = image.NewGray16(image.Rect(0, 0, width, height))
 479  			img = gray16
 480  		}
 481  	case cbGA16:
 482  		bitsPerPixel = 32
 483  		nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
 484  		img = nrgba64
 485  	case cbTC16:
 486  		bitsPerPixel = 48
 487  		if d.useTransparent {
 488  			nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
 489  			img = nrgba64
 490  		} else {
 491  			rgba64 = image.NewRGBA64(image.Rect(0, 0, width, height))
 492  			img = rgba64
 493  		}
 494  	case cbTCA16:
 495  		bitsPerPixel = 64
 496  		nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
 497  		img = nrgba64
 498  	}
 499  	if allocateOnly {
 500  		return img, nil
 501  	}
 502  	bytesPerPixel := (bitsPerPixel + 7) / 8
 503  
 504  	// The +1 is for the per-row filter type, which is at cr[0].
 505  	rowSize := 1 + (int64(bitsPerPixel)*int64(width)+7)/8
 506  	if rowSize != int64(int(rowSize)) {
 507  		return nil, UnsupportedError("dimension overflow")
 508  	}
 509  	// cr and pr are the bytes for the current and previous row.
 510  	cr := []uint8{:rowSize}
 511  	pr := []uint8{:rowSize}
 512  
 513  	for y := 0; y < height; y++ {
 514  		// Read the decompressed bytes.
 515  		_, err := io.ReadFull(r, cr)
 516  		if err != nil {
 517  			if err == io.EOF || err == io.ErrUnexpectedEOF {
 518  				return nil, FormatError("not enough pixel data")
 519  			}
 520  			return nil, err
 521  		}
 522  
 523  		// Apply the filter.
 524  		cdat := cr[1:]
 525  		pdat := pr[1:]
 526  		switch cr[0] {
 527  		case ftNone:
 528  			// No-op.
 529  		case ftSub:
 530  			for i := bytesPerPixel; i < len(cdat); i++ {
 531  				cdat[i] += cdat[i-bytesPerPixel]
 532  			}
 533  		case ftUp:
 534  			for i, p := range pdat {
 535  				cdat[i] += p
 536  			}
 537  		case ftAverage:
 538  			// The first column has no column to the left of it, so it is a
 539  			// special case. We know that the first column exists because we
 540  			// check above that width != 0, and so len(cdat) != 0.
 541  			for i := 0; i < bytesPerPixel; i++ {
 542  				cdat[i] += pdat[i] / 2
 543  			}
 544  			for i := bytesPerPixel; i < len(cdat); i++ {
 545  				cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2)
 546  			}
 547  		case ftPaeth:
 548  			filterPaeth(cdat, pdat, bytesPerPixel)
 549  		default:
 550  			return nil, FormatError("bad filter type")
 551  		}
 552  
 553  		// Convert from bytes to colors.
 554  		switch d.cb {
 555  		case cbG1:
 556  			if d.useTransparent {
 557  				ty := d.transparent[1]
 558  				for x := 0; x < width; x += 8 {
 559  					b := cdat[x/8]
 560  					for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
 561  						ycol := (b >> 7) * 0xff
 562  						acol := uint8(0xff)
 563  						if ycol == ty {
 564  							acol = 0x00
 565  						}
 566  						nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
 567  						b <<= 1
 568  					}
 569  				}
 570  			} else {
 571  				for x := 0; x < width; x += 8 {
 572  					b := cdat[x/8]
 573  					for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
 574  						gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff})
 575  						b <<= 1
 576  					}
 577  				}
 578  			}
 579  		case cbG2:
 580  			if d.useTransparent {
 581  				ty := d.transparent[1]
 582  				for x := 0; x < width; x += 4 {
 583  					b := cdat[x/4]
 584  					for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
 585  						ycol := (b >> 6) * 0x55
 586  						acol := uint8(0xff)
 587  						if ycol == ty {
 588  							acol = 0x00
 589  						}
 590  						nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
 591  						b <<= 2
 592  					}
 593  				}
 594  			} else {
 595  				for x := 0; x < width; x += 4 {
 596  					b := cdat[x/4]
 597  					for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
 598  						gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55})
 599  						b <<= 2
 600  					}
 601  				}
 602  			}
 603  		case cbG4:
 604  			if d.useTransparent {
 605  				ty := d.transparent[1]
 606  				for x := 0; x < width; x += 2 {
 607  					b := cdat[x/2]
 608  					for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
 609  						ycol := (b >> 4) * 0x11
 610  						acol := uint8(0xff)
 611  						if ycol == ty {
 612  							acol = 0x00
 613  						}
 614  						nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
 615  						b <<= 4
 616  					}
 617  				}
 618  			} else {
 619  				for x := 0; x < width; x += 2 {
 620  					b := cdat[x/2]
 621  					for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
 622  						gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11})
 623  						b <<= 4
 624  					}
 625  				}
 626  			}
 627  		case cbG8:
 628  			if d.useTransparent {
 629  				ty := d.transparent[1]
 630  				for x := 0; x < width; x++ {
 631  					ycol := cdat[x]
 632  					acol := uint8(0xff)
 633  					if ycol == ty {
 634  						acol = 0x00
 635  					}
 636  					nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, acol})
 637  				}
 638  			} else {
 639  				copy(gray.Pix[pixOffset:], cdat)
 640  				pixOffset += gray.Stride
 641  			}
 642  		case cbGA8:
 643  			for x := 0; x < width; x++ {
 644  				ycol := cdat[2*x+0]
 645  				nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]})
 646  			}
 647  		case cbTC8:
 648  			if d.useTransparent {
 649  				pix, i, j := nrgba.Pix, pixOffset, 0
 650  				tr, tg, tb := d.transparent[1], d.transparent[3], d.transparent[5]
 651  				for x := 0; x < width; x++ {
 652  					r := cdat[j+0]
 653  					g := cdat[j+1]
 654  					b := cdat[j+2]
 655  					a := uint8(0xff)
 656  					if r == tr && g == tg && b == tb {
 657  						a = 0x00
 658  					}
 659  					pix[i+0] = r
 660  					pix[i+1] = g
 661  					pix[i+2] = b
 662  					pix[i+3] = a
 663  					i += 4
 664  					j += 3
 665  				}
 666  				pixOffset += nrgba.Stride
 667  			} else {
 668  				pix, i, j := rgba.Pix, pixOffset, 0
 669  				for x := 0; x < width; x++ {
 670  					pix[i+0] = cdat[j+0]
 671  					pix[i+1] = cdat[j+1]
 672  					pix[i+2] = cdat[j+2]
 673  					pix[i+3] = 0xff
 674  					i += 4
 675  					j += 3
 676  				}
 677  				pixOffset += rgba.Stride
 678  			}
 679  		case cbP1:
 680  			for x := 0; x < width; x += 8 {
 681  				b := cdat[x/8]
 682  				for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
 683  					idx := b >> 7
 684  					if len(paletted.Palette) <= int(idx) {
 685  						paletted.Palette = paletted.Palette[:int(idx)+1]
 686  					}
 687  					paletted.SetColorIndex(x+x2, y, idx)
 688  					b <<= 1
 689  				}
 690  			}
 691  		case cbP2:
 692  			for x := 0; x < width; x += 4 {
 693  				b := cdat[x/4]
 694  				for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
 695  					idx := b >> 6
 696  					if len(paletted.Palette) <= int(idx) {
 697  						paletted.Palette = paletted.Palette[:int(idx)+1]
 698  					}
 699  					paletted.SetColorIndex(x+x2, y, idx)
 700  					b <<= 2
 701  				}
 702  			}
 703  		case cbP4:
 704  			for x := 0; x < width; x += 2 {
 705  				b := cdat[x/2]
 706  				for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
 707  					idx := b >> 4
 708  					if len(paletted.Palette) <= int(idx) {
 709  						paletted.Palette = paletted.Palette[:int(idx)+1]
 710  					}
 711  					paletted.SetColorIndex(x+x2, y, idx)
 712  					b <<= 4
 713  				}
 714  			}
 715  		case cbP8:
 716  			if len(paletted.Palette) != 256 {
 717  				for x := 0; x < width; x++ {
 718  					if len(paletted.Palette) <= int(cdat[x]) {
 719  						paletted.Palette = paletted.Palette[:int(cdat[x])+1]
 720  					}
 721  				}
 722  			}
 723  			copy(paletted.Pix[pixOffset:], cdat)
 724  			pixOffset += paletted.Stride
 725  		case cbTCA8:
 726  			copy(nrgba.Pix[pixOffset:], cdat)
 727  			pixOffset += nrgba.Stride
 728  		case cbG16:
 729  			if d.useTransparent {
 730  				ty := uint16(d.transparent[0])<<8 | uint16(d.transparent[1])
 731  				for x := 0; x < width; x++ {
 732  					ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
 733  					acol := uint16(0xffff)
 734  					if ycol == ty {
 735  						acol = 0x0000
 736  					}
 737  					nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
 738  				}
 739  			} else {
 740  				for x := 0; x < width; x++ {
 741  					ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
 742  					gray16.SetGray16(x, y, color.Gray16{ycol})
 743  				}
 744  			}
 745  		case cbGA16:
 746  			for x := 0; x < width; x++ {
 747  				ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1])
 748  				acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3])
 749  				nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
 750  			}
 751  		case cbTC16:
 752  			if d.useTransparent {
 753  				tr := uint16(d.transparent[0])<<8 | uint16(d.transparent[1])
 754  				tg := uint16(d.transparent[2])<<8 | uint16(d.transparent[3])
 755  				tb := uint16(d.transparent[4])<<8 | uint16(d.transparent[5])
 756  				for x := 0; x < width; x++ {
 757  					rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
 758  					gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
 759  					bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
 760  					acol := uint16(0xffff)
 761  					if rcol == tr && gcol == tg && bcol == tb {
 762  						acol = 0x0000
 763  					}
 764  					nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol})
 765  				}
 766  			} else {
 767  				for x := 0; x < width; x++ {
 768  					rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
 769  					gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
 770  					bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
 771  					rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff})
 772  				}
 773  			}
 774  		case cbTCA16:
 775  			for x := 0; x < width; x++ {
 776  				rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1])
 777  				gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3])
 778  				bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5])
 779  				acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7])
 780  				nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol})
 781  			}
 782  		}
 783  
 784  		// The current row for y is the previous row for y+1.
 785  		pr, cr = cr, pr
 786  	}
 787  
 788  	return img, nil
 789  }
 790  
 791  // mergePassInto merges a single pass into a full sized image.
 792  func (d *decoder) mergePassInto(dst image.Image, src image.Image, pass int) {
 793  	p := interlacing[pass]
 794  	var (
 795  		srcPix        []uint8
 796  		dstPix        []uint8
 797  		stride        int
 798  		rect          image.Rectangle
 799  		bytesPerPixel int
 800  	)
 801  	switch target := dst.(type) {
 802  	case *image.Alpha:
 803  		srcPix = src.(*image.Alpha).Pix
 804  		dstPix, stride, rect = target.Pix, target.Stride, target.Rect
 805  		bytesPerPixel = 1
 806  	case *image.Alpha16:
 807  		srcPix = src.(*image.Alpha16).Pix
 808  		dstPix, stride, rect = target.Pix, target.Stride, target.Rect
 809  		bytesPerPixel = 2
 810  	case *image.Gray:
 811  		srcPix = src.(*image.Gray).Pix
 812  		dstPix, stride, rect = target.Pix, target.Stride, target.Rect
 813  		bytesPerPixel = 1
 814  	case *image.Gray16:
 815  		srcPix = src.(*image.Gray16).Pix
 816  		dstPix, stride, rect = target.Pix, target.Stride, target.Rect
 817  		bytesPerPixel = 2
 818  	case *image.NRGBA:
 819  		srcPix = src.(*image.NRGBA).Pix
 820  		dstPix, stride, rect = target.Pix, target.Stride, target.Rect
 821  		bytesPerPixel = 4
 822  	case *image.NRGBA64:
 823  		srcPix = src.(*image.NRGBA64).Pix
 824  		dstPix, stride, rect = target.Pix, target.Stride, target.Rect
 825  		bytesPerPixel = 8
 826  	case *image.Paletted:
 827  		source := src.(*image.Paletted)
 828  		srcPix = source.Pix
 829  		dstPix, stride, rect = target.Pix, target.Stride, target.Rect
 830  		bytesPerPixel = 1
 831  		if len(target.Palette) < len(source.Palette) {
 832  			// readImagePass can return a paletted image whose implicit palette
 833  			// length (one more than the maximum Pix value) is larger than the
 834  			// explicit palette length (what's in the PLTE chunk). Make the
 835  			// same adjustment here.
 836  			target.Palette = source.Palette
 837  		}
 838  	case *image.RGBA:
 839  		srcPix = src.(*image.RGBA).Pix
 840  		dstPix, stride, rect = target.Pix, target.Stride, target.Rect
 841  		bytesPerPixel = 4
 842  	case *image.RGBA64:
 843  		srcPix = src.(*image.RGBA64).Pix
 844  		dstPix, stride, rect = target.Pix, target.Stride, target.Rect
 845  		bytesPerPixel = 8
 846  	}
 847  	s, bounds := 0, src.Bounds()
 848  	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
 849  		dBase := (y*p.yFactor+p.yOffset-rect.Min.Y)*stride + (p.xOffset-rect.Min.X)*bytesPerPixel
 850  		for x := bounds.Min.X; x < bounds.Max.X; x++ {
 851  			d := dBase + x*p.xFactor*bytesPerPixel
 852  			copy(dstPix[d:], srcPix[s:s+bytesPerPixel])
 853  			s += bytesPerPixel
 854  		}
 855  	}
 856  }
 857  
 858  func (d *decoder) parseIDAT(length uint32) (err error) {
 859  	d.idatLength = length
 860  	d.img, err = d.decode()
 861  	if err != nil {
 862  		return err
 863  	}
 864  	return d.verifyChecksum()
 865  }
 866  
 867  func (d *decoder) parseIEND(length uint32) error {
 868  	if length != 0 {
 869  		return FormatError("bad IEND length")
 870  	}
 871  	return d.verifyChecksum()
 872  }
 873  
 874  func (d *decoder) parseChunk(configOnly bool) error {
 875  	// Read the length and chunk type.
 876  	if _, err := io.ReadFull(d.r, d.tmp[:8]); err != nil {
 877  		return err
 878  	}
 879  	length := binary.BigEndian.Uint32(d.tmp[:4])
 880  	d.crc.Reset()
 881  	d.crc.Write(d.tmp[4:8])
 882  
 883  	// Read the chunk data.
 884  	switch d.tmp[4:8] {
 885  	case "IHDR":
 886  		if d.stage != dsStart {
 887  			return chunkOrderError
 888  		}
 889  		d.stage = dsSeenIHDR
 890  		return d.parseIHDR(length)
 891  	case "PLTE":
 892  		if d.stage != dsSeenIHDR {
 893  			return chunkOrderError
 894  		}
 895  		d.stage = dsSeenPLTE
 896  		return d.parsePLTE(length)
 897  	case "tRNS":
 898  		if cbPaletted(d.cb) {
 899  			if d.stage != dsSeenPLTE {
 900  				return chunkOrderError
 901  			}
 902  		} else if cbTrueColor(d.cb) {
 903  			if d.stage != dsSeenIHDR && 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  		if configOnly {
 924  			return nil
 925  		}
 926  		return d.parseIDAT(length)
 927  	case "IEND":
 928  		if d.stage != dsSeenIDAT {
 929  			return chunkOrderError
 930  		}
 931  		d.stage = dsSeenIEND
 932  		return d.parseIEND(length)
 933  	}
 934  	if length > 0x7fffffff {
 935  		return FormatError(fmt.Sprintf("Bad chunk length: %d", length))
 936  	}
 937  	// Ignore this chunk (of a known length).
 938  	var ignored [4096]byte
 939  	for length > 0 {
 940  		n, err := io.ReadFull(d.r, ignored[:min(len(ignored), int(length))])
 941  		if err != nil {
 942  			return err
 943  		}
 944  		d.crc.Write(ignored[:n])
 945  		length -= uint32(n)
 946  	}
 947  	return d.verifyChecksum()
 948  }
 949  
 950  func (d *decoder) verifyChecksum() error {
 951  	if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil {
 952  		return err
 953  	}
 954  	if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() {
 955  		return FormatError("invalid checksum")
 956  	}
 957  	return nil
 958  }
 959  
 960  func (d *decoder) checkHeader() error {
 961  	_, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)])
 962  	if err != nil {
 963  		return err
 964  	}
 965  	if d.tmp[:len(pngHeader)] != pngHeader {
 966  		return FormatError("not a PNG file")
 967  	}
 968  	return nil
 969  }
 970  
 971  // Decode reads a PNG image from r and returns it as an [image.Image].
 972  // The type of Image returned depends on the PNG contents.
 973  func Decode(r io.Reader) (image.Image, error) {
 974  	d := &decoder{
 975  		r:   r,
 976  		crc: crc32.NewIEEE(),
 977  	}
 978  	if err := d.checkHeader(); err != nil {
 979  		if err == io.EOF {
 980  			err = io.ErrUnexpectedEOF
 981  		}
 982  		return nil, err
 983  	}
 984  	for d.stage != dsSeenIEND {
 985  		if err := d.parseChunk(false); err != nil {
 986  			if err == io.EOF {
 987  				err = io.ErrUnexpectedEOF
 988  			}
 989  			return nil, err
 990  		}
 991  	}
 992  	return d.img, nil
 993  }
 994  
 995  // DecodeConfig returns the color model and dimensions of a PNG image without
 996  // decoding the entire image.
 997  func DecodeConfig(r io.Reader) (image.Config, error) {
 998  	d := &decoder{
 999  		r:   r,
1000  		crc: crc32.NewIEEE(),
1001  	}
1002  	if err := d.checkHeader(); err != nil {
1003  		if err == io.EOF {
1004  			err = io.ErrUnexpectedEOF
1005  		}
1006  		return image.Config{}, err
1007  	}
1008  
1009  	for {
1010  		if err := d.parseChunk(true); err != nil {
1011  			if err == io.EOF {
1012  				err = io.ErrUnexpectedEOF
1013  			}
1014  			return image.Config{}, err
1015  		}
1016  
1017  		if cbPaletted(d.cb) {
1018  			if d.stage >= dsSeentRNS {
1019  				break
1020  			}
1021  		} else {
1022  			if d.stage >= dsSeenIHDR {
1023  				break
1024  			}
1025  		}
1026  	}
1027  
1028  	var cm color.Model
1029  	switch d.cb {
1030  	case cbG1, cbG2, cbG4, cbG8:
1031  		cm = color.GrayModel
1032  	case cbGA8:
1033  		cm = color.NRGBAModel
1034  	case cbTC8:
1035  		cm = color.RGBAModel
1036  	case cbP1, cbP2, cbP4, cbP8:
1037  		cm = d.palette
1038  	case cbTCA8:
1039  		cm = color.NRGBAModel
1040  	case cbG16:
1041  		cm = color.Gray16Model
1042  	case cbGA16:
1043  		cm = color.NRGBA64Model
1044  	case cbTC16:
1045  		cm = color.RGBA64Model
1046  	case cbTCA16:
1047  		cm = color.NRGBA64Model
1048  	}
1049  	return image.Config{
1050  		ColorModel: cm,
1051  		Width:      d.width,
1052  		Height:     d.height,
1053  	}, nil
1054  }
1055  
1056  func init() {
1057  	image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)
1058  }
1059