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