libgo: update to go1.9
[official-gcc.git] / libgo / go / image / png / reader.go
blob4f043a0e4244d804953e0cdf5ca4a0f40499bee8
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.
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
10 import (
11 "compress/zlib"
12 "encoding/binary"
13 "fmt"
14 "hash"
15 "hash/crc32"
16 "image"
17 "image/color"
18 "io"
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
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
50 func cbPaletted(cb int) bool {
51 return cbP1 <= cb && cb <= cbP8
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
64 // Interlace type.
65 const (
66 itNone = 0
67 itAdam7 = 1
70 // interlaceScan defines the placement and size of a pass for Adam7 interlacing.
71 type interlaceScan struct {
72 xFactor, yFactor, xOffset, yOffset int
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},
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
102 const pngHeader = "\x89PNG\r\n\x1a\n"
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
117 // useTransparent and transparent are used for grayscale and truecolor
118 // transparency, as opposed to palette transparency.
119 useTransparent bool
120 transparent [6]byte
123 // A FormatError reports that the input is not a valid PNG.
124 type FormatError string
126 func (e FormatError) Error() string { return "png: invalid format: " + string(e) }
128 var chunkOrderError = FormatError("chunk out of order")
130 // An UnsupportedError reports that the input uses a valid but unimplemented PNG feature.
131 type UnsupportedError string
133 func (e UnsupportedError) Error() string { return "png: unsupported feature: " + string(e) }
135 func min(a, b int) int {
136 if a < b {
137 return a
139 return b
142 func (d *decoder) parseIHDR(length uint32) error {
143 if length != 13 {
144 return FormatError("bad IHDR length")
146 if _, err := io.ReadFull(d.r, d.tmp[:13]); err != nil {
147 return err
149 d.crc.Write(d.tmp[:13])
150 if d.tmp[10] != 0 {
151 return UnsupportedError("compression method")
153 if d.tmp[11] != 0 {
154 return UnsupportedError("filter method")
156 if d.tmp[12] != itNone && d.tmp[12] != itAdam7 {
157 return FormatError("invalid interlace method")
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")
165 nPixels := int64(w) * int64(h)
166 if nPixels != int64(int(nPixels)) {
167 return UnsupportedError("dimension overflow")
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
179 case 2:
180 switch d.tmp[9] {
181 case ctGrayscale:
182 d.cb = cbG2
183 case ctPaletted:
184 d.cb = cbP2
186 case 4:
187 switch d.tmp[9] {
188 case ctGrayscale:
189 d.cb = cbG4
190 case ctPaletted:
191 d.cb = cbP4
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
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
218 if d.cb == cbInvalid {
219 return UnsupportedError(fmt.Sprintf("bit depth %d, color type %d", d.tmp[8], d.tmp[9]))
221 d.width, d.height = int(w), int(h)
222 return d.verifyChecksum()
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")
230 n, err := io.ReadFull(d.r, d.tmp[:3*np])
231 if err != nil {
232 return err
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}
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}
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")
256 return d.verifyChecksum()
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")
265 n, err := io.ReadFull(d.r, d.tmp[:length])
266 if err != nil {
267 return err
269 d.crc.Write(d.tmp[:n])
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
280 d.useTransparent = true
282 case cbTC8, cbTC16:
283 if length != 6 {
284 return FormatError("bad tRNS length")
286 n, err := io.ReadFull(d.r, d.tmp[:length])
287 if err != nil {
288 return err
290 d.crc.Write(d.tmp[:n])
292 copy(d.transparent[:], d.tmp[:length])
293 d.useTransparent = true
295 case cbP1, cbP2, cbP4, cbP8:
296 if length > 256 {
297 return FormatError("bad tRNS length")
299 n, err := io.ReadFull(d.r, d.tmp[:length])
300 if err != nil {
301 return err
303 d.crc.Write(d.tmp[:n])
305 if len(d.palette) < n {
306 d.palette = d.palette[:n]
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]}
313 default:
314 return FormatError("tRNS, color type mismatch")
316 return d.verifyChecksum()
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
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
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
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")
344 d.crc.Reset()
345 d.crc.Write(d.tmp[4:8])
347 if int(d.idatLength) < 0 {
348 return 0, UnsupportedError("IDAT chunk length overflow")
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
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
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
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
375 for pass := 0; pass < 7; pass++ {
376 imagePass, err := d.readImagePass(r, pass, false)
377 if err != nil {
378 return nil, err
380 if imagePass != nil {
381 d.mergePassInto(img, imagePass, pass)
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
392 n, err = r.Read(d.tmp[:1])
394 if err != nil && err != io.EOF {
395 return nil, FormatError(err.Error())
397 if n != 0 || d.idatLength != 0 {
398 return nil, FormatError("too much pixel data")
401 return img, nil
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
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
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
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
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
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
484 case cbTCA16:
485 bitsPerPixel = 64
486 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
487 img = nrgba64
489 if allocateOnly {
490 return img, nil
492 bytesPerPixel := (bitsPerPixel + 7) / 8
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)
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")
507 return nil, err
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]
520 case ftUp:
521 for i, p := range pdat {
522 cdat[i] += p
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
531 for i := bytesPerPixel; i < len(cdat); i++ {
532 cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2)
534 case ftPaeth:
535 filterPaeth(cdat, pdat, bytesPerPixel)
536 default:
537 return nil, FormatError("bad filter type")
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
553 nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
554 b <<= 1
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
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
577 nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
578 b <<= 2
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
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
601 nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
602 b <<= 4
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
614 case cbG8:
615 if d.useTransparent {
616 ty := d.transparent[1]
617 for x := 0; x < width; x++ {
618 ycol := cdat[x]
619 acol := uint8(0xff)
620 if ycol == ty {
621 acol = 0x00
623 nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, acol})
625 } else {
626 copy(gray.Pix[pixOffset:], cdat)
627 pixOffset += gray.Stride
629 case cbGA8:
630 for x := 0; x < width; x++ {
631 ycol := cdat[2*x+0]
632 nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]})
634 case cbTC8:
635 if d.useTransparent {
636 pix, i, j := nrgba.Pix, pixOffset, 0
637 tr, tg, tb := d.transparent[1], d.transparent[3], d.transparent[5]
638 for x := 0; x < width; x++ {
639 r := cdat[j+0]
640 g := cdat[j+1]
641 b := cdat[j+2]
642 a := uint8(0xff)
643 if r == tr && g == tg && b == tb {
644 a = 0x00
646 pix[i+0] = r
647 pix[i+1] = g
648 pix[i+2] = b
649 pix[i+3] = a
650 i += 4
651 j += 3
653 pixOffset += nrgba.Stride
654 } else {
655 pix, i, j := rgba.Pix, pixOffset, 0
656 for x := 0; x < width; x++ {
657 pix[i+0] = cdat[j+0]
658 pix[i+1] = cdat[j+1]
659 pix[i+2] = cdat[j+2]
660 pix[i+3] = 0xff
661 i += 4
662 j += 3
664 pixOffset += rgba.Stride
666 case cbP1:
667 for x := 0; x < width; x += 8 {
668 b := cdat[x/8]
669 for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
670 idx := b >> 7
671 if len(paletted.Palette) <= int(idx) {
672 paletted.Palette = paletted.Palette[:int(idx)+1]
674 paletted.SetColorIndex(x+x2, y, idx)
675 b <<= 1
678 case cbP2:
679 for x := 0; x < width; x += 4 {
680 b := cdat[x/4]
681 for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
682 idx := b >> 6
683 if len(paletted.Palette) <= int(idx) {
684 paletted.Palette = paletted.Palette[:int(idx)+1]
686 paletted.SetColorIndex(x+x2, y, idx)
687 b <<= 2
690 case cbP4:
691 for x := 0; x < width; x += 2 {
692 b := cdat[x/2]
693 for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
694 idx := b >> 4
695 if len(paletted.Palette) <= int(idx) {
696 paletted.Palette = paletted.Palette[:int(idx)+1]
698 paletted.SetColorIndex(x+x2, y, idx)
699 b <<= 4
702 case cbP8:
703 if len(paletted.Palette) != 255 {
704 for x := 0; x < width; x++ {
705 if len(paletted.Palette) <= int(cdat[x]) {
706 paletted.Palette = paletted.Palette[:int(cdat[x])+1]
710 copy(paletted.Pix[pixOffset:], cdat)
711 pixOffset += paletted.Stride
712 case cbTCA8:
713 copy(nrgba.Pix[pixOffset:], cdat)
714 pixOffset += nrgba.Stride
715 case cbG16:
716 if d.useTransparent {
717 ty := uint16(d.transparent[0])<<8 | uint16(d.transparent[1])
718 for x := 0; x < width; x++ {
719 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
720 acol := uint16(0xffff)
721 if ycol == ty {
722 acol = 0x0000
724 nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
726 } else {
727 for x := 0; x < width; x++ {
728 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
729 gray16.SetGray16(x, y, color.Gray16{ycol})
732 case cbGA16:
733 for x := 0; x < width; x++ {
734 ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1])
735 acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3])
736 nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
738 case cbTC16:
739 if d.useTransparent {
740 tr := uint16(d.transparent[0])<<8 | uint16(d.transparent[1])
741 tg := uint16(d.transparent[2])<<8 | uint16(d.transparent[3])
742 tb := uint16(d.transparent[4])<<8 | uint16(d.transparent[5])
743 for x := 0; x < width; x++ {
744 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
745 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
746 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
747 acol := uint16(0xffff)
748 if rcol == tr && gcol == tg && bcol == tb {
749 acol = 0x0000
751 nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol})
753 } else {
754 for x := 0; x < width; x++ {
755 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
756 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
757 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
758 rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff})
761 case cbTCA16:
762 for x := 0; x < width; x++ {
763 rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1])
764 gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3])
765 bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5])
766 acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7])
767 nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol})
771 // The current row for y is the previous row for y+1.
772 pr, cr = cr, pr
775 return img, nil
778 // mergePassInto merges a single pass into a full sized image.
779 func (d *decoder) mergePassInto(dst image.Image, src image.Image, pass int) {
780 p := interlacing[pass]
781 var (
782 srcPix []uint8
783 dstPix []uint8
784 stride int
785 rect image.Rectangle
786 bytesPerPixel int
788 switch target := dst.(type) {
789 case *image.Alpha:
790 srcPix = src.(*image.Alpha).Pix
791 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
792 bytesPerPixel = 1
793 case *image.Alpha16:
794 srcPix = src.(*image.Alpha16).Pix
795 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
796 bytesPerPixel = 2
797 case *image.Gray:
798 srcPix = src.(*image.Gray).Pix
799 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
800 bytesPerPixel = 1
801 case *image.Gray16:
802 srcPix = src.(*image.Gray16).Pix
803 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
804 bytesPerPixel = 2
805 case *image.NRGBA:
806 srcPix = src.(*image.NRGBA).Pix
807 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
808 bytesPerPixel = 4
809 case *image.NRGBA64:
810 srcPix = src.(*image.NRGBA64).Pix
811 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
812 bytesPerPixel = 8
813 case *image.Paletted:
814 srcPix = src.(*image.Paletted).Pix
815 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
816 bytesPerPixel = 1
817 case *image.RGBA:
818 srcPix = src.(*image.RGBA).Pix
819 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
820 bytesPerPixel = 4
821 case *image.RGBA64:
822 srcPix = src.(*image.RGBA64).Pix
823 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
824 bytesPerPixel = 8
826 s, bounds := 0, src.Bounds()
827 for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
828 dBase := (y*p.yFactor+p.yOffset-rect.Min.Y)*stride + (p.xOffset-rect.Min.X)*bytesPerPixel
829 for x := bounds.Min.X; x < bounds.Max.X; x++ {
830 d := dBase + x*p.xFactor*bytesPerPixel
831 copy(dstPix[d:], srcPix[s:s+bytesPerPixel])
832 s += bytesPerPixel
837 func (d *decoder) parseIDAT(length uint32) (err error) {
838 d.idatLength = length
839 d.img, err = d.decode()
840 if err != nil {
841 return err
843 return d.verifyChecksum()
846 func (d *decoder) parseIEND(length uint32) error {
847 if length != 0 {
848 return FormatError("bad IEND length")
850 return d.verifyChecksum()
853 func (d *decoder) parseChunk() error {
854 // Read the length and chunk type.
855 n, err := io.ReadFull(d.r, d.tmp[:8])
856 if err != nil {
857 return err
859 length := binary.BigEndian.Uint32(d.tmp[:4])
860 d.crc.Reset()
861 d.crc.Write(d.tmp[4:8])
863 // Read the chunk data.
864 switch string(d.tmp[4:8]) {
865 case "IHDR":
866 if d.stage != dsStart {
867 return chunkOrderError
869 d.stage = dsSeenIHDR
870 return d.parseIHDR(length)
871 case "PLTE":
872 if d.stage != dsSeenIHDR {
873 return chunkOrderError
875 d.stage = dsSeenPLTE
876 return d.parsePLTE(length)
877 case "tRNS":
878 if cbPaletted(d.cb) {
879 if d.stage != dsSeenPLTE {
880 return chunkOrderError
882 } else if d.stage != dsSeenIHDR {
883 return chunkOrderError
885 d.stage = dsSeentRNS
886 return d.parsetRNS(length)
887 case "IDAT":
888 if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.stage == dsSeenIHDR && cbPaletted(d.cb)) {
889 return chunkOrderError
890 } else if d.stage == dsSeenIDAT {
891 // Ignore trailing zero-length or garbage IDAT chunks.
893 // This does not affect valid PNG images that contain multiple IDAT
894 // chunks, since the first call to parseIDAT below will consume all
895 // consecutive IDAT chunks required for decoding the image.
896 break
898 d.stage = dsSeenIDAT
899 return d.parseIDAT(length)
900 case "IEND":
901 if d.stage != dsSeenIDAT {
902 return chunkOrderError
904 d.stage = dsSeenIEND
905 return d.parseIEND(length)
907 if length > 0x7fffffff {
908 return FormatError(fmt.Sprintf("Bad chunk length: %d", length))
910 // Ignore this chunk (of a known length).
911 var ignored [4096]byte
912 for length > 0 {
913 n, err = io.ReadFull(d.r, ignored[:min(len(ignored), int(length))])
914 if err != nil {
915 return err
917 d.crc.Write(ignored[:n])
918 length -= uint32(n)
920 return d.verifyChecksum()
923 func (d *decoder) verifyChecksum() error {
924 if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil {
925 return err
927 if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() {
928 return FormatError("invalid checksum")
930 return nil
933 func (d *decoder) checkHeader() error {
934 _, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)])
935 if err != nil {
936 return err
938 if string(d.tmp[:len(pngHeader)]) != pngHeader {
939 return FormatError("not a PNG file")
941 return nil
944 // Decode reads a PNG image from r and returns it as an image.Image.
945 // The type of Image returned depends on the PNG contents.
946 func Decode(r io.Reader) (image.Image, error) {
947 d := &decoder{
948 r: r,
949 crc: crc32.NewIEEE(),
951 if err := d.checkHeader(); err != nil {
952 if err == io.EOF {
953 err = io.ErrUnexpectedEOF
955 return nil, err
957 for d.stage != dsSeenIEND {
958 if err := d.parseChunk(); err != nil {
959 if err == io.EOF {
960 err = io.ErrUnexpectedEOF
962 return nil, err
965 return d.img, nil
968 // DecodeConfig returns the color model and dimensions of a PNG image without
969 // decoding the entire image.
970 func DecodeConfig(r io.Reader) (image.Config, error) {
971 d := &decoder{
972 r: r,
973 crc: crc32.NewIEEE(),
975 if err := d.checkHeader(); err != nil {
976 if err == io.EOF {
977 err = io.ErrUnexpectedEOF
979 return image.Config{}, err
981 for {
982 if err := d.parseChunk(); err != nil {
983 if err == io.EOF {
984 err = io.ErrUnexpectedEOF
986 return image.Config{}, err
988 paletted := cbPaletted(d.cb)
989 if d.stage == dsSeenIHDR && !paletted {
990 break
992 if d.stage == dsSeenPLTE && paletted {
993 break
996 var cm color.Model
997 switch d.cb {
998 case cbG1, cbG2, cbG4, cbG8:
999 cm = color.GrayModel
1000 case cbGA8:
1001 cm = color.NRGBAModel
1002 case cbTC8:
1003 cm = color.RGBAModel
1004 case cbP1, cbP2, cbP4, cbP8:
1005 cm = d.palette
1006 case cbTCA8:
1007 cm = color.NRGBAModel
1008 case cbG16:
1009 cm = color.Gray16Model
1010 case cbGA16:
1011 cm = color.NRGBA64Model
1012 case cbTC16:
1013 cm = color.RGBA64Model
1014 case cbTCA16:
1015 cm = color.NRGBA64Model
1017 return image.Config{
1018 ColorModel: cm,
1019 Width: d.width,
1020 Height: d.height,
1021 }, nil
1024 func init() {
1025 image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)