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