go.image/tiff: Support reading 16-bit gray images.

Fixes golang/go#5866.

R=nigeltao
CC=golang-dev
https://golang.org/cl/11920043
This commit is contained in:
Benny Siegert 2013-07-30 15:02:33 +10:00 committed by Nigel Tao
parent d165204442
commit 26936f5590

View File

@ -44,6 +44,7 @@ type decoder struct {
byteOrder binary.ByteOrder byteOrder binary.ByteOrder
config image.Config config image.Config
mode imageMode mode imageMode
bpp uint
features map[int][]uint features map[int][]uint
palette []color.Color palette []color.Color
@ -185,7 +186,7 @@ func (d *decoder) decode(dst image.Image, ymin, ymax int) error {
// Apply horizontal predictor if necessary. // Apply horizontal predictor if necessary.
// In this case, p contains the color difference to the preceding pixel. // In this case, p contains the color difference to the preceding pixel.
// See page 64-65 of the spec. // See page 64-65 of the spec.
if d.firstVal(tPredictor) == prHorizontal && d.firstVal(tBitsPerSample) == 8 { if d.firstVal(tPredictor) == prHorizontal && d.bpp == 8 {
var off int var off int
spp := len(d.features[tBitsPerSample]) // samples per pixel spp := len(d.features[tBitsPerSample]) // samples per pixel
for y := ymin; y < ymax; y++ { for y := ymin; y < ymax; y++ {
@ -199,12 +200,24 @@ func (d *decoder) decode(dst image.Image, ymin, ymax int) error {
switch d.mode { switch d.mode {
case mGray, mGrayInvert: case mGray, mGrayInvert:
img := dst.(*image.Gray) if d.bpp == 16 {
bpp := d.firstVal(tBitsPerSample) img := dst.(*image.Gray16)
max := uint32((1 << bpp) - 1)
for y := ymin; y < ymax; y++ { for y := ymin; y < ymax; y++ {
for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ { for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ {
v := uint8(d.readBits(bpp) * 0xff / max) v := d.byteOrder.Uint16(d.buf[d.off : d.off+2])
d.off += 2
if d.mode == mGrayInvert {
v = 0xffff - v
}
img.SetGray16(x, y, color.Gray16{v})
}
}
} else {
img := dst.(*image.Gray)
max := uint32((1 << d.bpp) - 1)
for y := ymin; y < ymax; y++ {
for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ {
v := uint8(d.readBits(d.bpp) * 0xff / max)
if d.mode == mGrayInvert { if d.mode == mGrayInvert {
v = 0xff - v v = 0xff - v
} }
@ -212,12 +225,12 @@ func (d *decoder) decode(dst image.Image, ymin, ymax int) error {
} }
d.flushBits() d.flushBits()
} }
}
case mPaletted: case mPaletted:
img := dst.(*image.Paletted) img := dst.(*image.Paletted)
bpp := d.firstVal(tBitsPerSample)
for y := ymin; y < ymax; y++ { for y := ymin; y < ymax; y++ {
for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ { for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ {
img.SetColorIndex(x, y, uint8(d.readBits(bpp))) img.SetColorIndex(x, y, uint8(d.readBits(d.bpp)))
} }
d.flushBits() d.flushBits()
} }
@ -299,6 +312,7 @@ func newDecoder(r io.Reader) (*decoder, error) {
if _, ok := d.features[tBitsPerSample]; !ok { if _, ok := d.features[tBitsPerSample]; !ok {
return nil, FormatError("BitsPerSample tag missing") return nil, FormatError("BitsPerSample tag missing")
} }
d.bpp = d.firstVal(tBitsPerSample)
// Determine the image mode. // Determine the image mode.
switch d.firstVal(tPhotometricInterpretation) { switch d.firstVal(tPhotometricInterpretation) {
@ -336,10 +350,18 @@ func newDecoder(r io.Reader) (*decoder, error) {
d.config.ColorModel = color.Palette(d.palette) d.config.ColorModel = color.Palette(d.palette)
case pWhiteIsZero: case pWhiteIsZero:
d.mode = mGrayInvert d.mode = mGrayInvert
if d.bpp == 16 {
d.config.ColorModel = color.Gray16Model
} else {
d.config.ColorModel = color.GrayModel d.config.ColorModel = color.GrayModel
}
case pBlackIsZero: case pBlackIsZero:
d.mode = mGray d.mode = mGray
if d.bpp == 16 {
d.config.ColorModel = color.Gray16Model
} else {
d.config.ColorModel = color.GrayModel d.config.ColorModel = color.GrayModel
}
default: default:
return nil, UnsupportedError("color model") return nil, UnsupportedError("color model")
} }
@ -376,15 +398,20 @@ func Decode(r io.Reader) (img image.Image, err error) {
return nil, FormatError("inconsistent header") return nil, FormatError("inconsistent header")
} }
imgRect := image.Rect(0, 0, d.config.Width, d.config.Height)
switch d.mode { switch d.mode {
case mGray, mGrayInvert: case mGray, mGrayInvert:
img = image.NewGray(image.Rect(0, 0, d.config.Width, d.config.Height)) if d.bpp == 16 {
img = image.NewGray16(imgRect)
} else {
img = image.NewGray(imgRect)
}
case mPaletted: case mPaletted:
img = image.NewPaletted(image.Rect(0, 0, d.config.Width, d.config.Height), d.palette) img = image.NewPaletted(imgRect, d.palette)
case mNRGBA: case mNRGBA:
img = image.NewNRGBA(image.Rect(0, 0, d.config.Width, d.config.Height)) img = image.NewNRGBA(imgRect)
case mRGB, mRGBA: case mRGB, mRGBA:
img = image.NewRGBA(image.Rect(0, 0, d.config.Width, d.config.Height)) img = image.NewRGBA(imgRect)
} }
for i := 0; i < numStrips; i++ { for i := 0; i < numStrips; i++ {