Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / image / png / reader.go
blobe2d679bb425561cb3347ce103e6f6c974ab2bfcb
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // The png package implements a PNG image decoder and encoder.
6 //
7 // The PNG specification is at http://www.libpng.org/pub/png/spec/1.2/PNG-Contents.html
8 package png
10 import (
11 "compress/zlib"
12 "fmt"
13 "hash"
14 "hash/crc32"
15 "image"
16 "io"
17 "os"
20 // Color type, as per the PNG spec.
21 const (
22 ctGrayscale = 0
23 ctTrueColor = 2
24 ctPaletted = 3
25 ctGrayscaleAlpha = 4
26 ctTrueColorAlpha = 6
29 // A cb is a combination of color type and bit depth.
30 const (
31 cbInvalid = iota
32 cbG8
33 cbTC8
34 cbP8
35 cbTCA8
36 cbG16
37 cbTC16
38 cbTCA16
41 // Filter type, as per the PNG spec.
42 const (
43 ftNone = 0
44 ftSub = 1
45 ftUp = 2
46 ftAverage = 3
47 ftPaeth = 4
48 nFilter = 5
51 // Decoding stage.
52 // The PNG specification says that the IHDR, PLTE (if present), IDAT and IEND
53 // chunks must appear in that order. There may be multiple IDAT chunks, and
54 // IDAT chunks must be sequential (i.e. they may not have any other chunks
55 // between them).
56 const (
57 dsStart = iota
58 dsSeenIHDR
59 dsSeenPLTE
60 dsSeenIDAT
61 dsSeenIEND
64 const pngHeader = "\x89PNG\r\n\x1a\n"
66 type imgOrErr struct {
67 img image.Image
68 err os.Error
71 type decoder struct {
72 width, height int
73 palette image.PalettedColorModel
74 cb int
75 stage int
76 idatWriter io.WriteCloser
77 idatDone chan imgOrErr
78 tmp [3 * 256]byte
81 // A FormatError reports that the input is not a valid PNG.
82 type FormatError string
84 func (e FormatError) String() string { return "png: invalid format: " + string(e) }
86 var chunkOrderError = FormatError("chunk out of order")
88 // An IDATDecodingError wraps an inner error (such as a ZLIB decoding error) encountered while processing an IDAT chunk.
89 type IDATDecodingError struct {
90 Err os.Error
93 func (e IDATDecodingError) String() string { return "png: IDAT decoding error: " + e.Err.String() }
95 // An UnsupportedError reports that the input uses a valid but unimplemented PNG feature.
96 type UnsupportedError string
98 func (e UnsupportedError) String() string { return "png: unsupported feature: " + string(e) }
100 // Big-endian.
101 func parseUint32(b []uint8) uint32 {
102 return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
105 func abs(x int) int {
106 if x < 0 {
107 return -x
109 return x
112 func min(a, b int) int {
113 if a < b {
114 return a
116 return b
119 func (d *decoder) parseIHDR(r io.Reader, crc hash.Hash32, length uint32) os.Error {
120 if length != 13 {
121 return FormatError("bad IHDR length")
123 _, err := io.ReadFull(r, d.tmp[0:13])
124 if err != nil {
125 return err
127 crc.Write(d.tmp[0:13])
128 if d.tmp[10] != 0 || d.tmp[11] != 0 || d.tmp[12] != 0 {
129 return UnsupportedError("compression, filter or interlace method")
131 w := int32(parseUint32(d.tmp[0:4]))
132 h := int32(parseUint32(d.tmp[4:8]))
133 if w < 0 || h < 0 {
134 return FormatError("negative dimension")
136 nPixels := int64(w) * int64(h)
137 if nPixels != int64(int(nPixels)) {
138 return UnsupportedError("dimension overflow")
140 d.cb = cbInvalid
141 switch d.tmp[8] {
142 case 8:
143 switch d.tmp[9] {
144 case ctGrayscale:
145 d.cb = cbG8
146 case ctTrueColor:
147 d.cb = cbTC8
148 case ctPaletted:
149 d.cb = cbP8
150 case ctTrueColorAlpha:
151 d.cb = cbTCA8
153 case 16:
154 switch d.tmp[9] {
155 case ctGrayscale:
156 d.cb = cbG16
157 case ctTrueColor:
158 d.cb = cbTC16
159 case ctTrueColorAlpha:
160 d.cb = cbTCA16
163 if d.cb == cbInvalid {
164 return UnsupportedError(fmt.Sprintf("bit depth %d, color type %d", d.tmp[8], d.tmp[9]))
166 d.width, d.height = int(w), int(h)
167 return nil
170 func (d *decoder) parsePLTE(r io.Reader, crc hash.Hash32, length uint32) os.Error {
171 np := int(length / 3) // The number of palette entries.
172 if length%3 != 0 || np <= 0 || np > 256 {
173 return FormatError("bad PLTE length")
175 n, err := io.ReadFull(r, d.tmp[0:3*np])
176 if err != nil {
177 return err
179 crc.Write(d.tmp[0:n])
180 switch d.cb {
181 case cbP8:
182 d.palette = image.PalettedColorModel(make([]image.Color, np))
183 for i := 0; i < np; i++ {
184 d.palette[i] = image.RGBAColor{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff}
186 case cbTC8, cbTCA8, cbTC16, cbTCA16:
187 // As per the PNG spec, a PLTE chunk is optional (and for practical purposes,
188 // ignorable) for the ctTrueColor and ctTrueColorAlpha color types (section 4.1.2).
189 default:
190 return FormatError("PLTE, color type mismatch")
192 return nil
195 func (d *decoder) parsetRNS(r io.Reader, crc hash.Hash32, length uint32) os.Error {
196 if length > 256 {
197 return FormatError("bad tRNS length")
199 n, err := io.ReadFull(r, d.tmp[0:length])
200 if err != nil {
201 return err
203 crc.Write(d.tmp[0:n])
204 switch d.cb {
205 case cbG8, cbG16:
206 return UnsupportedError("grayscale transparency")
207 case cbTC8, cbTC16:
208 return UnsupportedError("truecolor transparency")
209 case cbP8:
210 if n > len(d.palette) {
211 return FormatError("bad tRNS length")
213 for i := 0; i < n; i++ {
214 rgba := d.palette[i].(image.RGBAColor)
215 d.palette[i] = image.RGBAColor{rgba.R, rgba.G, rgba.B, d.tmp[i]}
217 case cbTCA8, cbTCA16:
218 return FormatError("tRNS, color type mismatch")
220 return nil
223 // The Paeth filter function, as per the PNG specification.
224 func paeth(a, b, c uint8) uint8 {
225 p := int(a) + int(b) - int(c)
226 pa := abs(p - int(a))
227 pb := abs(p - int(b))
228 pc := abs(p - int(c))
229 if pa <= pb && pa <= pc {
230 return a
231 } else if pb <= pc {
232 return b
234 return c
237 func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) {
238 r, err := zlib.NewReader(idat)
239 if err != nil {
240 return nil, err
242 defer r.Close()
243 bpp := 0 // Bytes per pixel.
244 maxPalette := uint8(0)
245 var (
246 gray *image.Gray
247 rgba *image.RGBA
248 paletted *image.Paletted
249 nrgba *image.NRGBA
250 gray16 *image.Gray16
251 rgba64 *image.RGBA64
252 nrgba64 *image.NRGBA64
253 img image.Image
255 switch d.cb {
256 case cbG8:
257 bpp = 1
258 gray = image.NewGray(d.width, d.height)
259 img = gray
260 case cbTC8:
261 bpp = 3
262 rgba = image.NewRGBA(d.width, d.height)
263 img = rgba
264 case cbP8:
265 bpp = 1
266 paletted = image.NewPaletted(d.width, d.height, d.palette)
267 img = paletted
268 maxPalette = uint8(len(d.palette) - 1)
269 case cbTCA8:
270 bpp = 4
271 nrgba = image.NewNRGBA(d.width, d.height)
272 img = nrgba
273 case cbG16:
274 bpp = 2
275 gray16 = image.NewGray16(d.width, d.height)
276 img = gray16
277 case cbTC16:
278 bpp = 6
279 rgba64 = image.NewRGBA64(d.width, d.height)
280 img = rgba64
281 case cbTCA16:
282 bpp = 8
283 nrgba64 = image.NewNRGBA64(d.width, d.height)
284 img = nrgba64
286 // cr and pr are the bytes for the current and previous row.
287 // The +1 is for the per-row filter type, which is at cr[0].
288 cr := make([]uint8, 1+bpp*d.width)
289 pr := make([]uint8, 1+bpp*d.width)
291 for y := 0; y < d.height; y++ {
292 // Read the decompressed bytes.
293 _, err := io.ReadFull(r, cr)
294 if err != nil {
295 return nil, err
298 // Apply the filter.
299 cdat := cr[1:]
300 pdat := pr[1:]
301 switch cr[0] {
302 case ftNone:
303 // No-op.
304 case ftSub:
305 for i := bpp; i < len(cdat); i++ {
306 cdat[i] += cdat[i-bpp]
308 case ftUp:
309 for i := 0; i < len(cdat); i++ {
310 cdat[i] += pdat[i]
312 case ftAverage:
313 for i := 0; i < bpp; i++ {
314 cdat[i] += pdat[i] / 2
316 for i := bpp; i < len(cdat); i++ {
317 cdat[i] += uint8((int(cdat[i-bpp]) + int(pdat[i])) / 2)
319 case ftPaeth:
320 for i := 0; i < bpp; i++ {
321 cdat[i] += paeth(0, pdat[i], 0)
323 for i := bpp; i < len(cdat); i++ {
324 cdat[i] += paeth(cdat[i-bpp], pdat[i], pdat[i-bpp])
326 default:
327 return nil, FormatError("bad filter type")
330 // Convert from bytes to colors.
331 switch d.cb {
332 case cbG8:
333 for x := 0; x < d.width; x++ {
334 gray.Set(x, y, image.GrayColor{cdat[x]})
336 case cbTC8:
337 for x := 0; x < d.width; x++ {
338 rgba.Set(x, y, image.RGBAColor{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff})
340 case cbP8:
341 for x := 0; x < d.width; x++ {
342 if cdat[x] > maxPalette {
343 return nil, FormatError("palette index out of range")
345 paletted.SetColorIndex(x, y, cdat[x])
347 case cbTCA8:
348 for x := 0; x < d.width; x++ {
349 nrgba.Set(x, y, image.NRGBAColor{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]})
351 case cbG16:
352 for x := 0; x < d.width; x++ {
353 ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
354 gray16.Set(x, y, image.Gray16Color{ycol})
356 case cbTC16:
357 for x := 0; x < d.width; x++ {
358 rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
359 gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
360 bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
361 rgba64.Set(x, y, image.RGBA64Color{rcol, gcol, bcol, 0xffff})
363 case cbTCA16:
364 for x := 0; x < d.width; x++ {
365 rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1])
366 gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3])
367 bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5])
368 acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7])
369 nrgba64.Set(x, y, image.NRGBA64Color{rcol, gcol, bcol, acol})
373 // The current row for y is the previous row for y+1.
374 pr, cr = cr, pr
376 return img, nil
379 func (d *decoder) parseIDAT(r io.Reader, crc hash.Hash32, length uint32) os.Error {
380 // There may be more than one IDAT chunk, but their contents must be
381 // treated as if it was one continuous stream (to the zlib decoder).
382 // We bring up an io.Pipe and write the IDAT chunks into the pipe as
383 // we see them, and decode the stream in a separate go-routine, which
384 // signals its completion (successful or not) via a channel.
385 if d.idatWriter == nil {
386 pr, pw := io.Pipe()
387 d.idatWriter = pw
388 d.idatDone = make(chan imgOrErr)
389 go func() {
390 img, err := d.idatReader(pr)
391 if err == os.EOF {
392 err = FormatError("too little IDAT")
394 pr.CloseWithError(FormatError("too much IDAT"))
395 d.idatDone <- imgOrErr{img, err}
398 var buf [4096]byte
399 for length > 0 {
400 n, err1 := r.Read(buf[0:min(len(buf), int(length))])
401 // We delay checking err1. It is possible to get n bytes and an error,
402 // but if the n bytes themselves contain a FormatError, for example, we
403 // want to report that error, and not the one that made the Read stop.
404 n, err2 := d.idatWriter.Write(buf[0:n])
405 if err2 != nil {
406 return err2
408 if err1 != nil {
409 return err1
411 crc.Write(buf[0:n])
412 length -= uint32(n)
414 return nil
417 func (d *decoder) parseIEND(r io.Reader, crc hash.Hash32, length uint32) os.Error {
418 if length != 0 {
419 return FormatError("bad IEND length")
421 return nil
424 func (d *decoder) parseChunk(r io.Reader) os.Error {
425 // Read the length.
426 n, err := io.ReadFull(r, d.tmp[0:4])
427 if err == os.EOF {
428 return io.ErrUnexpectedEOF
430 if err != nil {
431 return err
433 length := parseUint32(d.tmp[0:4])
435 // Read the chunk type.
436 n, err = io.ReadFull(r, d.tmp[0:4])
437 if err == os.EOF {
438 return io.ErrUnexpectedEOF
440 if err != nil {
441 return err
443 crc := crc32.NewIEEE()
444 crc.Write(d.tmp[0:4])
446 // Read the chunk data.
447 switch string(d.tmp[0:4]) {
448 case "IHDR":
449 if d.stage != dsStart {
450 return chunkOrderError
452 d.stage = dsSeenIHDR
453 err = d.parseIHDR(r, crc, length)
454 case "PLTE":
455 if d.stage != dsSeenIHDR {
456 return chunkOrderError
458 d.stage = dsSeenPLTE
459 err = d.parsePLTE(r, crc, length)
460 case "tRNS":
461 if d.stage != dsSeenPLTE {
462 return chunkOrderError
464 err = d.parsetRNS(r, crc, length)
465 case "IDAT":
466 if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.cb == cbP8 && d.stage == dsSeenIHDR) {
467 return chunkOrderError
469 d.stage = dsSeenIDAT
470 err = d.parseIDAT(r, crc, length)
471 case "IEND":
472 if d.stage != dsSeenIDAT {
473 return chunkOrderError
475 d.stage = dsSeenIEND
476 err = d.parseIEND(r, crc, length)
477 default:
478 // Ignore this chunk (of a known length).
479 var ignored [4096]byte
480 for length > 0 {
481 n, err = io.ReadFull(r, ignored[0:min(len(ignored), int(length))])
482 if err != nil {
483 return err
485 crc.Write(ignored[0:n])
486 length -= uint32(n)
489 if err != nil {
490 return err
493 // Read the checksum.
494 n, err = io.ReadFull(r, d.tmp[0:4])
495 if err == os.EOF {
496 return io.ErrUnexpectedEOF
498 if err != nil {
499 return err
501 if parseUint32(d.tmp[0:4]) != crc.Sum32() {
502 return FormatError("invalid checksum")
504 return nil
507 func (d *decoder) checkHeader(r io.Reader) os.Error {
508 _, err := io.ReadFull(r, d.tmp[0:8])
509 if err != nil {
510 return err
512 if string(d.tmp[0:8]) != pngHeader {
513 return FormatError("not a PNG file")
515 return nil
518 // Decode reads a PNG image from r and returns it as an image.Image.
519 // The type of Image returned depends on the PNG contents.
520 func Decode(r io.Reader) (image.Image, os.Error) {
521 var d decoder
522 err := d.checkHeader(r)
523 if err != nil {
524 return nil, err
526 for d.stage != dsSeenIEND {
527 err = d.parseChunk(r)
528 if err != nil {
529 break
532 var img image.Image
533 if d.idatWriter != nil {
534 d.idatWriter.Close()
535 ie := <-d.idatDone
536 if err == nil {
537 img, err = ie.img, ie.err
540 if err != nil {
541 return nil, err
543 return img, nil
546 // DecodeConfig returns the color model and dimensions of a PNG image without
547 // decoding the entire image.
548 func DecodeConfig(r io.Reader) (image.Config, os.Error) {
549 var d decoder
550 err := d.checkHeader(r)
551 if err != nil {
552 return image.Config{}, err
554 for {
555 err = d.parseChunk(r)
556 if err != nil {
557 return image.Config{}, err
559 if d.stage == dsSeenIHDR && d.cb != cbP8 {
560 break
562 if d.stage == dsSeenPLTE && d.cb == cbP8 {
563 break
566 var cm image.ColorModel
567 switch d.cb {
568 case cbG8:
569 cm = image.GrayColorModel
570 case cbTC8:
571 cm = image.RGBAColorModel
572 case cbP8:
573 cm = d.palette
574 case cbTCA8:
575 cm = image.NRGBAColorModel
576 case cbG16:
577 cm = image.Gray16ColorModel
578 case cbTC16:
579 cm = image.RGBA64ColorModel
580 case cbTCA16:
581 cm = image.NRGBA64ColorModel
583 return image.Config{cm, d.width, d.height}, nil
586 func init() {
587 image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)