Black Lives Matter. Support the Equal Justice Initiative.

Source file src/image/png/reader.go

Documentation: image/png

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

View as plain text