/* Copyright 2014 The Perkeep Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package images import ( "bytes" "image" "image/jpeg" "io" "io/ioutil" "testing" "perkeep.org/internal/images/fastjpeg" "perkeep.org/internal/images/resize" ) // The decode routines being benchmarked in this file will use these bytes for // their in-memory io.Readers. var jpegBytes []byte func init() { // Create image with non-uniform color to make decoding more realistic. // Solid color jpeg images decode faster than non-uniform images. b := new(bytes.Buffer) w, h := 4000, 4000 im := image.NewNRGBA(image.Rect(0, 0, w, h)) for i := range im.Pix { switch { case i%4 == 3: im.Pix[i] = 255 default: im.Pix[i] = uint8(i) } } if err := jpeg.Encode(b, im, nil); err != nil { panic(err) } jpegBytes = b.Bytes() } type decodeFunc func(r io.Reader) (image.Image, string, error) func BenchmarkStdlib(b *testing.B) { common(b, image.Decode) } func decodeDownsample(factor int) decodeFunc { return func(r io.Reader) (image.Image, string, error) { im, err := fastjpeg.DecodeDownsample(r, factor) return im, "jpeg", err } } func BenchmarkDjpeg1(b *testing.B) { if !fastjpeg.Available() { b.Skip("Skipping benchmark, djpeg unavailable.") } common(b, decodeDownsample(1)) } func BenchmarkDjpeg2(b *testing.B) { if !fastjpeg.Available() { b.Skip("Skipping benchmark, djpeg unavailable.") } common(b, decodeDownsample(2)) } func BenchmarkDjpeg4(b *testing.B) { if !fastjpeg.Available() { b.Skip("Skipping benchmark, djpeg unavailable.") } common(b, decodeDownsample(4)) } func BenchmarkDjpeg8(b *testing.B) { if !fastjpeg.Available() { b.Skip("Skipping benchmark, djpeg unavailable.") } common(b, decodeDownsample(8)) } func testRun(b testing.TB, decode decodeFunc) { if !fastjpeg.Available() { b.Skip("Skipping benchmark, djpeg unavailable.") } im, _, err := decode(bytes.NewReader(jpegBytes)) if err != nil { b.Fatal(err) } rect := im.Bounds() w, h := 128, 128 im = resize.Resize(im, rect, w, h) err = jpeg.Encode(ioutil.Discard, im, nil) if err != nil { b.Fatal(err) } } func common(b *testing.B, decode decodeFunc) { for i := 0; i < b.N; i++ { testRun(b, decode) } } func TestStdlib(t *testing.T) { testRun(t, decodeDownsample(1)) } func TestDjpeg1(t *testing.T) { testRun(t, decodeDownsample(1)) } func TestDjpeg2(t *testing.T) { testRun(t, decodeDownsample(2)) } func TestDjpeg4(t *testing.T) { testRun(t, decodeDownsample(4)) } func TestDjpeg8(t *testing.T) { testRun(t, decodeDownsample(8)) }