1/* 2Copyright 2014 The Perkeep Authors. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package images 18 19import ( 20 "bytes" 21 "image" 22 "image/jpeg" 23 "io" 24 "io/ioutil" 25 "testing" 26 27 "perkeep.org/internal/images/fastjpeg" 28 "perkeep.org/internal/images/resize" 29) 30 31// The decode routines being benchmarked in this file will use these bytes for 32// their in-memory io.Readers. 33var jpegBytes []byte 34 35func init() { 36 // Create image with non-uniform color to make decoding more realistic. 37 // Solid color jpeg images decode faster than non-uniform images. 38 b := new(bytes.Buffer) 39 w, h := 4000, 4000 40 im := image.NewNRGBA(image.Rect(0, 0, w, h)) 41 for i := range im.Pix { 42 switch { 43 case i%4 == 3: 44 im.Pix[i] = 255 45 default: 46 im.Pix[i] = uint8(i) 47 } 48 } 49 if err := jpeg.Encode(b, im, nil); err != nil { 50 panic(err) 51 } 52 jpegBytes = b.Bytes() 53} 54 55type decodeFunc func(r io.Reader) (image.Image, string, error) 56 57func BenchmarkStdlib(b *testing.B) { 58 common(b, image.Decode) 59} 60 61func decodeDownsample(factor int) decodeFunc { 62 return func(r io.Reader) (image.Image, string, error) { 63 im, err := fastjpeg.DecodeDownsample(r, factor) 64 return im, "jpeg", err 65 } 66} 67 68func BenchmarkDjpeg1(b *testing.B) { 69 if !fastjpeg.Available() { 70 b.Skip("Skipping benchmark, djpeg unavailable.") 71 } 72 common(b, decodeDownsample(1)) 73} 74 75func BenchmarkDjpeg2(b *testing.B) { 76 if !fastjpeg.Available() { 77 b.Skip("Skipping benchmark, djpeg unavailable.") 78 } 79 common(b, decodeDownsample(2)) 80} 81 82func BenchmarkDjpeg4(b *testing.B) { 83 if !fastjpeg.Available() { 84 b.Skip("Skipping benchmark, djpeg unavailable.") 85 } 86 common(b, decodeDownsample(4)) 87} 88 89func BenchmarkDjpeg8(b *testing.B) { 90 if !fastjpeg.Available() { 91 b.Skip("Skipping benchmark, djpeg unavailable.") 92 } 93 common(b, decodeDownsample(8)) 94} 95 96func testRun(b testing.TB, decode decodeFunc) { 97 if !fastjpeg.Available() { 98 b.Skip("Skipping benchmark, djpeg unavailable.") 99 } 100 im, _, err := decode(bytes.NewReader(jpegBytes)) 101 if err != nil { 102 b.Fatal(err) 103 } 104 rect := im.Bounds() 105 w, h := 128, 128 106 im = resize.Resize(im, rect, w, h) 107 err = jpeg.Encode(ioutil.Discard, im, nil) 108 if err != nil { 109 b.Fatal(err) 110 } 111} 112 113func common(b *testing.B, decode decodeFunc) { 114 for i := 0; i < b.N; i++ { 115 testRun(b, decode) 116 } 117} 118 119func TestStdlib(t *testing.T) { 120 testRun(t, decodeDownsample(1)) 121} 122 123func TestDjpeg1(t *testing.T) { 124 testRun(t, decodeDownsample(1)) 125} 126 127func TestDjpeg2(t *testing.T) { 128 testRun(t, decodeDownsample(2)) 129} 130 131func TestDjpeg4(t *testing.T) { 132 testRun(t, decodeDownsample(4)) 133} 134 135func TestDjpeg8(t *testing.T) { 136 testRun(t, decodeDownsample(8)) 137} 138