Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
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) { | |
nigeltao
2013/07/03 03:27:25
readGif should be readGIF.
Andrew Bonventre
2013/07/03 17:19:35
Done.
| |
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 << 10}, | |
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 } | |
80 var buf bytes.Buffer | |
81 err = Encode(&buf, m0, nil) | |
82 if err != nil { | |
83 t.Error(tc.filename, err) | |
84 } | |
85 m1, err := Decode(&buf) | |
86 if err != nil { | |
87 t.Error(tc.filename, err) | |
88 } | |
89 if m0.Bounds() != m1.Bounds() { | |
90 t.Errorf("%s, bounds differ: %v and %v", tc.filename, m0 .Bounds(), m1.Bounds()) | |
91 } | |
92 // Compare the average delta to the tolerance level. | |
93 avgDelta := averageDelta(m0, m1) | |
94 if avgDelta > tc.tolerance { | |
95 t.Errorf("%s: average delta is too high. expected: %d, g ot %d", tc.filename, tc.tolerance, avgDelta) | |
96 continue | |
97 } | |
98 } | |
99 } | |
100 | |
101 var frames = []string{ | |
102 "../testdata/video-001.gif", | |
103 "../testdata/video-005.gray.gif", | |
104 } | |
105 | |
106 func TestEncodeAll(t *testing.T) { | |
107 g0 := &GIF{ | |
108 Image: make([]*image.Paletted, len(frames)), | |
109 Delay: make([]int, len(frames), 5), | |
nigeltao
2013/07/03 03:27:25
Why the ", 5"?
Andrew Bonventre
2013/07/03 17:19:35
Oops. Removed.
| |
110 LoopCount: 5, | |
111 } | |
112 for i, f := range frames { | |
113 m, err := readGif(f) | |
114 if err != nil { | |
115 t.Error(f, err) | |
116 } | |
117 g0.Image[i] = m.Image[0] | |
118 } | |
119 var buf bytes.Buffer | |
120 if err := EncodeAll(&buf, g0); err != nil { | |
121 t.Error("EncodeAll:", err) | |
122 } | |
123 g1, err := DecodeAll(&buf) | |
124 if err != nil { | |
125 t.Error("DecodeAll:", err) | |
126 } | |
127 if g0.LoopCount != g1.LoopCount { | |
128 t.Errorf("loop counts differ: %d and %d", g0.LoopCount, g1.LoopC ount) | |
129 } | |
130 for i := range g0.Image { | |
131 m0, m1 := g0.Image[i], g1.Image[i] | |
132 if m0.Bounds() != m1.Bounds() { | |
133 t.Errorf("%s, bounds differ: %v and %v", frames[i], m0.B ounds(), m1.Bounds()) | |
134 } | |
135 d0, d1 := g0.Delay[i], g1.Delay[i] | |
136 if d0 != d1 { | |
137 t.Errorf("%s: delay values differ: %d and %d", frames[i] , d0, d1) | |
138 } | |
139 } | |
140 | |
141 g1.Delay = make([]int, 1) | |
142 if err := EncodeAll(ioutil.Discard, g1); err == nil { | |
143 t.Error("expected error from mismatched delay and image slice le ngths") | |
144 } | |
145 if err := EncodeAll(ioutil.Discard, &GIF{}); err == nil { | |
146 t.Error("expected error from providing empty gif") | |
147 } | |
148 } | |
149 | |
150 func BenchmarkEncode(b *testing.B) { | |
151 b.StopTimer() | |
152 img := image.NewRGBA(image.Rect(0, 0, 640, 480)) | |
153 bo := img.Bounds() | |
154 rnd := rand.New(rand.NewSource(123)) | |
155 | |
156 // Restrict to a 256-color palette to avoid quantization path. | |
nigeltao
2013/07/03 03:27:25
I'd also like a benchmark for the quantization pat
Andrew Bonventre
2013/07/03 17:19:35
Done.
| |
157 palette := make([]color.RGBA, 256) | |
158 for i := range palette { | |
159 palette[i] = color.RGBA{ | |
160 uint8(rnd.Intn(256)), | |
161 uint8(rnd.Intn(256)), | |
162 uint8(rnd.Intn(256)), | |
163 255, | |
164 } | |
165 } | |
166 for y := bo.Min.Y; y < bo.Max.Y; y++ { | |
167 for x := bo.Min.X; x < bo.Max.X; x++ { | |
168 img.SetRGBA(x, y, palette[rnd.Intn(256)]) | |
169 } | |
170 } | |
171 b.SetBytes(640 * 480 * 4) | |
172 b.StartTimer() | |
173 for i := 0; i < b.N; i++ { | |
174 Encode(ioutil.Discard, img, nil) | |
175 } | |
176 } | |
OLD | NEW |