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 source := src.(*image.Paletted)
825 srcPix = source.Pix
826 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
827 bytesPerPixel = 1
828 if len(target.Palette) < len(source.Palette) {
829
830
831
832
833 target.Palette = source.Palette
834 }
835 case *image.RGBA:
836 srcPix = src.(*image.RGBA).Pix
837 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
838 bytesPerPixel = 4
839 case *image.RGBA64:
840 srcPix = src.(*image.RGBA64).Pix
841 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
842 bytesPerPixel = 8
843 }
844 s, bounds := 0, src.Bounds()
845 for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
846 dBase := (y*p.yFactor+p.yOffset-rect.Min.Y)*stride + (p.xOffset-rect.Min.X)*bytesPerPixel
847 for x := bounds.Min.X; x < bounds.Max.X; x++ {
848 d := dBase + x*p.xFactor*bytesPerPixel
849 copy(dstPix[d:], srcPix[s:s+bytesPerPixel])
850 s += bytesPerPixel
851 }
852 }
853 }
854
855 func (d *decoder) parseIDAT(length uint32) (err error) {
856 d.idatLength = length
857 d.img, err = d.decode()
858 if err != nil {
859 return err
860 }
861 return d.verifyChecksum()
862 }
863
864 func (d *decoder) parseIEND(length uint32) error {
865 if length != 0 {
866 return FormatError("bad IEND length")
867 }
868 return d.verifyChecksum()
869 }
870
871 func (d *decoder) parseChunk() error {
872
873 if _, err := io.ReadFull(d.r, d.tmp[:8]); err != nil {
874 return err
875 }
876 length := binary.BigEndian.Uint32(d.tmp[:4])
877 d.crc.Reset()
878 d.crc.Write(d.tmp[4:8])
879
880
881 switch string(d.tmp[4:8]) {
882 case "IHDR":
883 if d.stage != dsStart {
884 return chunkOrderError
885 }
886 d.stage = dsSeenIHDR
887 return d.parseIHDR(length)
888 case "PLTE":
889 if d.stage != dsSeenIHDR {
890 return chunkOrderError
891 }
892 d.stage = dsSeenPLTE
893 return d.parsePLTE(length)
894 case "tRNS":
895 if cbPaletted(d.cb) {
896 if d.stage != dsSeenPLTE {
897 return chunkOrderError
898 }
899 } else if d.stage != dsSeenIHDR {
900 return chunkOrderError
901 }
902 d.stage = dsSeentRNS
903 return d.parsetRNS(length)
904 case "IDAT":
905 if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.stage == dsSeenIHDR && cbPaletted(d.cb)) {
906 return chunkOrderError
907 } else if d.stage == dsSeenIDAT {
908
909
910
911
912
913 break
914 }
915 d.stage = dsSeenIDAT
916 return d.parseIDAT(length)
917 case "IEND":
918 if d.stage != dsSeenIDAT {
919 return chunkOrderError
920 }
921 d.stage = dsSeenIEND
922 return d.parseIEND(length)
923 }
924 if length > 0x7fffffff {
925 return FormatError(fmt.Sprintf("Bad chunk length: %d", length))
926 }
927
928 var ignored [4096]byte
929 for length > 0 {
930 n, err := io.ReadFull(d.r, ignored[:min(len(ignored), int(length))])
931 if err != nil {
932 return err
933 }
934 d.crc.Write(ignored[:n])
935 length -= uint32(n)
936 }
937 return d.verifyChecksum()
938 }
939
940 func (d *decoder) verifyChecksum() error {
941 if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil {
942 return err
943 }
944 if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() {
945 return FormatError("invalid checksum")
946 }
947 return nil
948 }
949
950 func (d *decoder) checkHeader() error {
951 _, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)])
952 if err != nil {
953 return err
954 }
955 if string(d.tmp[:len(pngHeader)]) != pngHeader {
956 return FormatError("not a PNG file")
957 }
958 return nil
959 }
960
961
962
963 func Decode(r io.Reader) (image.Image, error) {
964 d := &decoder{
965 r: r,
966 crc: crc32.NewIEEE(),
967 }
968 if err := d.checkHeader(); err != nil {
969 if err == io.EOF {
970 err = io.ErrUnexpectedEOF
971 }
972 return nil, err
973 }
974 for d.stage != dsSeenIEND {
975 if err := d.parseChunk(); err != nil {
976 if err == io.EOF {
977 err = io.ErrUnexpectedEOF
978 }
979 return nil, err
980 }
981 }
982 return d.img, nil
983 }
984
985
986
987 func DecodeConfig(r io.Reader) (image.Config, error) {
988 d := &decoder{
989 r: r,
990 crc: crc32.NewIEEE(),
991 }
992 if err := d.checkHeader(); err != nil {
993 if err == io.EOF {
994 err = io.ErrUnexpectedEOF
995 }
996 return image.Config{}, err
997 }
998 for {
999 if err := d.parseChunk(); err != nil {
1000 if err == io.EOF {
1001 err = io.ErrUnexpectedEOF
1002 }
1003 return image.Config{}, err
1004 }
1005 paletted := cbPaletted(d.cb)
1006 if d.stage == dsSeenIHDR && !paletted {
1007 break
1008 }
1009 if d.stage == dsSeenPLTE && paletted {
1010 break
1011 }
1012 }
1013 var cm color.Model
1014 switch d.cb {
1015 case cbG1, cbG2, cbG4, cbG8:
1016 cm = color.GrayModel
1017 case cbGA8:
1018 cm = color.NRGBAModel
1019 case cbTC8:
1020 cm = color.RGBAModel
1021 case cbP1, cbP2, cbP4, cbP8:
1022 cm = d.palette
1023 case cbTCA8:
1024 cm = color.NRGBAModel
1025 case cbG16:
1026 cm = color.Gray16Model
1027 case cbGA16:
1028 cm = color.NRGBA64Model
1029 case cbTC16:
1030 cm = color.RGBA64Model
1031 case cbTCA16:
1032 cm = color.NRGBA64Model
1033 }
1034 return image.Config{
1035 ColorModel: cm,
1036 Width: d.width,
1037 Height: d.height,
1038 }, nil
1039 }
1040
1041 func init() {
1042 image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)
1043 }
1044
View as plain text