go.image/tiff: encoder fix non LZW Predictor and Paletted SamplesPerPixel and non RGB ExtraSamples.

TIFF6.0 Spec:
Page 31: ExtraSamples can only included in RGB mode image.
Page 39, SamplesPerPixel is usually 1 for bilevel, grayscale, and palette-color images.
Page 64, Currently Predictor field is used only with LZW.

Fixes golang/go#6421.

R=bsiegert, nigeltao, gbulmer
CC=golang-dev
https://golang.org/cl/13779043
This commit is contained in:
ChaiShushan 2013-09-22 11:21:53 +10:00 committed by Nigel Tao
parent b2d744f611
commit 420d421738

View File

@ -291,11 +291,12 @@ type Options struct {
func Encode(w io.Writer, m image.Image, opt *Options) error { func Encode(w io.Writer, m image.Image, opt *Options) error {
d := m.Bounds().Size() d := m.Bounds().Size()
predictor := false
compression := uint32(cNone) compression := uint32(cNone)
predictor := false
if opt != nil { if opt != nil {
predictor = opt.Predictor
compression = opt.Compression.specValue() compression = opt.Compression.specValue()
// The predictor field is only used with LZW. See page 64 of the spec.
predictor = opt.Predictor && compression == cLZW
} }
_, err := io.WriteString(w, leHeader) _, err := io.WriteString(w, leHeader)
@ -343,7 +344,7 @@ func Encode(w io.Writer, m image.Image, opt *Options) error {
photometricInterpretation := uint32(pRGB) photometricInterpretation := uint32(pRGB)
samplesPerPixel := uint32(4) samplesPerPixel := uint32(4)
bitsPerSample := []uint32{8, 8, 8, 8} bitsPerSample := []uint32{8, 8, 8, 8}
extrasamples := uint32(1) // Associated alpha (default). extraSamples := uint32(0)
colorMap := []uint32{} colorMap := []uint32{}
if predictor { if predictor {
@ -352,7 +353,7 @@ func Encode(w io.Writer, m image.Image, opt *Options) error {
switch m := m.(type) { switch m := m.(type) {
case *image.Paletted: case *image.Paletted:
photometricInterpretation = pPaletted photometricInterpretation = pPaletted
samplesPerPixel = 3 samplesPerPixel = 1
bitsPerSample = []uint32{8} bitsPerSample = []uint32{8}
colorMap = make([]uint32, 256*3) colorMap = make([]uint32, 256*3)
for i := 0; i < 256 && i < len(m.Palette); i++ { for i := 0; i < 256 && i < len(m.Palette); i++ {
@ -373,18 +374,21 @@ func Encode(w io.Writer, m image.Image, opt *Options) error {
bitsPerSample = []uint32{16} bitsPerSample = []uint32{16}
err = encodeGray16(dst, m.Pix, d.X, d.Y, m.Stride, predictor) err = encodeGray16(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
case *image.NRGBA: case *image.NRGBA:
extrasamples = 2 // Unassociated alpha. extraSamples = 2 // Unassociated alpha.
err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor) err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
case *image.NRGBA64: case *image.NRGBA64:
extrasamples = 2 // Unassociated alpha. extraSamples = 2 // Unassociated alpha.
bitsPerSample = []uint32{16, 16, 16, 16} bitsPerSample = []uint32{16, 16, 16, 16}
err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor) err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
case *image.RGBA: case *image.RGBA:
extraSamples = 1 // Associated alpha.
err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor) err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
case *image.RGBA64: case *image.RGBA64:
extraSamples = 1 // Associated alpha.
bitsPerSample = []uint32{16, 16, 16, 16} bitsPerSample = []uint32{16, 16, 16, 16}
err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor) err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
default: default:
extraSamples = 1 // Associated alpha.
err = encode(dst, m, predictor) err = encode(dst, m, predictor)
} }
if err != nil { if err != nil {
@ -419,12 +423,16 @@ func Encode(w io.Writer, m image.Image, opt *Options) error {
{tXResolution, dtRational, []uint32{72, 1}}, {tXResolution, dtRational, []uint32{72, 1}},
{tYResolution, dtRational, []uint32{72, 1}}, {tYResolution, dtRational, []uint32{72, 1}},
{tResolutionUnit, dtShort, []uint32{resPerInch}}, {tResolutionUnit, dtShort, []uint32{resPerInch}},
{tPredictor, dtShort, []uint32{pr}}, }
{tExtraSamples, dtShort, []uint32{extrasamples}}, if pr != prNone {
ifd = append(ifd, ifdEntry{tPredictor, dtShort, []uint32{pr}})
} }
if len(colorMap) != 0 { if len(colorMap) != 0 {
ifd = append(ifd, ifdEntry{tColorMap, dtShort, colorMap}) ifd = append(ifd, ifdEntry{tColorMap, dtShort, colorMap})
} }
if extraSamples > 0 {
ifd = append(ifd, ifdEntry{tExtraSamples, dtShort, []uint32{extraSamples}})
}
return writeIFD(w, imageLen+8, ifd) return writeIFD(w, imageLen+8, ifd)
} }