Commit 0be3176a authored by Nigel Tao's avatar Nigel Tao

image/gif: don't let the per-frame transparent index modify the global

palette.

Fixes #7993.

LGTM=r
R=r
CC=golang-codereviews, james.jdunne
https://golang.org/cl/138600043
parent 3b2577ce
...@@ -171,7 +171,8 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error { ...@@ -171,7 +171,8 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
if err != nil { if err != nil {
return err return err
} }
if d.imageFields&fColorMapFollows != 0 { useLocalColorMap := d.imageFields&fColorMapFollows != 0
if useLocalColorMap {
m.Palette, err = d.readColorMap() m.Palette, err = d.readColorMap()
if err != nil { if err != nil {
return err return err
...@@ -180,6 +181,10 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error { ...@@ -180,6 +181,10 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
m.Palette = d.globalColorMap m.Palette = d.globalColorMap
} }
if d.hasTransparentIndex && int(d.transparentIndex) < len(m.Palette) { if d.hasTransparentIndex && int(d.transparentIndex) < len(m.Palette) {
if !useLocalColorMap {
// Clone the global color map.
m.Palette = append(color.Palette(nil), d.globalColorMap...)
}
m.Palette[d.transparentIndex] = color.RGBA{} m.Palette[d.transparentIndex] = color.RGBA{}
} }
litWidth, err := d.r.ReadByte() litWidth, err := d.r.ReadByte()
......
...@@ -22,16 +22,16 @@ const ( ...@@ -22,16 +22,16 @@ const (
trailerStr = "\x3b" trailerStr = "\x3b"
) )
func TestDecode(t *testing.T) { // lzwEncode returns an LZW encoding (with 2-bit literals) of n zeroes.
// lzwEncode returns an LZW encoding (with 2-bit literals) of n zeroes. func lzwEncode(n int) []byte {
lzwEncode := func(n int) []byte {
b := &bytes.Buffer{} b := &bytes.Buffer{}
w := lzw.NewWriter(b, lzw.LSB, 2) w := lzw.NewWriter(b, lzw.LSB, 2)
w.Write(make([]byte, n)) w.Write(make([]byte, n))
w.Close() w.Close()
return b.Bytes() return b.Bytes()
} }
func TestDecode(t *testing.T) {
testCases := []struct { testCases := []struct {
nPix int // The number of pixels in the image data. nPix int // The number of pixels in the image data.
extra bool // Whether to write an extra block after the LZW-encoded data. extra bool // Whether to write an extra block after the LZW-encoded data.
...@@ -90,6 +90,52 @@ func TestDecode(t *testing.T) { ...@@ -90,6 +90,52 @@ func TestDecode(t *testing.T) {
} }
} }
func TestTransparentIndex(t *testing.T) {
b := &bytes.Buffer{}
b.WriteString(headerStr)
b.WriteString(paletteStr)
for transparentIndex := 0; transparentIndex < 3; transparentIndex++ {
if transparentIndex < 2 {
// Write the graphic control for the transparent index.
b.WriteString("\x21\xf9\x00\x01\x00\x00")
b.WriteByte(byte(transparentIndex))
b.WriteByte(0)
}
// Write an image with bounds 2x1, as per TestDecode.
b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
enc := lzwEncode(2)
if len(enc) > 0xff {
t.Fatalf("compressed length %d is too large", len(enc))
}
b.WriteByte(byte(len(enc)))
b.Write(enc)
b.WriteByte(0x00)
}
b.WriteString(trailerStr)
g, err := DecodeAll(b)
if err != nil {
t.Fatalf("DecodeAll: %v", err)
}
c0 := color.RGBA{paletteStr[0], paletteStr[1], paletteStr[2], 0xff}
c1 := color.RGBA{paletteStr[3], paletteStr[4], paletteStr[5], 0xff}
cz := color.RGBA{}
wants := []color.Palette{
{cz, c1},
{c0, cz},
{c0, c1},
}
if len(g.Image) != len(wants) {
t.Fatalf("got %d images, want %d", len(g.Image), len(wants))
}
for i, want := range wants {
got := g.Image[i].Palette
if !reflect.DeepEqual(got, want) {
t.Errorf("palette #%d:\ngot %v\nwant %v", i, got, want)
}
}
}
// testGIF is a simple GIF that we can modify to test different scenarios. // testGIF is a simple GIF that we can modify to test different scenarios.
var testGIF = []byte{ var testGIF = []byte{
'G', 'I', 'F', '8', '9', 'a', 'G', 'I', 'F', '8', '9', 'a',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment