| // Copyright 2011 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package jpeg |
| |
| import ( |
| "bytes" |
| "image" |
| "image/color" |
| "image/png" |
| "io/ioutil" |
| "math/rand" |
| "os" |
| "testing" |
| ) |
| |
| var testCase = []struct { |
| filename string |
| quality int |
| tolerance int64 |
| }{ |
| {"../testdata/video-001.png", 1, 24 << 8}, |
| {"../testdata/video-001.png", 20, 12 << 8}, |
| {"../testdata/video-001.png", 60, 8 << 8}, |
| {"../testdata/video-001.png", 80, 6 << 8}, |
| {"../testdata/video-001.png", 90, 4 << 8}, |
| {"../testdata/video-001.png", 100, 2 << 8}, |
| } |
| |
| func delta(u0, u1 uint32) int64 { |
| d := int64(u0) - int64(u1) |
| if d < 0 { |
| return -d |
| } |
| return d |
| } |
| |
| func readPng(filename string) (image.Image, error) { |
| f, err := os.Open(filename) |
| if err != nil { |
| return nil, err |
| } |
| defer f.Close() |
| return png.Decode(f) |
| } |
| |
| func TestWriter(t *testing.T) { |
| for _, tc := range testCase { |
| // Read the image. |
| m0, err := readPng(tc.filename) |
| if err != nil { |
| t.Error(tc.filename, err) |
| continue |
| } |
| // Encode that image as JPEG. |
| var buf bytes.Buffer |
| err = Encode(&buf, m0, &Options{Quality: tc.quality}) |
| if err != nil { |
| t.Error(tc.filename, err) |
| continue |
| } |
| // Decode that JPEG. |
| m1, err := Decode(&buf) |
| if err != nil { |
| t.Error(tc.filename, err) |
| continue |
| } |
| // Compute the average delta in RGB space. |
| b := m0.Bounds() |
| var sum, n int64 |
| for y := b.Min.Y; y < b.Max.Y; y++ { |
| for x := b.Min.X; x < b.Max.X; x++ { |
| c0 := m0.At(x, y) |
| c1 := m1.At(x, y) |
| r0, g0, b0, _ := c0.RGBA() |
| r1, g1, b1, _ := c1.RGBA() |
| sum += delta(r0, r1) |
| sum += delta(g0, g1) |
| sum += delta(b0, b1) |
| n += 3 |
| } |
| } |
| // Compare the average delta to the tolerance level. |
| if sum/n > tc.tolerance { |
| t.Errorf("%s, quality=%d: average delta is too high", tc.filename, tc.quality) |
| continue |
| } |
| } |
| } |
| |
| func BenchmarkEncodeRGBOpaque(b *testing.B) { |
| b.StopTimer() |
| img := image.NewRGBA(image.Rect(0, 0, 640, 480)) |
| // Set all pixels to 0xFF alpha to force opaque mode. |
| bo := img.Bounds() |
| rnd := rand.New(rand.NewSource(123)) |
| for y := bo.Min.Y; y < bo.Max.Y; y++ { |
| for x := bo.Min.X; x < bo.Max.X; x++ { |
| img.Set(x, y, color.RGBA{ |
| uint8(rnd.Intn(256)), |
| uint8(rnd.Intn(256)), |
| uint8(rnd.Intn(256)), |
| 255}) |
| } |
| } |
| if !img.Opaque() { |
| b.Fatal("expected image to be opaque") |
| } |
| b.SetBytes(640 * 480 * 4) |
| b.StartTimer() |
| options := &Options{Quality: 90} |
| for i := 0; i < b.N; i++ { |
| Encode(ioutil.Discard, img, options) |
| } |
| } |