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

View as plain text