Source file src/pkg/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
51 const (
52 ftNone = 0
53 ftSub = 1
54 ftUp = 2
55 ftAverage = 3
56 ftPaeth = 4
57 nFilter = 5
58 )
59
60
61
62
63
64
65
66 const (
67 dsStart = iota
68 dsSeenIHDR
69 dsSeenPLTE
70 dsSeenIDAT
71 dsSeenIEND
72 )
73
74 const pngHeader = "\x89PNG\r\n\x1a\n"
75
76 type decoder struct {
77 r io.Reader
78 img image.Image
79 crc hash.Hash32
80 width, height int
81 depth int
82 palette color.Palette
83 cb int
84 stage int
85 idatLength uint32
86 tmp [3 * 256]byte
87 }
88
89
90 type FormatError string
91
92 func (e FormatError) Error() string { return "png: invalid format: " + string(e) }
93
94 var chunkOrderError = FormatError("chunk out of order")
95
96
97 type UnsupportedError string
98
99 func (e UnsupportedError) Error() string { return "png: unsupported feature: " + string(e) }
100
101 func min(a, b int) int {
102 if a < b {
103 return a
104 }
105 return b
106 }
107
108 func (d *decoder) parseIHDR(length uint32) error {
109 if length != 13 {
110 return FormatError("bad IHDR length")
111 }
112 if _, err := io.ReadFull(d.r, d.tmp[:13]); err != nil {
113 return err
114 }
115 d.crc.Write(d.tmp[:13])
116 if d.tmp[10] != 0 || d.tmp[11] != 0 || d.tmp[12] != 0 {
117 return UnsupportedError("compression, filter or interlace method")
118 }
119 w := int32(binary.BigEndian.Uint32(d.tmp[0:4]))
120 h := int32(binary.BigEndian.Uint32(d.tmp[4:8]))
121 if w < 0 || h < 0 {
122 return FormatError("negative dimension")
123 }
124 nPixels := int64(w) * int64(h)
125 if nPixels != int64(int(nPixels)) {
126 return UnsupportedError("dimension overflow")
127 }
128 d.cb = cbInvalid
129 d.depth = int(d.tmp[8])
130 switch d.depth {
131 case 1:
132 switch d.tmp[9] {
133 case ctGrayscale:
134 d.cb = cbG1
135 case ctPaletted:
136 d.cb = cbP1
137 }
138 case 2:
139 switch d.tmp[9] {
140 case ctGrayscale:
141 d.cb = cbG2
142 case ctPaletted:
143 d.cb = cbP2
144 }
145 case 4:
146 switch d.tmp[9] {
147 case ctGrayscale:
148 d.cb = cbG4
149 case ctPaletted:
150 d.cb = cbP4
151 }
152 case 8:
153 switch d.tmp[9] {
154 case ctGrayscale:
155 d.cb = cbG8
156 case ctTrueColor:
157 d.cb = cbTC8
158 case ctPaletted:
159 d.cb = cbP8
160 case ctGrayscaleAlpha:
161 d.cb = cbGA8
162 case ctTrueColorAlpha:
163 d.cb = cbTCA8
164 }
165 case 16:
166 switch d.tmp[9] {
167 case ctGrayscale:
168 d.cb = cbG16
169 case ctTrueColor:
170 d.cb = cbTC16
171 case ctGrayscaleAlpha:
172 d.cb = cbGA16
173 case ctTrueColorAlpha:
174 d.cb = cbTCA16
175 }
176 }
177 if d.cb == cbInvalid {
178 return UnsupportedError(fmt.Sprintf("bit depth %d, color type %d", d.tmp[8], d.tmp[9]))
179 }
180 d.width, d.height = int(w), int(h)
181 return d.verifyChecksum()
182 }
183
184 func (d *decoder) parsePLTE(length uint32) error {
185 np := int(length / 3)
186 if length%3 != 0 || np <= 0 || np > 256 || np > 1<<uint(d.depth) {
187 return FormatError("bad PLTE length")
188 }
189 n, err := io.ReadFull(d.r, d.tmp[:3*np])
190 if err != nil {
191 return err
192 }
193 d.crc.Write(d.tmp[:n])
194 switch d.cb {
195 case cbP1, cbP2, cbP4, cbP8:
196 d.palette = make(color.Palette, 256)
197 for i := 0; i < np; i++ {
198 d.palette[i] = color.RGBA{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff}
199 }
200 for i := np; i < 256; i++ {
201
202
203
204
205
206 d.palette[i] = color.RGBA{0x00, 0x00, 0x00, 0xff}
207 }
208 d.palette = d.palette[:np]
209 case cbTC8, cbTCA8, cbTC16, cbTCA16:
210
211
212 default:
213 return FormatError("PLTE, color type mismatch")
214 }
215 return d.verifyChecksum()
216 }
217
218 func (d *decoder) parsetRNS(length uint32) error {
219 if length > 256 {
220 return FormatError("bad tRNS length")
221 }
222 n, err := io.ReadFull(d.r, d.tmp[:length])
223 if err != nil {
224 return err
225 }
226 d.crc.Write(d.tmp[:n])
227 switch d.cb {
228 case cbG8, cbG16:
229 return UnsupportedError("grayscale transparency")
230 case cbTC8, cbTC16:
231 return UnsupportedError("truecolor transparency")
232 case cbP1, cbP2, cbP4, cbP8:
233 if len(d.palette) < n {
234 d.palette = d.palette[:n]
235 }
236 for i := 0; i < n; i++ {
237 rgba := d.palette[i].(color.RGBA)
238 d.palette[i] = color.NRGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]}
239 }
240 case cbGA8, cbGA16, cbTCA8, cbTCA16:
241 return FormatError("tRNS, color type mismatch")
242 }
243 return d.verifyChecksum()
244 }
245
246
247
248
249
250
251
252
253 func (d *decoder) Read(p []byte) (int, error) {
254 if len(p) == 0 {
255 return 0, nil
256 }
257 for d.idatLength == 0 {
258
259 if err := d.verifyChecksum(); err != nil {
260 return 0, err
261 }
262
263
264 if _, err := io.ReadFull(d.r, d.tmp[:8]); err != nil {
265 return 0, err
266 }
267 d.idatLength = binary.BigEndian.Uint32(d.tmp[:4])
268 if string(d.tmp[4:8]) != "IDAT" {
269 return 0, FormatError("not enough pixel data")
270 }
271 d.crc.Reset()
272 d.crc.Write(d.tmp[4:8])
273 }
274 if int(d.idatLength) < 0 {
275 return 0, UnsupportedError("IDAT chunk length overflow")
276 }
277 n, err := d.r.Read(p[:min(len(p), int(d.idatLength))])
278 d.crc.Write(p[:n])
279 d.idatLength -= uint32(n)
280 return n, err
281 }
282
283
284 func (d *decoder) decode() (image.Image, error) {
285 r, err := zlib.NewReader(d)
286 if err != nil {
287 return nil, err
288 }
289 defer r.Close()
290 bitsPerPixel := 0
291 pixOffset := 0
292 var (
293 gray *image.Gray
294 rgba *image.RGBA
295 paletted *image.Paletted
296 nrgba *image.NRGBA
297 gray16 *image.Gray16
298 rgba64 *image.RGBA64
299 nrgba64 *image.NRGBA64
300 img image.Image
301 )
302 switch d.cb {
303 case cbG1, cbG2, cbG4, cbG8:
304 bitsPerPixel = d.depth
305 gray = image.NewGray(image.Rect(0, 0, d.width, d.height))
306 img = gray
307 case cbGA8:
308 bitsPerPixel = 16
309 nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height))
310 img = nrgba
311 case cbTC8:
312 bitsPerPixel = 24
313 rgba = image.NewRGBA(image.Rect(0, 0, d.width, d.height))
314 img = rgba
315 case cbP1, cbP2, cbP4, cbP8:
316 bitsPerPixel = d.depth
317 paletted = image.NewPaletted(image.Rect(0, 0, d.width, d.height), d.palette)
318 img = paletted
319 case cbTCA8:
320 bitsPerPixel = 32
321 nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height))
322 img = nrgba
323 case cbG16:
324 bitsPerPixel = 16
325 gray16 = image.NewGray16(image.Rect(0, 0, d.width, d.height))
326 img = gray16
327 case cbGA16:
328 bitsPerPixel = 32
329 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height))
330 img = nrgba64
331 case cbTC16:
332 bitsPerPixel = 48
333 rgba64 = image.NewRGBA64(image.Rect(0, 0, d.width, d.height))
334 img = rgba64
335 case cbTCA16:
336 bitsPerPixel = 64
337 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height))
338 img = nrgba64
339 }
340 bytesPerPixel := (bitsPerPixel + 7) / 8
341
342
343
344 cr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8)
345 pr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8)
346
347 for y := 0; y < d.height; y++ {
348
349 _, err := io.ReadFull(r, cr)
350 if err != nil {
351 return nil, err
352 }
353
354
355 cdat := cr[1:]
356 pdat := pr[1:]
357 switch cr[0] {
358 case ftNone:
359
360 case ftSub:
361 for i := bytesPerPixel; i < len(cdat); i++ {
362 cdat[i] += cdat[i-bytesPerPixel]
363 }
364 case ftUp:
365 for i, p := range pdat {
366 cdat[i] += p
367 }
368 case ftAverage:
369 for i := 0; i < bytesPerPixel; i++ {
370 cdat[i] += pdat[i] / 2
371 }
372 for i := bytesPerPixel; i < len(cdat); i++ {
373 cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2)
374 }
375 case ftPaeth:
376 filterPaeth(cdat, pdat, bytesPerPixel)
377 default:
378 return nil, FormatError("bad filter type")
379 }
380
381
382 switch d.cb {
383 case cbG1:
384 for x := 0; x < d.width; x += 8 {
385 b := cdat[x/8]
386 for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
387 gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff})
388 b <<= 1
389 }
390 }
391 case cbG2:
392 for x := 0; x < d.width; x += 4 {
393 b := cdat[x/4]
394 for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
395 gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55})
396 b <<= 2
397 }
398 }
399 case cbG4:
400 for x := 0; x < d.width; x += 2 {
401 b := cdat[x/2]
402 for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
403 gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11})
404 b <<= 4
405 }
406 }
407 case cbG8:
408 copy(gray.Pix[pixOffset:], cdat)
409 pixOffset += gray.Stride
410 case cbGA8:
411 for x := 0; x < d.width; x++ {
412 ycol := cdat[2*x+0]
413 nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]})
414 }
415 case cbTC8:
416 pix, i, j := rgba.Pix, pixOffset, 0
417 for x := 0; x < d.width; x++ {
418 pix[i+0] = cdat[j+0]
419 pix[i+1] = cdat[j+1]
420 pix[i+2] = cdat[j+2]
421 pix[i+3] = 0xff
422 i += 4
423 j += 3
424 }
425 pixOffset += rgba.Stride
426 case cbP1:
427 for x := 0; x < d.width; x += 8 {
428 b := cdat[x/8]
429 for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
430 idx := b >> 7
431 if len(paletted.Palette) <= int(idx) {
432 paletted.Palette = paletted.Palette[:int(idx)+1]
433 }
434 paletted.SetColorIndex(x+x2, y, idx)
435 b <<= 1
436 }
437 }
438 case cbP2:
439 for x := 0; x < d.width; x += 4 {
440 b := cdat[x/4]
441 for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
442 idx := b >> 6
443 if len(paletted.Palette) <= int(idx) {
444 paletted.Palette = paletted.Palette[:int(idx)+1]
445 }
446 paletted.SetColorIndex(x+x2, y, idx)
447 b <<= 2
448 }
449 }
450 case cbP4:
451 for x := 0; x < d.width; x += 2 {
452 b := cdat[x/2]
453 for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
454 idx := b >> 4
455 if len(paletted.Palette) <= int(idx) {
456 paletted.Palette = paletted.Palette[:int(idx)+1]
457 }
458 paletted.SetColorIndex(x+x2, y, idx)
459 b <<= 4
460 }
461 }
462 case cbP8:
463 if len(paletted.Palette) != 255 {
464 for x := 0; x < d.width; x++ {
465 if len(paletted.Palette) <= int(cdat[x]) {
466 paletted.Palette = paletted.Palette[:int(cdat[x])+1]
467 }
468 }
469 }
470 copy(paletted.Pix[pixOffset:], cdat)
471 pixOffset += paletted.Stride
472 case cbTCA8:
473 copy(nrgba.Pix[pixOffset:], cdat)
474 pixOffset += nrgba.Stride
475 case cbG16:
476 for x := 0; x < d.width; x++ {
477 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
478 gray16.SetGray16(x, y, color.Gray16{ycol})
479 }
480 case cbGA16:
481 for x := 0; x < d.width; x++ {
482 ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1])
483 acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3])
484 nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
485 }
486 case cbTC16:
487 for x := 0; x < d.width; x++ {
488 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
489 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
490 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
491 rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff})
492 }
493 case cbTCA16:
494 for x := 0; x < d.width; x++ {
495 rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1])
496 gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3])
497 bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5])
498 acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7])
499 nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol})
500 }
501 }
502
503
504 pr, cr = cr, pr
505 }
506
507
508 n, err := r.Read(pr[:1])
509 if err != io.EOF {
510 return nil, FormatError(err.Error())
511 }
512 if n != 0 || d.idatLength != 0 {
513 return nil, FormatError("too much pixel data")
514 }
515
516 return img, nil
517 }
518
519 func (d *decoder) parseIDAT(length uint32) (err error) {
520 d.idatLength = length
521 d.img, err = d.decode()
522 if err != nil {
523 return err
524 }
525 return d.verifyChecksum()
526 }
527
528 func (d *decoder) parseIEND(length uint32) error {
529 if length != 0 {
530 return FormatError("bad IEND length")
531 }
532 return d.verifyChecksum()
533 }
534
535 func (d *decoder) parseChunk() error {
536
537 n, err := io.ReadFull(d.r, d.tmp[:8])
538 if err != nil {
539 return err
540 }
541 length := binary.BigEndian.Uint32(d.tmp[:4])
542 d.crc.Reset()
543 d.crc.Write(d.tmp[4:8])
544
545
546 switch string(d.tmp[4:8]) {
547 case "IHDR":
548 if d.stage != dsStart {
549 return chunkOrderError
550 }
551 d.stage = dsSeenIHDR
552 return d.parseIHDR(length)
553 case "PLTE":
554 if d.stage != dsSeenIHDR {
555 return chunkOrderError
556 }
557 d.stage = dsSeenPLTE
558 return d.parsePLTE(length)
559 case "tRNS":
560 if d.stage != dsSeenPLTE {
561 return chunkOrderError
562 }
563 return d.parsetRNS(length)
564 case "IDAT":
565 if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.cb == cbP8 && d.stage == dsSeenIHDR) {
566 return chunkOrderError
567 }
568 d.stage = dsSeenIDAT
569 return d.parseIDAT(length)
570 case "IEND":
571 if d.stage != dsSeenIDAT {
572 return chunkOrderError
573 }
574 d.stage = dsSeenIEND
575 return d.parseIEND(length)
576 }
577
578 var ignored [4096]byte
579 for length > 0 {
580 n, err = io.ReadFull(d.r, ignored[:min(len(ignored), int(length))])
581 if err != nil {
582 return err
583 }
584 d.crc.Write(ignored[:n])
585 length -= uint32(n)
586 }
587 return d.verifyChecksum()
588 }
589
590 func (d *decoder) verifyChecksum() error {
591 if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil {
592 return err
593 }
594 if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() {
595 return FormatError("invalid checksum")
596 }
597 return nil
598 }
599
600 func (d *decoder) checkHeader() error {
601 _, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)])
602 if err != nil {
603 return err
604 }
605 if string(d.tmp[:len(pngHeader)]) != pngHeader {
606 return FormatError("not a PNG file")
607 }
608 return nil
609 }
610
611
612
613 func Decode(r io.Reader) (image.Image, error) {
614 d := &decoder{
615 r: r,
616 crc: crc32.NewIEEE(),
617 }
618 if err := d.checkHeader(); err != nil {
619 if err == io.EOF {
620 err = io.ErrUnexpectedEOF
621 }
622 return nil, err
623 }
624 for d.stage != dsSeenIEND {
625 if err := d.parseChunk(); err != nil {
626 if err == io.EOF {
627 err = io.ErrUnexpectedEOF
628 }
629 return nil, err
630 }
631 }
632 return d.img, nil
633 }
634
635
636
637 func DecodeConfig(r io.Reader) (image.Config, error) {
638 d := &decoder{
639 r: r,
640 crc: crc32.NewIEEE(),
641 }
642 if err := d.checkHeader(); err != nil {
643 if err == io.EOF {
644 err = io.ErrUnexpectedEOF
645 }
646 return image.Config{}, err
647 }
648 for {
649 if err := d.parseChunk(); err != nil {
650 if err == io.EOF {
651 err = io.ErrUnexpectedEOF
652 }
653 return image.Config{}, err
654 }
655 paletted := d.cb == cbP8 || d.cb == cbP4 || d.cb == cbP2 || d.cb == cbP1
656 if d.stage == dsSeenIHDR && !paletted {
657 break
658 }
659 if d.stage == dsSeenPLTE && paletted {
660 break
661 }
662 }
663 var cm color.Model
664 switch d.cb {
665 case cbG1, cbG2, cbG4, cbG8:
666 cm = color.GrayModel
667 case cbGA8:
668 cm = color.NRGBAModel
669 case cbTC8:
670 cm = color.RGBAModel
671 case cbP1, cbP2, cbP4, cbP8:
672 cm = d.palette
673 case cbTCA8:
674 cm = color.NRGBAModel
675 case cbG16:
676 cm = color.Gray16Model
677 case cbGA16:
678 cm = color.NRGBA64Model
679 case cbTC16:
680 cm = color.RGBA64Model
681 case cbTCA16:
682 cm = color.NRGBA64Model
683 }
684 return image.Config{
685 ColorModel: cm,
686 Width: d.width,
687 Height: d.height,
688 }, nil
689 }
690
691 func init() {
692 image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)
693 }
View as plain text