...

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

View as plain text