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