diff options
Diffstat (limited to 'libgo/go/image/png/reader.go')
-rw-r--r-- | libgo/go/image/png/reader.go | 174 |
1 files changed, 147 insertions, 27 deletions
diff --git a/libgo/go/image/png/reader.go b/libgo/go/image/png/reader.go index e2d679bb425..eee4eac2e15 100644 --- a/libgo/go/image/png/reader.go +++ b/libgo/go/image/png/reader.go @@ -29,11 +29,19 @@ const ( // A cb is a combination of color type and bit depth. const ( cbInvalid = iota + cbG1 + cbG2 + cbG4 cbG8 + cbGA8 cbTC8 + cbP1 + cbP2 + cbP4 cbP8 cbTCA8 cbG16 + cbGA16 cbTC16 cbTCA16 ) @@ -70,6 +78,7 @@ type imgOrErr struct { type decoder struct { width, height int + depth int palette image.PalettedColorModel cb int stage int @@ -138,7 +147,29 @@ func (d *decoder) parseIHDR(r io.Reader, crc hash.Hash32, length uint32) os.Erro return UnsupportedError("dimension overflow") } d.cb = cbInvalid - switch d.tmp[8] { + d.depth = int(d.tmp[8]) + switch d.depth { + case 1: + switch d.tmp[9] { + case ctGrayscale: + d.cb = cbG1 + case ctPaletted: + d.cb = cbP1 + } + case 2: + switch d.tmp[9] { + case ctGrayscale: + d.cb = cbG2 + case ctPaletted: + d.cb = cbP2 + } + case 4: + switch d.tmp[9] { + case ctGrayscale: + d.cb = cbG4 + case ctPaletted: + d.cb = cbP4 + } case 8: switch d.tmp[9] { case ctGrayscale: @@ -147,6 +178,8 @@ func (d *decoder) parseIHDR(r io.Reader, crc hash.Hash32, length uint32) os.Erro d.cb = cbTC8 case ctPaletted: d.cb = cbP8 + case ctGrayscaleAlpha: + d.cb = cbGA8 case ctTrueColorAlpha: d.cb = cbTCA8 } @@ -156,6 +189,8 @@ func (d *decoder) parseIHDR(r io.Reader, crc hash.Hash32, length uint32) os.Erro d.cb = cbG16 case ctTrueColor: d.cb = cbTC16 + case ctGrayscaleAlpha: + d.cb = cbGA16 case ctTrueColorAlpha: d.cb = cbTCA16 } @@ -169,7 +204,7 @@ func (d *decoder) parseIHDR(r io.Reader, crc hash.Hash32, length uint32) os.Erro func (d *decoder) parsePLTE(r io.Reader, crc hash.Hash32, length uint32) os.Error { np := int(length / 3) // The number of palette entries. - if length%3 != 0 || np <= 0 || np > 256 { + if length%3 != 0 || np <= 0 || np > 256 || np > 1<<uint(d.depth) { return FormatError("bad PLTE length") } n, err := io.ReadFull(r, d.tmp[0:3*np]) @@ -178,7 +213,7 @@ func (d *decoder) parsePLTE(r io.Reader, crc hash.Hash32, length uint32) os.Erro } crc.Write(d.tmp[0:n]) switch d.cb { - case cbP8: + case cbP1, cbP2, cbP4, cbP8: d.palette = image.PalettedColorModel(make([]image.Color, np)) for i := 0; i < np; i++ { d.palette[i] = image.RGBAColor{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff} @@ -206,7 +241,7 @@ func (d *decoder) parsetRNS(r io.Reader, crc hash.Hash32, length uint32) os.Erro return UnsupportedError("grayscale transparency") case cbTC8, cbTC16: return UnsupportedError("truecolor transparency") - case cbP8: + case cbP1, cbP2, cbP4, cbP8: if n > len(d.palette) { return FormatError("bad tRNS length") } @@ -214,7 +249,7 @@ func (d *decoder) parsetRNS(r io.Reader, crc hash.Hash32, length uint32) os.Erro rgba := d.palette[i].(image.RGBAColor) d.palette[i] = image.RGBAColor{rgba.R, rgba.G, rgba.B, d.tmp[i]} } - case cbTCA8, cbTCA16: + case cbGA8, cbGA16, cbTCA8, cbTCA16: return FormatError("tRNS, color type mismatch") } return nil @@ -240,7 +275,7 @@ func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) { return nil, err } defer r.Close() - bpp := 0 // Bytes per pixel. + bitsPerPixel := 0 maxPalette := uint8(0) var ( gray *image.Gray @@ -253,40 +288,50 @@ func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) { img image.Image ) switch d.cb { - case cbG8: - bpp = 1 + case cbG1, cbG2, cbG4, cbG8: + bitsPerPixel = d.depth gray = image.NewGray(d.width, d.height) img = gray + case cbGA8: + bitsPerPixel = 16 + nrgba = image.NewNRGBA(d.width, d.height) + img = nrgba case cbTC8: - bpp = 3 + bitsPerPixel = 24 rgba = image.NewRGBA(d.width, d.height) img = rgba - case cbP8: - bpp = 1 + case cbP1, cbP2, cbP4, cbP8: + bitsPerPixel = d.depth paletted = image.NewPaletted(d.width, d.height, d.palette) img = paletted maxPalette = uint8(len(d.palette) - 1) case cbTCA8: - bpp = 4 + bitsPerPixel = 32 nrgba = image.NewNRGBA(d.width, d.height) img = nrgba case cbG16: - bpp = 2 + bitsPerPixel = 16 gray16 = image.NewGray16(d.width, d.height) img = gray16 + case cbGA16: + bitsPerPixel = 32 + nrgba64 = image.NewNRGBA64(d.width, d.height) + img = nrgba64 case cbTC16: - bpp = 6 + bitsPerPixel = 48 rgba64 = image.NewRGBA64(d.width, d.height) img = rgba64 case cbTCA16: - bpp = 8 + bitsPerPixel = 64 nrgba64 = image.NewNRGBA64(d.width, d.height) img = nrgba64 } + bytesPerPixel := (bitsPerPixel + 7) / 8 + // cr and pr are the bytes for the current and previous row. // The +1 is for the per-row filter type, which is at cr[0]. - cr := make([]uint8, 1+bpp*d.width) - pr := make([]uint8, 1+bpp*d.width) + cr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8) + pr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8) for y := 0; y < d.height; y++ { // Read the decompressed bytes. @@ -302,26 +347,26 @@ func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) { case ftNone: // No-op. case ftSub: - for i := bpp; i < len(cdat); i++ { - cdat[i] += cdat[i-bpp] + for i := bytesPerPixel; i < len(cdat); i++ { + cdat[i] += cdat[i-bytesPerPixel] } case ftUp: for i := 0; i < len(cdat); i++ { cdat[i] += pdat[i] } case ftAverage: - for i := 0; i < bpp; i++ { + for i := 0; i < bytesPerPixel; i++ { cdat[i] += pdat[i] / 2 } - for i := bpp; i < len(cdat); i++ { - cdat[i] += uint8((int(cdat[i-bpp]) + int(pdat[i])) / 2) + for i := bytesPerPixel; i < len(cdat); i++ { + cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2) } case ftPaeth: - for i := 0; i < bpp; i++ { + for i := 0; i < bytesPerPixel; i++ { cdat[i] += paeth(0, pdat[i], 0) } - for i := bpp; i < len(cdat); i++ { - cdat[i] += paeth(cdat[i-bpp], pdat[i], pdat[i-bpp]) + for i := bytesPerPixel; i < len(cdat); i++ { + cdat[i] += paeth(cdat[i-bytesPerPixel], pdat[i], pdat[i-bytesPerPixel]) } default: return nil, FormatError("bad filter type") @@ -329,14 +374,79 @@ func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) { // Convert from bytes to colors. switch d.cb { + case cbG1: + for x := 0; x < d.width; x += 8 { + b := cdat[x/8] + for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ { + gray.Set(x+x2, y, image.GrayColor{(b >> 7) * 0xff}) + b <<= 1 + } + } + case cbG2: + for x := 0; x < d.width; x += 4 { + b := cdat[x/4] + for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ { + gray.Set(x+x2, y, image.GrayColor{(b >> 6) * 0x55}) + b <<= 2 + } + } + case cbG4: + for x := 0; x < d.width; x += 2 { + b := cdat[x/2] + for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ { + gray.Set(x+x2, y, image.GrayColor{(b >> 4) * 0x11}) + b <<= 4 + } + } case cbG8: for x := 0; x < d.width; x++ { gray.Set(x, y, image.GrayColor{cdat[x]}) } + case cbGA8: + for x := 0; x < d.width; x++ { + ycol := cdat[2*x+0] + nrgba.Set(x, y, image.NRGBAColor{ycol, ycol, ycol, cdat[2*x+1]}) + } case cbTC8: for x := 0; x < d.width; x++ { rgba.Set(x, y, image.RGBAColor{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff}) } + case cbP1: + for x := 0; x < d.width; x += 8 { + b := cdat[x/8] + for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ { + idx := b >> 7 + if idx > maxPalette { + return nil, FormatError("palette index out of range") + } + paletted.SetColorIndex(x+x2, y, idx) + b <<= 1 + } + } + case cbP2: + for x := 0; x < d.width; x += 4 { + b := cdat[x/4] + for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ { + idx := b >> 6 + if idx > maxPalette { + return nil, FormatError("palette index out of range") + } + paletted.SetColorIndex(x+x2, y, idx) + b <<= 2 + } + } + case cbP4: + for x := 0; x < d.width; x += 2 { + b := cdat[x/2] + for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ { + idx := b >> 4 + if idx > maxPalette { + return nil, FormatError("palette index out of range") + } + paletted.SetColorIndex(x+x2, y, idx) + b <<= 4 + } + } case cbP8: for x := 0; x < d.width; x++ { if cdat[x] > maxPalette { @@ -353,6 +463,12 @@ func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) { ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1]) gray16.Set(x, y, image.Gray16Color{ycol}) } + case cbGA16: + for x := 0; x < d.width; x++ { + ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1]) + acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3]) + nrgba64.Set(x, y, image.NRGBA64Color{ycol, ycol, ycol, acol}) + } case cbTC16: for x := 0; x < d.width; x++ { rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1]) @@ -565,16 +681,20 @@ func DecodeConfig(r io.Reader) (image.Config, os.Error) { } var cm image.ColorModel switch d.cb { - case cbG8: + case cbG1, cbG2, cbG4, cbG8: cm = image.GrayColorModel + case cbGA8: + cm = image.NRGBAColorModel case cbTC8: cm = image.RGBAColorModel - case cbP8: + case cbP1, cbP2, cbP4, cbP8: cm = d.palette case cbTCA8: cm = image.NRGBAColorModel case cbG16: cm = image.Gray16ColorModel + case cbGA16: + cm = image.NRGBA64ColorModel case cbTC16: cm = image.RGBA64ColorModel case cbTCA16: |