]> Cypherpunks repositories - gostls13.git/commitdiff
image/gif: don't let the per-frame transparent index modify the global
authorNigel Tao <nigeltao@golang.org>
Mon, 22 Sep 2014 04:29:45 +0000 (14:29 +1000)
committerNigel Tao <nigeltao@golang.org>
Mon, 22 Sep 2014 04:29:45 +0000 (14:29 +1000)
palette.

Fixes #7993.

LGTM=r
R=r
CC=golang-codereviews, james.jdunne
https://golang.org/cl/138600043

src/image/gif/reader.go
src/image/gif/reader_test.go

index 926710a4562da27068b16eb429c115586f8b7301..5a863e204f3066b7fc232023ee2ad0450e1a3654 100644 (file)
@@ -171,7 +171,8 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
                        if err != nil {
                                return err
                        }
-                       if d.imageFields&fColorMapFollows != 0 {
+                       useLocalColorMap := d.imageFields&fColorMapFollows != 0
+                       if useLocalColorMap {
                                m.Palette, err = d.readColorMap()
                                if err != nil {
                                        return err
@@ -180,6 +181,10 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
                                m.Palette = d.globalColorMap
                        }
                        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{}
                        }
                        litWidth, err := d.r.ReadByte()
index fc2041e99704209193404656acb41c4eb898f860..7b6f504367cf8e8983c80e69a0c0acf078bfa8c2 100644 (file)
@@ -22,16 +22,16 @@ const (
        trailerStr = "\x3b"
 )
 
-func TestDecode(t *testing.T) {
-       // lzwEncode returns an LZW encoding (with 2-bit literals) of n zeroes.
-       lzwEncode := func(n int) []byte {
-               b := &bytes.Buffer{}
-               w := lzw.NewWriter(b, lzw.LSB, 2)
-               w.Write(make([]byte, n))
-               w.Close()
-               return b.Bytes()
-       }
+// lzwEncode returns an LZW encoding (with 2-bit literals) of n zeroes.
+func lzwEncode(n int) []byte {
+       b := &bytes.Buffer{}
+       w := lzw.NewWriter(b, lzw.LSB, 2)
+       w.Write(make([]byte, n))
+       w.Close()
+       return b.Bytes()
+}
 
+func TestDecode(t *testing.T) {
        testCases := []struct {
                nPix    int  // The number of pixels in the image data.
                extra   bool // Whether to write an extra block after the LZW-encoded data.
@@ -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.
 var testGIF = []byte{
        'G', 'I', 'F', '8', '9', 'a',