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  }