1 // Copyright 2011 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.
19 // zigzag maps from the natural ordering to the zig-zag ordering. For example,
20 // zigzag[0*8 + 3] is the zig-zag sequence number of the element in the fourth
21 // column and first row.
22 var zigzag
= [blockSize
]int{
23 0, 1, 5, 6, 14, 15, 27, 28,
24 2, 4, 7, 13, 16, 26, 29, 42,
25 3, 8, 12, 17, 25, 30, 41, 43,
26 9, 11, 18, 24, 31, 40, 44, 53,
27 10, 19, 23, 32, 39, 45, 52, 54,
28 20, 22, 33, 38, 46, 51, 55, 60,
29 21, 34, 37, 47, 50, 56, 59, 61,
30 35, 36, 48, 49, 57, 58, 62, 63,
33 func TestZigUnzig(t
*testing
.T
) {
34 for i
:= 0; i
< blockSize
; i
++ {
35 if unzig
[zigzag
[i
]] != i
{
36 t
.Errorf("unzig[zigzag[%d]] == %d", i
, unzig
[zigzag
[i
]])
38 if zigzag
[unzig
[i
]] != i
{
39 t
.Errorf("zigzag[unzig[%d]] == %d", i
, zigzag
[unzig
[i
]])
44 // unscaledQuantInNaturalOrder are the unscaled quantization tables in
45 // natural (not zig-zag) order, as specified in section K.1.
46 var unscaledQuantInNaturalOrder
= [nQuantIndex
][blockSize
]byte{
49 16, 11, 10, 16, 24, 40, 51, 61,
50 12, 12, 14, 19, 26, 58, 60, 55,
51 14, 13, 16, 24, 40, 57, 69, 56,
52 14, 17, 22, 29, 51, 87, 80, 62,
53 18, 22, 37, 56, 68, 109, 103, 77,
54 24, 35, 55, 64, 81, 104, 113, 92,
55 49, 64, 78, 87, 103, 121, 120, 101,
56 72, 92, 95, 98, 112, 100, 103, 99,
60 17, 18, 24, 47, 99, 99, 99, 99,
61 18, 21, 26, 66, 99, 99, 99, 99,
62 24, 26, 56, 99, 99, 99, 99, 99,
63 47, 66, 99, 99, 99, 99, 99, 99,
64 99, 99, 99, 99, 99, 99, 99, 99,
65 99, 99, 99, 99, 99, 99, 99, 99,
66 99, 99, 99, 99, 99, 99, 99, 99,
67 99, 99, 99, 99, 99, 99, 99, 99,
71 func TestUnscaledQuant(t
*testing
.T
) {
73 for i
:= quantIndex(0); i
< nQuantIndex
; i
++ {
74 for zig
:= 0; zig
< blockSize
; zig
++ {
75 got
:= unscaledQuant
[i
][zig
]
76 want
:= unscaledQuantInNaturalOrder
[i
][unzig
[zig
]]
78 t
.Errorf("i=%d, zig=%d: got %d, want %d", i
, zig
, got
, want
)
84 names
:= [nQuantIndex
]string{"Luminance", "Chrominance"}
85 buf
:= &bytes
.Buffer
{}
86 for i
, name
:= range names
{
87 fmt
.Fprintf(buf
, "// %s.\n{\n", name
)
88 for zig
:= 0; zig
< blockSize
; zig
++ {
89 fmt
.Fprintf(buf
, "%d, ", unscaledQuantInNaturalOrder
[i
][unzig
[zig
]])
94 buf
.WriteString("},\n")
96 t
.Logf("expected unscaledQuant values:\n%s", buf
.String())
100 var testCase
= []struct {
105 {"../testdata/video-001.png", 1, 24 << 8},
106 {"../testdata/video-001.png", 20, 12 << 8},
107 {"../testdata/video-001.png", 60, 8 << 8},
108 {"../testdata/video-001.png", 80, 6 << 8},
109 {"../testdata/video-001.png", 90, 4 << 8},
110 {"../testdata/video-001.png", 100, 2 << 8},
113 func delta(u0
, u1
uint32) int64 {
114 d
:= int64(u0
) - int64(u1
)
121 func readPng(filename
string) (image
.Image
, error
) {
122 f
, err
:= os
.Open(filename
)
130 func TestWriter(t
*testing
.T
) {
131 for _
, tc
:= range testCase
{
133 m0
, err
:= readPng(tc
.filename
)
135 t
.Error(tc
.filename
, err
)
138 // Encode that image as JPEG.
140 err
= Encode(&buf
, m0
, &Options
{Quality
: tc
.quality
})
142 t
.Error(tc
.filename
, err
)
146 m1
, err
:= Decode(&buf
)
148 t
.Error(tc
.filename
, err
)
151 if m0
.Bounds() != m1
.Bounds() {
152 t
.Errorf("%s, bounds differ: %v and %v", tc
.filename
, m0
.Bounds(), m1
.Bounds())
155 // Compare the average delta to the tolerance level.
156 if averageDelta(m0
, m1
) > tc
.tolerance
{
157 t
.Errorf("%s, quality=%d: average delta is too high", tc
.filename
, tc
.quality
)
163 // averageDelta returns the average delta in RGB space. The two images must
164 // have the same bounds.
165 func averageDelta(m0
, m1 image
.Image
) int64 {
168 for y
:= b
.Min
.Y
; y
< b
.Max
.Y
; y
++ {
169 for x
:= b
.Min
.X
; x
< b
.Max
.X
; x
++ {
172 r0
, g0
, b0
, _
:= c0
.RGBA()
173 r1
, g1
, b1
, _
:= c1
.RGBA()
183 func BenchmarkEncode(b
*testing
.B
) {
185 img
:= image
.NewRGBA(image
.Rect(0, 0, 640, 480))
187 rnd
:= rand
.New(rand
.NewSource(123))
188 for y
:= bo
.Min
.Y
; y
< bo
.Max
.Y
; y
++ {
189 for x
:= bo
.Min
.X
; x
< bo
.Max
.X
; x
++ {
190 img
.SetRGBA(x
, y
, color
.RGBA
{
191 uint8(rnd
.Intn(256)),
192 uint8(rnd
.Intn(256)),
193 uint8(rnd
.Intn(256)),
198 b
.SetBytes(640 * 480 * 4)
200 options
:= &Options
{Quality
: 90}
201 for i
:= 0; i
< b
.N
; i
++ {
202 Encode(ioutil
.Discard
, img
, options
)