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.
7 // The PNG specification is at http://www.libpng.org/pub/png/spec/1.2/PNG-Contents.html
20 // Color type, as per the PNG spec.
29 // A cb is a combination of color type and bit depth.
41 // Filter type, as per the PNG spec.
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
64 const pngHeader
= "\x89PNG\r\n\x1a\n"
66 type imgOrErr
struct {
73 palette image
.PalettedColorModel
76 idatWriter io
.WriteCloser
77 idatDone
chan imgOrErr
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 {
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
) }
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 {
112 func min(a
, b
int) int {
119 func (d
*decoder
) parseIHDR(r io
.Reader
, crc hash
.Hash32
, length
uint32) os
.Error
{
121 return FormatError("bad IHDR length")
123 _
, err
:= io
.ReadFull(r
, d
.tmp
[0:13])
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]))
134 return FormatError("negative dimension")
136 nPixels
:= int64(w
) * int64(h
)
137 if nPixels
!= int64(int(nPixels
)) {
138 return UnsupportedError("dimension overflow")
150 case ctTrueColorAlpha
:
159 case ctTrueColorAlpha
:
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
)
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
])
179 crc
.Write(d
.tmp
[0:n
])
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).
190 return FormatError("PLTE, color type mismatch")
195 func (d
*decoder
) parsetRNS(r io
.Reader
, crc hash
.Hash32
, length
uint32) os
.Error
{
197 return FormatError("bad tRNS length")
199 n
, err
:= io
.ReadFull(r
, d
.tmp
[0:length
])
203 crc
.Write(d
.tmp
[0:n
])
206 return UnsupportedError("grayscale transparency")
208 return UnsupportedError("truecolor transparency")
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")
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
{
237 func (d
*decoder
) idatReader(idat io
.Reader
) (image
.Image
, os
.Error
) {
238 r
, err
:= zlib
.NewReader(idat
)
243 bpp
:= 0 // Bytes per pixel.
244 maxPalette
:= uint8(0)
248 paletted
*image
.Paletted
252 nrgba64
*image
.NRGBA64
258 gray
= image
.NewGray(d
.width
, d
.height
)
262 rgba
= image
.NewRGBA(d
.width
, d
.height
)
266 paletted
= image
.NewPaletted(d
.width
, d
.height
, d
.palette
)
268 maxPalette
= uint8(len(d
.palette
) - 1)
271 nrgba
= image
.NewNRGBA(d
.width
, d
.height
)
275 gray16
= image
.NewGray16(d
.width
, d
.height
)
279 rgba64
= image
.NewRGBA64(d
.width
, d
.height
)
283 nrgba64
= image
.NewNRGBA64(d
.width
, d
.height
)
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
)
305 for i
:= bpp
; i
< len(cdat
); i
++ {
306 cdat
[i
] += cdat
[i
-bpp
]
309 for i
:= 0; i
< len(cdat
); i
++ {
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)
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
])
327 return nil, FormatError("bad filter type")
330 // Convert from bytes to colors.
333 for x
:= 0; x
< d
.width
; x
++ {
334 gray
.Set(x
, y
, image
.GrayColor
{cdat
[x
]})
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})
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
])
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]})
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
})
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})
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.
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 {
388 d
.idatDone
= make(chan imgOrErr
)
390 img
, err
:= d
.idatReader(pr
)
392 err
= FormatError("too little IDAT")
394 pr
.CloseWithError(FormatError("too much IDAT"))
395 d
.idatDone
<- imgOrErr
{img
, err
}
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
])
417 func (d
*decoder
) parseIEND(r io
.Reader
, crc hash
.Hash32
, length
uint32) os
.Error
{
419 return FormatError("bad IEND length")
424 func (d
*decoder
) parseChunk(r io
.Reader
) os
.Error
{
426 n
, err
:= io
.ReadFull(r
, d
.tmp
[0:4])
428 return io
.ErrUnexpectedEOF
433 length
:= parseUint32(d
.tmp
[0:4])
435 // Read the chunk type.
436 n
, err
= io
.ReadFull(r
, d
.tmp
[0:4])
438 return io
.ErrUnexpectedEOF
443 crc
:= crc32
.NewIEEE()
444 crc
.Write(d
.tmp
[0:4])
446 // Read the chunk data.
447 switch string(d
.tmp
[0:4]) {
449 if d
.stage
!= dsStart
{
450 return chunkOrderError
453 err
= d
.parseIHDR(r
, crc
, length
)
455 if d
.stage
!= dsSeenIHDR
{
456 return chunkOrderError
459 err
= d
.parsePLTE(r
, crc
, length
)
461 if d
.stage
!= dsSeenPLTE
{
462 return chunkOrderError
464 err
= d
.parsetRNS(r
, crc
, length
)
466 if d
.stage
< dsSeenIHDR || d
.stage
> dsSeenIDAT ||
(d
.cb
== cbP8
&& d
.stage
== dsSeenIHDR
) {
467 return chunkOrderError
470 err
= d
.parseIDAT(r
, crc
, length
)
472 if d
.stage
!= dsSeenIDAT
{
473 return chunkOrderError
476 err
= d
.parseIEND(r
, crc
, length
)
478 // Ignore this chunk (of a known length).
479 var ignored
[4096]byte
481 n
, err
= io
.ReadFull(r
, ignored
[0:min(len(ignored
), int(length
))])
485 crc
.Write(ignored
[0:n
])
493 // Read the checksum.
494 n
, err
= io
.ReadFull(r
, d
.tmp
[0:4])
496 return io
.ErrUnexpectedEOF
501 if parseUint32(d
.tmp
[0:4]) != crc
.Sum32() {
502 return FormatError("invalid checksum")
507 func (d
*decoder
) checkHeader(r io
.Reader
) os
.Error
{
508 _
, err
:= io
.ReadFull(r
, d
.tmp
[0:8])
512 if string(d
.tmp
[0:8]) != pngHeader
{
513 return FormatError("not a PNG file")
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
) {
522 err
:= d
.checkHeader(r
)
526 for d
.stage
!= dsSeenIEND
{
527 err
= d
.parseChunk(r
)
533 if d
.idatWriter
!= nil {
537 img
, err
= ie
.img
, ie
.err
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
) {
550 err
:= d
.checkHeader(r
)
552 return image
.Config
{}, err
555 err
= d
.parseChunk(r
)
557 return image
.Config
{}, err
559 if d
.stage
== dsSeenIHDR
&& d
.cb
!= cbP8
{
562 if d
.stage
== dsSeenPLTE
&& d
.cb
== cbP8
{
566 var cm image
.ColorModel
569 cm
= image
.GrayColorModel
571 cm
= image
.RGBAColorModel
575 cm
= image
.NRGBAColorModel
577 cm
= image
.Gray16ColorModel
579 cm
= image
.RGBA64ColorModel
581 cm
= image
.NRGBA64ColorModel
583 return image
.Config
{cm
, d
.width
, d
.height
}, nil
587 image
.RegisterFormat("png", pngHeader
, Decode
, DecodeConfig
)