github.com/freddyisaac/sicortex-golang@v0.0.0-20231019035217-e03519e66f60/src/image/png/reader.go (about)

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