Source file src/image/png/reader.go

     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  		source := src.(*image.Paletted)
   825  		srcPix = source.Pix
   826  		dstPix, stride, rect = target.Pix, target.Stride, target.Rect
   827  		bytesPerPixel = 1
   828  		if len(target.Palette) < len(source.Palette) {
   829  			// readImagePass can return a paletted image whose implicit palette
   830  			// length (one more than the maximum Pix value) is larger than the
   831  			// explicit palette length (what's in the PLTE chunk). Make the
   832  			// same adjustment here.
   833  			target.Palette = source.Palette
   834  		}
   835  	case *image.RGBA:
   836  		srcPix = src.(*image.RGBA).Pix
   837  		dstPix, stride, rect = target.Pix, target.Stride, target.Rect
   838  		bytesPerPixel = 4
   839  	case *image.RGBA64:
   840  		srcPix = src.(*image.RGBA64).Pix
   841  		dstPix, stride, rect = target.Pix, target.Stride, target.Rect
   842  		bytesPerPixel = 8
   843  	}
   844  	s, bounds := 0, src.Bounds()
   845  	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
   846  		dBase := (y*p.yFactor+p.yOffset-rect.Min.Y)*stride + (p.xOffset-rect.Min.X)*bytesPerPixel
   847  		for x := bounds.Min.X; x < bounds.Max.X; x++ {
   848  			d := dBase + x*p.xFactor*bytesPerPixel
   849  			copy(dstPix[d:], srcPix[s:s+bytesPerPixel])
   850  			s += bytesPerPixel
   851  		}
   852  	}
   853  }
   854  
   855  func (d *decoder) parseIDAT(length uint32) (err error) {
   856  	d.idatLength = length
   857  	d.img, err = d.decode()
   858  	if err != nil {
   859  		return err
   860  	}
   861  	return d.verifyChecksum()
   862  }
   863  
   864  func (d *decoder) parseIEND(length uint32) error {
   865  	if length != 0 {
   866  		return FormatError("bad IEND length")
   867  	}
   868  	return d.verifyChecksum()
   869  }
   870  
   871  func (d *decoder) parseChunk() error {
   872  	// Read the length and chunk type.
   873  	if _, err := io.ReadFull(d.r, d.tmp[:8]); err != nil {
   874  		return err
   875  	}
   876  	length := binary.BigEndian.Uint32(d.tmp[:4])
   877  	d.crc.Reset()
   878  	d.crc.Write(d.tmp[4:8])
   879  
   880  	// Read the chunk data.
   881  	switch string(d.tmp[4:8]) {
   882  	case "IHDR":
   883  		if d.stage != dsStart {
   884  			return chunkOrderError
   885  		}
   886  		d.stage = dsSeenIHDR
   887  		return d.parseIHDR(length)
   888  	case "PLTE":
   889  		if d.stage != dsSeenIHDR {
   890  			return chunkOrderError
   891  		}
   892  		d.stage = dsSeenPLTE
   893  		return d.parsePLTE(length)
   894  	case "tRNS":
   895  		if cbPaletted(d.cb) {
   896  			if d.stage != dsSeenPLTE {
   897  				return chunkOrderError
   898  			}
   899  		} else if d.stage != dsSeenIHDR {
   900  			return chunkOrderError
   901  		}
   902  		d.stage = dsSeentRNS
   903  		return d.parsetRNS(length)
   904  	case "IDAT":
   905  		if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.stage == dsSeenIHDR && cbPaletted(d.cb)) {
   906  			return chunkOrderError
   907  		} else if d.stage == dsSeenIDAT {
   908  			// Ignore trailing zero-length or garbage IDAT chunks.
   909  			//
   910  			// This does not affect valid PNG images that contain multiple IDAT
   911  			// chunks, since the first call to parseIDAT below will consume all
   912  			// consecutive IDAT chunks required for decoding the image.
   913  			break
   914  		}
   915  		d.stage = dsSeenIDAT
   916  		return d.parseIDAT(length)
   917  	case "IEND":
   918  		if d.stage != dsSeenIDAT {
   919  			return chunkOrderError
   920  		}
   921  		d.stage = dsSeenIEND
   922  		return d.parseIEND(length)
   923  	}
   924  	if length > 0x7fffffff {
   925  		return FormatError(fmt.Sprintf("Bad chunk length: %d", length))
   926  	}
   927  	// Ignore this chunk (of a known length).
   928  	var ignored [4096]byte
   929  	for length > 0 {
   930  		n, err := io.ReadFull(d.r, ignored[:min(len(ignored), int(length))])
   931  		if err != nil {
   932  			return err
   933  		}
   934  		d.crc.Write(ignored[:n])
   935  		length -= uint32(n)
   936  	}
   937  	return d.verifyChecksum()
   938  }
   939  
   940  func (d *decoder) verifyChecksum() error {
   941  	if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil {
   942  		return err
   943  	}
   944  	if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() {
   945  		return FormatError("invalid checksum")
   946  	}
   947  	return nil
   948  }
   949  
   950  func (d *decoder) checkHeader() error {
   951  	_, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)])
   952  	if err != nil {
   953  		return err
   954  	}
   955  	if string(d.tmp[:len(pngHeader)]) != pngHeader {
   956  		return FormatError("not a PNG file")
   957  	}
   958  	return nil
   959  }
   960  
   961  // Decode reads a PNG image from r and returns it as an image.Image.
   962  // The type of Image returned depends on the PNG contents.
   963  func Decode(r io.Reader) (image.Image, 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 nil, err
   973  	}
   974  	for d.stage != dsSeenIEND {
   975  		if err := d.parseChunk(); err != nil {
   976  			if err == io.EOF {
   977  				err = io.ErrUnexpectedEOF
   978  			}
   979  			return nil, err
   980  		}
   981  	}
   982  	return d.img, nil
   983  }
   984  
   985  // DecodeConfig returns the color model and dimensions of a PNG image without
   986  // decoding the entire image.
   987  func DecodeConfig(r io.Reader) (image.Config, error) {
   988  	d := &decoder{
   989  		r:   r,
   990  		crc: crc32.NewIEEE(),
   991  	}
   992  	if err := d.checkHeader(); err != nil {
   993  		if err == io.EOF {
   994  			err = io.ErrUnexpectedEOF
   995  		}
   996  		return image.Config{}, err
   997  	}
   998  	for {
   999  		if err := d.parseChunk(); err != nil {
  1000  			if err == io.EOF {
  1001  				err = io.ErrUnexpectedEOF
  1002  			}
  1003  			return image.Config{}, err
  1004  		}
  1005  		paletted := cbPaletted(d.cb)
  1006  		if d.stage == dsSeenIHDR && !paletted {
  1007  			break
  1008  		}
  1009  		if d.stage == dsSeenPLTE && paletted {
  1010  			break
  1011  		}
  1012  	}
  1013  	var cm color.Model
  1014  	switch d.cb {
  1015  	case cbG1, cbG2, cbG4, cbG8:
  1016  		cm = color.GrayModel
  1017  	case cbGA8:
  1018  		cm = color.NRGBAModel
  1019  	case cbTC8:
  1020  		cm = color.RGBAModel
  1021  	case cbP1, cbP2, cbP4, cbP8:
  1022  		cm = d.palette
  1023  	case cbTCA8:
  1024  		cm = color.NRGBAModel
  1025  	case cbG16:
  1026  		cm = color.Gray16Model
  1027  	case cbGA16:
  1028  		cm = color.NRGBA64Model
  1029  	case cbTC16:
  1030  		cm = color.RGBA64Model
  1031  	case cbTCA16:
  1032  		cm = color.NRGBA64Model
  1033  	}
  1034  	return image.Config{
  1035  		ColorModel: cm,
  1036  		Width:      d.width,
  1037  		Height:     d.height,
  1038  	}, nil
  1039  }
  1040  
  1041  func init() {
  1042  	image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)
  1043  }
  1044  

View as plain text