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

View as plain text