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 nPixels := int64(w) * int64(h)
167 if nPixels != int64(int(nPixels)) {
168 return UnsupportedError("dimension overflow")
169 }
170
171 if nPixels != (nPixels*8)/8 {
172 return UnsupportedError("dimension overflow")
173 }
174
175 d.cb = cbInvalid
176 d.depth = int(d.tmp[8])
177 switch d.depth {
178 case 1:
179 switch d.tmp[9] {
180 case ctGrayscale:
181 d.cb = cbG1
182 case ctPaletted:
183 d.cb = cbP1
184 }
185 case 2:
186 switch d.tmp[9] {
187 case ctGrayscale:
188 d.cb = cbG2
189 case ctPaletted:
190 d.cb = cbP2
191 }
192 case 4:
193 switch d.tmp[9] {
194 case ctGrayscale:
195 d.cb = cbG4
196 case ctPaletted:
197 d.cb = cbP4
198 }
199 case 8:
200 switch d.tmp[9] {
201 case ctGrayscale:
202 d.cb = cbG8
203 case ctTrueColor:
204 d.cb = cbTC8
205 case ctPaletted:
206 d.cb = cbP8
207 case ctGrayscaleAlpha:
208 d.cb = cbGA8
209 case ctTrueColorAlpha:
210 d.cb = cbTCA8
211 }
212 case 16:
213 switch d.tmp[9] {
214 case ctGrayscale:
215 d.cb = cbG16
216 case ctTrueColor:
217 d.cb = cbTC16
218 case ctGrayscaleAlpha:
219 d.cb = cbGA16
220 case ctTrueColorAlpha:
221 d.cb = cbTCA16
222 }
223 }
224 if d.cb == cbInvalid {
225 return UnsupportedError(fmt.Sprintf("bit depth %d, color type %d", d.tmp[8], d.tmp[9]))
226 }
227 d.width, d.height = int(w), int(h)
228 return d.verifyChecksum()
229 }
230
231 func (d *decoder) parsePLTE(length uint32) error {
232 np := int(length / 3)
233 if length%3 != 0 || np <= 0 || np > 256 || np > 1<<uint(d.depth) {
234 return FormatError("bad PLTE length")
235 }
236 n, err := io.ReadFull(d.r, d.tmp[:3*np])
237 if err != nil {
238 return err
239 }
240 d.crc.Write(d.tmp[:n])
241 switch d.cb {
242 case cbP1, cbP2, cbP4, cbP8:
243 d.palette = make(color.Palette, 256)
244 for i := 0; i < np; i++ {
245 d.palette[i] = color.RGBA{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff}
246 }
247 for i := np; i < 256; i++ {
248
249
250
251
252
253 d.palette[i] = color.RGBA{0x00, 0x00, 0x00, 0xff}
254 }
255 d.palette = d.palette[:np]
256 case cbTC8, cbTCA8, cbTC16, cbTCA16:
257
258
259 default:
260 return FormatError("PLTE, color type mismatch")
261 }
262 return d.verifyChecksum()
263 }
264
265 func (d *decoder) parsetRNS(length uint32) error {
266 switch d.cb {
267 case cbG1, cbG2, cbG4, cbG8, cbG16:
268 if length != 2 {
269 return FormatError("bad tRNS length")
270 }
271 n, err := io.ReadFull(d.r, d.tmp[:length])
272 if err != nil {
273 return err
274 }
275 d.crc.Write(d.tmp[:n])
276
277 copy(d.transparent[:], d.tmp[:length])
278 switch d.cb {
279 case cbG1:
280 d.transparent[1] *= 0xff
281 case cbG2:
282 d.transparent[1] *= 0x55
283 case cbG4:
284 d.transparent[1] *= 0x11
285 }
286 d.useTransparent = true
287
288 case cbTC8, cbTC16:
289 if length != 6 {
290 return FormatError("bad tRNS length")
291 }
292 n, err := io.ReadFull(d.r, d.tmp[:length])
293 if err != nil {
294 return err
295 }
296 d.crc.Write(d.tmp[:n])
297
298 copy(d.transparent[:], d.tmp[:length])
299 d.useTransparent = true
300
301 case cbP1, cbP2, cbP4, cbP8:
302 if length > 256 {
303 return FormatError("bad tRNS length")
304 }
305 n, err := io.ReadFull(d.r, d.tmp[:length])
306 if err != nil {
307 return err
308 }
309 d.crc.Write(d.tmp[:n])
310
311 if len(d.palette) < n {
312 d.palette = d.palette[:n]
313 }
314 for i := 0; i < n; i++ {
315 rgba := d.palette[i].(color.RGBA)
316 d.palette[i] = color.NRGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]}
317 }
318
319 default:
320 return FormatError("tRNS, color type mismatch")
321 }
322 return d.verifyChecksum()
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 + (bitsPerPixel*width+7)/8
502
503 cr := make([]uint8, rowSize)
504 pr := make([]uint8, rowSize)
505
506 for y := 0; y < height; y++ {
507
508 _, err := io.ReadFull(r, cr)
509 if err != nil {
510 if err == io.EOF || err == io.ErrUnexpectedEOF {
511 return nil, FormatError("not enough pixel data")
512 }
513 return nil, err
514 }
515
516
517 cdat := cr[1:]
518 pdat := pr[1:]
519 switch cr[0] {
520 case ftNone:
521
522 case ftSub:
523 for i := bytesPerPixel; i < len(cdat); i++ {
524 cdat[i] += cdat[i-bytesPerPixel]
525 }
526 case ftUp:
527 for i, p := range pdat {
528 cdat[i] += p
529 }
530 case ftAverage:
531
532
533
534 for i := 0; i < bytesPerPixel; i++ {
535 cdat[i] += pdat[i] / 2
536 }
537 for i := bytesPerPixel; i < len(cdat); i++ {
538 cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2)
539 }
540 case ftPaeth:
541 filterPaeth(cdat, pdat, bytesPerPixel)
542 default:
543 return nil, FormatError("bad filter type")
544 }
545
546
547 switch d.cb {
548 case cbG1:
549 if d.useTransparent {
550 ty := d.transparent[1]
551 for x := 0; x < width; x += 8 {
552 b := cdat[x/8]
553 for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
554 ycol := (b >> 7) * 0xff
555 acol := uint8(0xff)
556 if ycol == ty {
557 acol = 0x00
558 }
559 nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
560 b <<= 1
561 }
562 }
563 } else {
564 for x := 0; x < width; x += 8 {
565 b := cdat[x/8]
566 for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
567 gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff})
568 b <<= 1
569 }
570 }
571 }
572 case cbG2:
573 if d.useTransparent {
574 ty := d.transparent[1]
575 for x := 0; x < width; x += 4 {
576 b := cdat[x/4]
577 for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
578 ycol := (b >> 6) * 0x55
579 acol := uint8(0xff)
580 if ycol == ty {
581 acol = 0x00
582 }
583 nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
584 b <<= 2
585 }
586 }
587 } else {
588 for x := 0; x < width; x += 4 {
589 b := cdat[x/4]
590 for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
591 gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55})
592 b <<= 2
593 }
594 }
595 }
596 case cbG4:
597 if d.useTransparent {
598 ty := d.transparent[1]
599 for x := 0; x < width; x += 2 {
600 b := cdat[x/2]
601 for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
602 ycol := (b >> 4) * 0x11
603 acol := uint8(0xff)
604 if ycol == ty {
605 acol = 0x00
606 }
607 nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
608 b <<= 4
609 }
610 }
611 } else {
612 for x := 0; x < width; x += 2 {
613 b := cdat[x/2]
614 for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
615 gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11})
616 b <<= 4
617 }
618 }
619 }
620 case cbG8:
621 if d.useTransparent {
622 ty := d.transparent[1]
623 for x := 0; x < width; x++ {
624 ycol := cdat[x]
625 acol := uint8(0xff)
626 if ycol == ty {
627 acol = 0x00
628 }
629 nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, acol})
630 }
631 } else {
632 copy(gray.Pix[pixOffset:], cdat)
633 pixOffset += gray.Stride
634 }
635 case cbGA8:
636 for x := 0; x < width; x++ {
637 ycol := cdat[2*x+0]
638 nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]})
639 }
640 case cbTC8:
641 if d.useTransparent {
642 pix, i, j := nrgba.Pix, pixOffset, 0
643 tr, tg, tb := d.transparent[1], d.transparent[3], d.transparent[5]
644 for x := 0; x < width; x++ {
645 r := cdat[j+0]
646 g := cdat[j+1]
647 b := cdat[j+2]
648 a := uint8(0xff)
649 if r == tr && g == tg && b == tb {
650 a = 0x00
651 }
652 pix[i+0] = r
653 pix[i+1] = g
654 pix[i+2] = b
655 pix[i+3] = a
656 i += 4
657 j += 3
658 }
659 pixOffset += nrgba.Stride
660 } else {
661 pix, i, j := rgba.Pix, pixOffset, 0
662 for x := 0; x < width; x++ {
663 pix[i+0] = cdat[j+0]
664 pix[i+1] = cdat[j+1]
665 pix[i+2] = cdat[j+2]
666 pix[i+3] = 0xff
667 i += 4
668 j += 3
669 }
670 pixOffset += rgba.Stride
671 }
672 case cbP1:
673 for x := 0; x < width; x += 8 {
674 b := cdat[x/8]
675 for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
676 idx := b >> 7
677 if len(paletted.Palette) <= int(idx) {
678 paletted.Palette = paletted.Palette[:int(idx)+1]
679 }
680 paletted.SetColorIndex(x+x2, y, idx)
681 b <<= 1
682 }
683 }
684 case cbP2:
685 for x := 0; x < width; x += 4 {
686 b := cdat[x/4]
687 for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
688 idx := b >> 6
689 if len(paletted.Palette) <= int(idx) {
690 paletted.Palette = paletted.Palette[:int(idx)+1]
691 }
692 paletted.SetColorIndex(x+x2, y, idx)
693 b <<= 2
694 }
695 }
696 case cbP4:
697 for x := 0; x < width; x += 2 {
698 b := cdat[x/2]
699 for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
700 idx := b >> 4
701 if len(paletted.Palette) <= int(idx) {
702 paletted.Palette = paletted.Palette[:int(idx)+1]
703 }
704 paletted.SetColorIndex(x+x2, y, idx)
705 b <<= 4
706 }
707 }
708 case cbP8:
709 if len(paletted.Palette) != 256 {
710 for x := 0; x < width; x++ {
711 if len(paletted.Palette) <= int(cdat[x]) {
712 paletted.Palette = paletted.Palette[:int(cdat[x])+1]
713 }
714 }
715 }
716 copy(paletted.Pix[pixOffset:], cdat)
717 pixOffset += paletted.Stride
718 case cbTCA8:
719 copy(nrgba.Pix[pixOffset:], cdat)
720 pixOffset += nrgba.Stride
721 case cbG16:
722 if d.useTransparent {
723 ty := uint16(d.transparent[0])<<8 | uint16(d.transparent[1])
724 for x := 0; x < width; x++ {
725 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
726 acol := uint16(0xffff)
727 if ycol == ty {
728 acol = 0x0000
729 }
730 nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
731 }
732 } else {
733 for x := 0; x < width; x++ {
734 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
735 gray16.SetGray16(x, y, color.Gray16{ycol})
736 }
737 }
738 case cbGA16:
739 for x := 0; x < width; x++ {
740 ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1])
741 acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3])
742 nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
743 }
744 case cbTC16:
745 if d.useTransparent {
746 tr := uint16(d.transparent[0])<<8 | uint16(d.transparent[1])
747 tg := uint16(d.transparent[2])<<8 | uint16(d.transparent[3])
748 tb := uint16(d.transparent[4])<<8 | uint16(d.transparent[5])
749 for x := 0; x < width; x++ {
750 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
751 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
752 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
753 acol := uint16(0xffff)
754 if rcol == tr && gcol == tg && bcol == tb {
755 acol = 0x0000
756 }
757 nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol})
758 }
759 } else {
760 for x := 0; x < width; x++ {
761 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
762 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
763 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
764 rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff})
765 }
766 }
767 case cbTCA16:
768 for x := 0; x < width; x++ {
769 rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1])
770 gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3])
771 bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5])
772 acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7])
773 nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol})
774 }
775 }
776
777
778 pr, cr = cr, pr
779 }
780
781 return img, nil
782 }
783
784
785 func (d *decoder) mergePassInto(dst image.Image, src image.Image, pass int) {
786 p := interlacing[pass]
787 var (
788 srcPix []uint8
789 dstPix []uint8
790 stride int
791 rect image.Rectangle
792 bytesPerPixel int
793 )
794 switch target := dst.(type) {
795 case *image.Alpha:
796 srcPix = src.(*image.Alpha).Pix
797 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
798 bytesPerPixel = 1
799 case *image.Alpha16:
800 srcPix = src.(*image.Alpha16).Pix
801 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
802 bytesPerPixel = 2
803 case *image.Gray:
804 srcPix = src.(*image.Gray).Pix
805 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
806 bytesPerPixel = 1
807 case *image.Gray16:
808 srcPix = src.(*image.Gray16).Pix
809 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
810 bytesPerPixel = 2
811 case *image.NRGBA:
812 srcPix = src.(*image.NRGBA).Pix
813 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
814 bytesPerPixel = 4
815 case *image.NRGBA64:
816 srcPix = src.(*image.NRGBA64).Pix
817 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
818 bytesPerPixel = 8
819 case *image.Paletted:
820 srcPix = src.(*image.Paletted).Pix
821 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
822 bytesPerPixel = 1
823 case *image.RGBA:
824 srcPix = src.(*image.RGBA).Pix
825 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
826 bytesPerPixel = 4
827 case *image.RGBA64:
828 srcPix = src.(*image.RGBA64).Pix
829 dstPix, stride, rect = target.Pix, target.Stride, target.Rect
830 bytesPerPixel = 8
831 }
832 s, bounds := 0, src.Bounds()
833 for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
834 dBase := (y*p.yFactor+p.yOffset-rect.Min.Y)*stride + (p.xOffset-rect.Min.X)*bytesPerPixel
835 for x := bounds.Min.X; x < bounds.Max.X; x++ {
836 d := dBase + x*p.xFactor*bytesPerPixel
837 copy(dstPix[d:], srcPix[s:s+bytesPerPixel])
838 s += bytesPerPixel
839 }
840 }
841 }
842
843 func (d *decoder) parseIDAT(length uint32) (err error) {
844 d.idatLength = length
845 d.img, err = d.decode()
846 if err != nil {
847 return err
848 }
849 return d.verifyChecksum()
850 }
851
852 func (d *decoder) parseIEND(length uint32) error {
853 if length != 0 {
854 return FormatError("bad IEND length")
855 }
856 return d.verifyChecksum()
857 }
858
859 func (d *decoder) parseChunk() error {
860
861 n, err := io.ReadFull(d.r, d.tmp[:8])
862 if err != nil {
863 return err
864 }
865 length := binary.BigEndian.Uint32(d.tmp[:4])
866 d.crc.Reset()
867 d.crc.Write(d.tmp[4:8])
868
869
870 switch string(d.tmp[4:8]) {
871 case "IHDR":
872 if d.stage != dsStart {
873 return chunkOrderError
874 }
875 d.stage = dsSeenIHDR
876 return d.parseIHDR(length)
877 case "PLTE":
878 if d.stage != dsSeenIHDR {
879 return chunkOrderError
880 }
881 d.stage = dsSeenPLTE
882 return d.parsePLTE(length)
883 case "tRNS":
884 if cbPaletted(d.cb) {
885 if d.stage != dsSeenPLTE {
886 return chunkOrderError
887 }
888 } else if d.stage != dsSeenIHDR {
889 return chunkOrderError
890 }
891 d.stage = dsSeentRNS
892 return d.parsetRNS(length)
893 case "IDAT":
894 if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.stage == dsSeenIHDR && cbPaletted(d.cb)) {
895 return chunkOrderError
896 } else if d.stage == dsSeenIDAT {
897
898
899
900
901
902 break
903 }
904 d.stage = dsSeenIDAT
905 return d.parseIDAT(length)
906 case "IEND":
907 if d.stage != dsSeenIDAT {
908 return chunkOrderError
909 }
910 d.stage = dsSeenIEND
911 return d.parseIEND(length)
912 }
913 if length > 0x7fffffff {
914 return FormatError(fmt.Sprintf("Bad chunk length: %d", length))
915 }
916
917 var ignored [4096]byte
918 for length > 0 {
919 n, err = io.ReadFull(d.r, ignored[:min(len(ignored), int(length))])
920 if err != nil {
921 return err
922 }
923 d.crc.Write(ignored[:n])
924 length -= uint32(n)
925 }
926 return d.verifyChecksum()
927 }
928
929 func (d *decoder) verifyChecksum() error {
930 if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil {
931 return err
932 }
933 if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() {
934 return FormatError("invalid checksum")
935 }
936 return nil
937 }
938
939 func (d *decoder) checkHeader() error {
940 _, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)])
941 if err != nil {
942 return err
943 }
944 if string(d.tmp[:len(pngHeader)]) != pngHeader {
945 return FormatError("not a PNG file")
946 }
947 return nil
948 }
949
950
951
952 func Decode(r io.Reader) (image.Image, error) {
953 d := &decoder{
954 r: r,
955 crc: crc32.NewIEEE(),
956 }
957 if err := d.checkHeader(); err != nil {
958 if err == io.EOF {
959 err = io.ErrUnexpectedEOF
960 }
961 return nil, err
962 }
963 for d.stage != dsSeenIEND {
964 if err := d.parseChunk(); err != nil {
965 if err == io.EOF {
966 err = io.ErrUnexpectedEOF
967 }
968 return nil, err
969 }
970 }
971 return d.img, nil
972 }
973
974
975
976 func DecodeConfig(r io.Reader) (image.Config, error) {
977 d := &decoder{
978 r: r,
979 crc: crc32.NewIEEE(),
980 }
981 if err := d.checkHeader(); err != nil {
982 if err == io.EOF {
983 err = io.ErrUnexpectedEOF
984 }
985 return image.Config{}, err
986 }
987 for {
988 if err := d.parseChunk(); err != nil {
989 if err == io.EOF {
990 err = io.ErrUnexpectedEOF
991 }
992 return image.Config{}, err
993 }
994 paletted := cbPaletted(d.cb)
995 if d.stage == dsSeenIHDR && !paletted {
996 break
997 }
998 if d.stage == dsSeenPLTE && paletted {
999 break
1000 }
1001 }
1002 var cm color.Model
1003 switch d.cb {
1004 case cbG1, cbG2, cbG4, cbG8:
1005 cm = color.GrayModel
1006 case cbGA8:
1007 cm = color.NRGBAModel
1008 case cbTC8:
1009 cm = color.RGBAModel
1010 case cbP1, cbP2, cbP4, cbP8:
1011 cm = d.palette
1012 case cbTCA8:
1013 cm = color.NRGBAModel
1014 case cbG16:
1015 cm = color.Gray16Model
1016 case cbGA16:
1017 cm = color.NRGBA64Model
1018 case cbTC16:
1019 cm = color.RGBA64Model
1020 case cbTCA16:
1021 cm = color.NRGBA64Model
1022 }
1023 return image.Config{
1024 ColorModel: cm,
1025 Width: d.width,
1026 Height: d.height,
1027 }, nil
1028 }
1029
1030 func init() {
1031 image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)
1032 }
1033
View as plain text