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:
parent
d165204442
commit
26936f5590
|
@ -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,25 +200,37 @@ 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 := d.byteOrder.Uint16(d.buf[d.off : d.off+2])
|
||||||
v := uint8(d.readBits(bpp) * 0xff / max)
|
d.off += 2
|
||||||
if d.mode == mGrayInvert {
|
if d.mode == mGrayInvert {
|
||||||
v = 0xff - v
|
v = 0xffff - v
|
||||||
|
}
|
||||||
|
img.SetGray16(x, y, color.Gray16{v})
|
||||||
}
|
}
|
||||||
img.SetGray(x, y, color.Gray{v})
|
|
||||||
}
|
}
|
||||||
d.flushBits()
|
} 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 {
|
||||||
|
v = 0xff - v
|
||||||
|
}
|
||||||
|
img.SetGray(x, y, color.Gray{v})
|
||||||
|
}
|
||||||
|
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
|
||||||
d.config.ColorModel = color.GrayModel
|
if d.bpp == 16 {
|
||||||
|
d.config.ColorModel = color.Gray16Model
|
||||||
|
} else {
|
||||||
|
d.config.ColorModel = color.GrayModel
|
||||||
|
}
|
||||||
case pBlackIsZero:
|
case pBlackIsZero:
|
||||||
d.mode = mGray
|
d.mode = mGray
|
||||||
d.config.ColorModel = color.GrayModel
|
if d.bpp == 16 {
|
||||||
|
d.config.ColorModel = color.Gray16Model
|
||||||
|
} else {
|
||||||
|
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++ {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user