github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/image/gif/writer_test.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gif 6 7 import ( 8 "bytes" 9 "image" 10 "image/color" 11 _ "image/png" 12 "io/ioutil" 13 "math/rand" 14 "os" 15 "testing" 16 ) 17 18 func readImg(filename string) (image.Image, error) { 19 f, err := os.Open(filename) 20 if err != nil { 21 return nil, err 22 } 23 defer f.Close() 24 m, _, err := image.Decode(f) 25 return m, err 26 } 27 28 func readGIF(filename string) (*GIF, error) { 29 f, err := os.Open(filename) 30 if err != nil { 31 return nil, err 32 } 33 defer f.Close() 34 return DecodeAll(f) 35 } 36 37 func delta(u0, u1 uint32) int64 { 38 d := int64(u0) - int64(u1) 39 if d < 0 { 40 return -d 41 } 42 return d 43 } 44 45 // averageDelta returns the average delta in RGB space. The two images must 46 // have the same bounds. 47 func averageDelta(m0, m1 image.Image) int64 { 48 b := m0.Bounds() 49 var sum, n int64 50 for y := b.Min.Y; y < b.Max.Y; y++ { 51 for x := b.Min.X; x < b.Max.X; x++ { 52 c0 := m0.At(x, y) 53 c1 := m1.At(x, y) 54 r0, g0, b0, _ := c0.RGBA() 55 r1, g1, b1, _ := c1.RGBA() 56 sum += delta(r0, r1) 57 sum += delta(g0, g1) 58 sum += delta(b0, b1) 59 n += 3 60 } 61 } 62 return sum / n 63 } 64 65 var testCase = []struct { 66 filename string 67 tolerance int64 68 }{ 69 {"../testdata/video-001.png", 1 << 12}, 70 {"../testdata/video-001.gif", 0}, 71 {"../testdata/video-001.interlaced.gif", 0}, 72 } 73 74 func TestWriter(t *testing.T) { 75 for _, tc := range testCase { 76 m0, err := readImg(tc.filename) 77 if err != nil { 78 t.Error(tc.filename, err) 79 continue 80 } 81 var buf bytes.Buffer 82 err = Encode(&buf, m0, nil) 83 if err != nil { 84 t.Error(tc.filename, err) 85 continue 86 } 87 m1, err := Decode(&buf) 88 if err != nil { 89 t.Error(tc.filename, err) 90 continue 91 } 92 if m0.Bounds() != m1.Bounds() { 93 t.Errorf("%s, bounds differ: %v and %v", tc.filename, m0.Bounds(), m1.Bounds()) 94 continue 95 } 96 // Compare the average delta to the tolerance level. 97 avgDelta := averageDelta(m0, m1) 98 if avgDelta > tc.tolerance { 99 t.Errorf("%s: average delta is too high. expected: %d, got %d", tc.filename, tc.tolerance, avgDelta) 100 continue 101 } 102 } 103 } 104 105 var frames = []string{ 106 "../testdata/video-001.gif", 107 "../testdata/video-005.gray.gif", 108 } 109 110 func TestEncodeAll(t *testing.T) { 111 g0 := &GIF{ 112 Image: make([]*image.Paletted, len(frames)), 113 Delay: make([]int, len(frames)), 114 LoopCount: 5, 115 } 116 for i, f := range frames { 117 m, err := readGIF(f) 118 if err != nil { 119 t.Error(f, err) 120 } 121 g0.Image[i] = m.Image[0] 122 } 123 var buf bytes.Buffer 124 if err := EncodeAll(&buf, g0); err != nil { 125 t.Fatal("EncodeAll:", err) 126 } 127 g1, err := DecodeAll(&buf) 128 if err != nil { 129 t.Fatal("DecodeAll:", err) 130 } 131 if g0.LoopCount != g1.LoopCount { 132 t.Errorf("loop counts differ: %d and %d", g0.LoopCount, g1.LoopCount) 133 } 134 for i := range g0.Image { 135 m0, m1 := g0.Image[i], g1.Image[i] 136 if m0.Bounds() != m1.Bounds() { 137 t.Errorf("%s, bounds differ: %v and %v", frames[i], m0.Bounds(), m1.Bounds()) 138 } 139 d0, d1 := g0.Delay[i], g1.Delay[i] 140 if d0 != d1 { 141 t.Errorf("%s: delay values differ: %d and %d", frames[i], d0, d1) 142 } 143 } 144 145 g1.Delay = make([]int, 1) 146 if err := EncodeAll(ioutil.Discard, g1); err == nil { 147 t.Error("expected error from mismatched delay and image slice lengths") 148 } 149 if err := EncodeAll(ioutil.Discard, &GIF{}); err == nil { 150 t.Error("expected error from providing empty gif") 151 } 152 } 153 154 func BenchmarkEncode(b *testing.B) { 155 b.StopTimer() 156 157 bo := image.Rect(0, 0, 640, 480) 158 rnd := rand.New(rand.NewSource(123)) 159 160 // Restrict to a 256-color paletted image to avoid quantization path. 161 palette := make(color.Palette, 256) 162 for i := range palette { 163 palette[i] = color.RGBA{ 164 uint8(rnd.Intn(256)), 165 uint8(rnd.Intn(256)), 166 uint8(rnd.Intn(256)), 167 255, 168 } 169 } 170 img := image.NewPaletted(image.Rect(0, 0, 640, 480), palette) 171 for y := bo.Min.Y; y < bo.Max.Y; y++ { 172 for x := bo.Min.X; x < bo.Max.X; x++ { 173 img.Set(x, y, palette[rnd.Intn(256)]) 174 } 175 } 176 177 b.SetBytes(640 * 480 * 4) 178 b.StartTimer() 179 for i := 0; i < b.N; i++ { 180 Encode(ioutil.Discard, img, nil) 181 } 182 } 183 184 func BenchmarkQuantizedEncode(b *testing.B) { 185 b.StopTimer() 186 img := image.NewRGBA(image.Rect(0, 0, 640, 480)) 187 bo := img.Bounds() 188 rnd := rand.New(rand.NewSource(123)) 189 for y := bo.Min.Y; y < bo.Max.Y; y++ { 190 for x := bo.Min.X; x < bo.Max.X; x++ { 191 img.SetRGBA(x, y, color.RGBA{ 192 uint8(rnd.Intn(256)), 193 uint8(rnd.Intn(256)), 194 uint8(rnd.Intn(256)), 195 255, 196 }) 197 } 198 } 199 b.SetBytes(640 * 480 * 4) 200 b.StartTimer() 201 for i := 0; i < b.N; i++ { 202 Encode(ioutil.Discard, img, nil) 203 } 204 }