func testEncodeAll(t *testing.T, go1Dot5Fields bool, useGlobalColorModel bool) { const width, height = 150, 103 g0 := &GIF{ Image: make([]*image.Paletted, len(frames)), Delay: make([]int, len(frames)), LoopCount: 5, } for i, f := range frames { g, err := readGIF(f) if err != nil { t.Fatal(f, err) } m := g.Image[0] if m.Bounds().Dx() != width || m.Bounds().Dy() != height { t.Fatalf("frame %d had unexpected bounds: got %v, want width/height = %d/%d", i, m.Bounds(), width, height) } g0.Image[i] = m } // The GIF.Disposal, GIF.Config and GIF.BackgroundIndex fields were added // in Go 1.5. Valid Go 1.4 or earlier code should still produce valid GIFs. // // On the following line, color.Model is an interface type, and // color.Palette is a concrete (slice) type. globalColorModel, backgroundIndex := color.Model(color.Palette(nil)), uint8(0) if useGlobalColorModel { globalColorModel, backgroundIndex = color.Palette(palette.WebSafe), uint8(1) } if go1Dot5Fields { g0.Disposal = make([]byte, len(g0.Image)) for i := range g0.Disposal { g0.Disposal[i] = DisposalNone } g0.Config = image.Config{ ColorModel: globalColorModel, Width: width, Height: height, } g0.BackgroundIndex = backgroundIndex } var buf bytes.Buffer if err := EncodeAll(&buf, g0); err != nil { t.Fatal("EncodeAll:", err) } encoded := buf.Bytes() config, err := DecodeConfig(bytes.NewReader(encoded)) if err != nil { t.Fatal("DecodeConfig:", err) } g1, err := DecodeAll(bytes.NewReader(encoded)) if err != nil { t.Fatal("DecodeAll:", err) } if !reflect.DeepEqual(config, g1.Config) { t.Errorf("DecodeConfig inconsistent with DecodeAll") } if !palettesEqual(g1.Config.ColorModel.(color.Palette), globalColorModel.(color.Palette)) { t.Errorf("unexpected global color model") } if w, h := g1.Config.Width, g1.Config.Height; w != width || h != height { t.Errorf("got config width * height = %d * %d, want %d * %d", w, h, width, height) } if g0.LoopCount != g1.LoopCount { t.Errorf("loop counts differ: %d and %d", g0.LoopCount, g1.LoopCount) } if backgroundIndex != g1.BackgroundIndex { t.Errorf("background indexes differ: %d and %d", backgroundIndex, g1.BackgroundIndex) } if len(g0.Image) != len(g1.Image) { t.Fatalf("image lengths differ: %d and %d", len(g0.Image), len(g1.Image)) } if len(g1.Image) != len(g1.Delay) { t.Fatalf("image and delay lengths differ: %d and %d", len(g1.Image), len(g1.Delay)) } if len(g1.Image) != len(g1.Disposal) { t.Fatalf("image and disposal lengths differ: %d and %d", len(g1.Image), len(g1.Disposal)) } for i := range g0.Image { m0, m1 := g0.Image[i], g1.Image[i] if m0.Bounds() != m1.Bounds() { t.Errorf("frame %d: bounds differ: %v and %v", i, m0.Bounds(), m1.Bounds()) } d0, d1 := g0.Delay[i], g1.Delay[i] if d0 != d1 { t.Errorf("frame %d: delay values differ: %d and %d", i, d0, d1) } p0, p1 := uint8(0), g1.Disposal[i] if go1Dot5Fields { p0 = DisposalNone } if p0 != p1 { t.Errorf("frame %d: disposal values differ: %d and %d", i, p0, p1) } } }
for i, r := range chars { y := uint32(i * value) y |= y << 8 c := TextColor{r, y} pal[i] = &c } return pal } // slice of *TextColor -> color.Palette func NewPalette(p []*TextColor) color.Palette { pal := make([]color.Color, len(p)) for i, r := range p { pal[i] = color.Color(r) } return pal } // default Palette var ( DefaultSet = MakeTextColors([]rune(" .:oO8@")...) AlternateSet = MakeTextColors([]rune(" .:;+=xX$&")...) SciSet = MakeTextColors([]rune(" .,-+=:;/XHM%@#$$")...) UnicodeBoxSet = MakeTextColors([]rune(" ▏▎▍▌▋▊")...) UnicodeShadeSet = MakeTextColors([]rune(" .░▒▓■")...) ) // The color model for ASCII images var TextModel color.Model = color.Model(NewPalette(DefaultSet))