...
Run Format

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

View as plain text