Source file
src/image/jpeg/dct_test.go
1
2
3
4
5 package jpeg
6
7 import (
8 "fmt"
9 "math"
10 "math/rand"
11 "strings"
12 "testing"
13 )
14
15 func benchmarkDCT(b *testing.B, f func(*block)) {
16 b.StopTimer()
17 blocks := make([]block, 0, b.N*len(testBlocks))
18 for i := 0; i < b.N; i++ {
19 blocks = append(blocks, testBlocks[:]...)
20 }
21 b.StartTimer()
22 for i := range blocks {
23 f(&blocks[i])
24 }
25 }
26
27 func BenchmarkFDCT(b *testing.B) {
28 benchmarkDCT(b, fdct)
29 }
30
31 func BenchmarkIDCT(b *testing.B) {
32 benchmarkDCT(b, idct)
33 }
34
35 func TestDCT(t *testing.T) {
36 blocks := make([]block, len(testBlocks))
37 copy(blocks, testBlocks[:])
38
39
40 r := rand.New(rand.NewSource(123))
41 for i := 0; i < 100; i++ {
42 b := block{}
43 n := r.Int() % 64
44 for j := 0; j < n; j++ {
45 b[r.Int()%len(b)] = r.Int31() % 256
46 }
47 blocks = append(blocks, b)
48 }
49
50
51
52
53 for i, b := range blocks {
54 got, want := b, b
55 for j := range got {
56 got[j] = (got[j] - 128) * 8
57 }
58 slowFDCT(&got)
59 slowIDCT(&got)
60 for j := range got {
61 got[j] = got[j]/8 + 128
62 }
63 if differ(&got, &want) {
64 t.Errorf("i=%d: IDCT(FDCT)\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
65 }
66 }
67
68
69
70 for i, b := range blocks {
71 got, want := b, b
72 fdct(&got)
73 for j := range want {
74 want[j] = (want[j] - 128) * 8
75 }
76 slowFDCT(&want)
77 if differ(&got, &want) {
78 t.Errorf("i=%d: FDCT\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
79 }
80 }
81
82
83 for i, b := range blocks {
84 got, want := b, b
85 idct(&got)
86 slowIDCT(&want)
87 if differ(&got, &want) {
88 t.Errorf("i=%d: IDCT\nsrc\n%s\ngot\n%s\nwant\n%s\n", i, &b, &got, &want)
89 }
90 }
91 }
92
93
94
95
96
97 func differ(b0, b1 *block) bool {
98 for i := range b0 {
99 delta := b0[i] - b1[i]
100 if delta < -2 || +2 < delta {
101 return true
102 }
103 }
104 return false
105 }
106
107
108 func alpha(i int) float64 {
109 if i == 0 {
110 return 1
111 }
112 return math.Sqrt2
113 }
114
115 var cosines = [32]float64{
116 +1.0000000000000000000000000000000000000000000000000000000000000000,
117 +0.9807852804032304491261822361342390369739337308933360950029160885,
118 +0.9238795325112867561281831893967882868224166258636424861150977312,
119 +0.8314696123025452370787883776179057567385608119872499634461245902,
120 +0.7071067811865475244008443621048490392848359376884740365883398689,
121 +0.5555702330196022247428308139485328743749371907548040459241535282,
122 +0.3826834323650897717284599840303988667613445624856270414338006356,
123 +0.1950903220161282678482848684770222409276916177519548077545020894,
124
125 -0.0000000000000000000000000000000000000000000000000000000000000000,
126 -0.1950903220161282678482848684770222409276916177519548077545020894,
127 -0.3826834323650897717284599840303988667613445624856270414338006356,
128 -0.5555702330196022247428308139485328743749371907548040459241535282,
129 -0.7071067811865475244008443621048490392848359376884740365883398689,
130 -0.8314696123025452370787883776179057567385608119872499634461245902,
131 -0.9238795325112867561281831893967882868224166258636424861150977312,
132 -0.9807852804032304491261822361342390369739337308933360950029160885,
133
134 -1.0000000000000000000000000000000000000000000000000000000000000000,
135 -0.9807852804032304491261822361342390369739337308933360950029160885,
136 -0.9238795325112867561281831893967882868224166258636424861150977312,
137 -0.8314696123025452370787883776179057567385608119872499634461245902,
138 -0.7071067811865475244008443621048490392848359376884740365883398689,
139 -0.5555702330196022247428308139485328743749371907548040459241535282,
140 -0.3826834323650897717284599840303988667613445624856270414338006356,
141 -0.1950903220161282678482848684770222409276916177519548077545020894,
142
143 +0.0000000000000000000000000000000000000000000000000000000000000000,
144 +0.1950903220161282678482848684770222409276916177519548077545020894,
145 +0.3826834323650897717284599840303988667613445624856270414338006356,
146 +0.5555702330196022247428308139485328743749371907548040459241535282,
147 +0.7071067811865475244008443621048490392848359376884740365883398689,
148 +0.8314696123025452370787883776179057567385608119872499634461245902,
149 +0.9238795325112867561281831893967882868224166258636424861150977312,
150 +0.9807852804032304491261822361342390369739337308933360950029160885,
151 }
152
153
154
155
156
157
158
159
160
161
162 func slowFDCT(b *block) {
163 var dst [blockSize]float64
164 for v := 0; v < 8; v++ {
165 for u := 0; u < 8; u++ {
166 sum := 0.0
167 for y := 0; y < 8; y++ {
168 for x := 0; x < 8; x++ {
169 sum += alpha(u) * alpha(v) * float64(b[8*y+x]) *
170 cosines[((2*x+1)*u)%32] *
171 cosines[((2*y+1)*v)%32]
172 }
173 }
174 dst[8*v+u] = sum / 8
175 }
176 }
177
178 for i := range dst {
179 b[i] = int32(dst[i] + 0.5)
180 }
181 }
182
183
184
185
186
187
188
189
190
191
192 func slowIDCT(b *block) {
193 var dst [blockSize]float64
194 for y := 0; y < 8; y++ {
195 for x := 0; x < 8; x++ {
196 sum := 0.0
197 for v := 0; v < 8; v++ {
198 for u := 0; u < 8; u++ {
199 sum += alpha(u) * alpha(v) * float64(b[8*v+u]) *
200 cosines[((2*x+1)*u)%32] *
201 cosines[((2*y+1)*v)%32]
202 }
203 }
204 dst[8*y+x] = sum / 8
205 }
206 }
207
208 for i := range dst {
209 b[i] = int32(dst[i] + 0.5)
210 }
211 }
212
213 func (b *block) String() string {
214 s := &strings.Builder{}
215 fmt.Fprintf(s, "{\n")
216 for y := 0; y < 8; y++ {
217 fmt.Fprintf(s, "\t")
218 for x := 0; x < 8; x++ {
219 fmt.Fprintf(s, "0x%04x, ", uint16(b[8*y+x]))
220 }
221 fmt.Fprintln(s)
222 }
223 fmt.Fprintf(s, "}")
224 return s.String()
225 }
226
227
228 var testBlocks = [10]block{
229 {
230 0x7f, 0xf6, 0x01, 0x07, 0xff, 0x00, 0x00, 0x00,
231 0xf5, 0x01, 0xfa, 0x01, 0xfe, 0x00, 0x01, 0x00,
232 0x05, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x01, 0xff, 0xf8, 0x00, 0x01, 0xff, 0x00, 0x00,
234 0x00, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00,
235 0xff, 0x0c, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01,
236 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
237 0x01, 0x00, 0x00, 0x01, 0xff, 0x01, 0x00, 0xfe,
238 },
239 {
240 0x29, 0x07, 0x00, 0xfc, 0x01, 0x01, 0x00, 0x00,
241 0x07, 0x00, 0x03, 0x00, 0x01, 0x00, 0xff, 0xff,
242 0xff, 0xfd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
243 0x00, 0x00, 0x04, 0x00, 0xff, 0x01, 0x00, 0x00,
244 0x01, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
245 0x01, 0xfa, 0x01, 0x00, 0x01, 0x00, 0x01, 0xff,
246 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
247 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x02,
248 },
249 {
250 0xc5, 0xfa, 0x01, 0x00, 0x00, 0x01, 0x00, 0xff,
251 0x02, 0xff, 0x01, 0x00, 0x01, 0x00, 0xff, 0x00,
252 0xff, 0xff, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00,
253 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00,
254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
255 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
257 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
258 },
259 {
260 0x86, 0x05, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00,
261 0xf2, 0x06, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00,
262 0xf6, 0xfa, 0xf9, 0x00, 0xff, 0x01, 0x00, 0x00,
263 0xf9, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
264 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
265 0xff, 0x00, 0x00, 0x01, 0x00, 0xff, 0x01, 0x00,
266 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01,
267 0x00, 0x01, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00,
268 },
269 {
270 0x24, 0xfe, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
271 0x08, 0xfd, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00,
272 0x06, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00,
273 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
274 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
275 0x01, 0x00, 0x01, 0xff, 0x00, 0x01, 0x00, 0x00,
276 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
277 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x01,
278 },
279 {
280 0xcd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
281 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
282 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
283 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
285 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
286 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff,
288 },
289 {
290 0x81, 0xfe, 0x05, 0xff, 0x01, 0xff, 0x01, 0x00,
291 0xef, 0xf9, 0x00, 0xf9, 0x00, 0xff, 0x00, 0xff,
292 0x05, 0xf9, 0x00, 0xf8, 0x01, 0xff, 0x01, 0xff,
293 0x00, 0xff, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00,
294 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
295 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01,
296 0xff, 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00,
297 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
298 },
299 {
300 0x28, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
301 0x0b, 0x02, 0x01, 0x03, 0x00, 0xff, 0x00, 0x01,
302 0xfe, 0x02, 0x01, 0x03, 0xff, 0x00, 0x00, 0x00,
303 0x01, 0x00, 0xfd, 0x00, 0x01, 0x00, 0xff, 0x00,
304 0x01, 0xff, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00,
305 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x00, 0xff,
306 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01,
308 },
309 {
310 0xdf, 0xf9, 0xfe, 0x00, 0x03, 0x01, 0xff, 0xff,
311 0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
312 0xff, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01,
313 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00,
314 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01,
315 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
316 0x00, 0xff, 0x00, 0xff, 0x01, 0x00, 0x00, 0x01,
317 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
318 },
319 {
320 0x88, 0xfd, 0x00, 0x00, 0xff, 0x00, 0x01, 0xff,
321 0xe1, 0x06, 0x06, 0x01, 0xff, 0x00, 0x01, 0x00,
322 0x08, 0x00, 0xfa, 0x00, 0xff, 0xff, 0xff, 0xff,
323 0x08, 0x01, 0x00, 0xff, 0x01, 0xff, 0x00, 0x00,
324 0xf5, 0xff, 0x00, 0x01, 0xff, 0x01, 0x01, 0x00,
325 0xff, 0xff, 0x01, 0xff, 0x01, 0x00, 0x01, 0x00,
326 0x00, 0x01, 0x01, 0xff, 0x00, 0xff, 0x00, 0x01,
327 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
328 },
329 }
330
View as plain text