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