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