1// Copyright 2013 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. 4 5package bmp 6 7import ( 8 "bytes" 9 "fmt" 10 "image" 11 "image/draw" 12 "io/ioutil" 13 "os" 14 "testing" 15 "time" 16) 17 18func openImage(filename string) (image.Image, error) { 19 f, err := os.Open(testdataDir + filename) 20 if err != nil { 21 return nil, err 22 } 23 defer f.Close() 24 return Decode(f) 25} 26 27func convertToRGBA(in image.Image) image.Image { 28 b := in.Bounds() 29 out := image.NewRGBA(b) 30 draw.Draw(out, b, in, b.Min, draw.Src) 31 return out 32} 33 34func convertToNRGBA(in image.Image) image.Image { 35 b := in.Bounds() 36 out := image.NewNRGBA(b) 37 draw.Draw(out, b, in, b.Min, draw.Src) 38 return out 39} 40 41func TestEncode(t *testing.T) { 42 testCases := []string{ 43 "video-001.bmp", 44 "yellow_rose-small.bmp", 45 } 46 47 for _, tc := range testCases { 48 img0, err := openImage(tc) 49 if err != nil { 50 t.Errorf("%s: Open BMP: %v", tc, err) 51 continue 52 } 53 54 buf := new(bytes.Buffer) 55 err = Encode(buf, img0) 56 if err != nil { 57 t.Errorf("%s: Encode BMP: %v", tc, err) 58 continue 59 } 60 61 img1, err := Decode(buf) 62 if err != nil { 63 t.Errorf("%s: Decode BMP: %v", tc, err) 64 continue 65 } 66 67 err = compare(img0, img1) 68 if err != nil { 69 t.Errorf("%s: Compare BMP: %v", tc, err) 70 continue 71 } 72 73 buf2 := new(bytes.Buffer) 74 rgba := convertToRGBA(img0) 75 err = Encode(buf2, rgba) 76 if err != nil { 77 t.Errorf("%s: Encode pre-multiplied BMP: %v", tc, err) 78 continue 79 } 80 81 img2, err := Decode(buf2) 82 if err != nil { 83 t.Errorf("%s: Decode pre-multiplied BMP: %v", tc, err) 84 continue 85 } 86 87 // We need to do another round trip to NRGBA to compare to, since 88 // the conversion process is lossy. 89 img3 := convertToNRGBA(rgba) 90 91 err = compare(img3, img2) 92 if err != nil { 93 t.Errorf("%s: Compare pre-multiplied BMP: %v", tc, err) 94 } 95 } 96} 97 98// TestZeroWidthVeryLargeHeight tests that encoding and decoding a degenerate 99// image with zero width but over one billion pixels in height is faster than 100// naively calling an io.Reader or io.Writer method once per row. 101func TestZeroWidthVeryLargeHeight(t *testing.T) { 102 c := make(chan error, 1) 103 go func() { 104 b := image.Rect(0, 0, 0, 0x3fffffff) 105 var buf bytes.Buffer 106 if err := Encode(&buf, image.NewRGBA(b)); err != nil { 107 c <- err 108 return 109 } 110 m, err := Decode(&buf) 111 if err != nil { 112 c <- err 113 return 114 } 115 if got := m.Bounds(); got != b { 116 c <- fmt.Errorf("bounds: got %v, want %v", got, b) 117 return 118 } 119 c <- nil 120 }() 121 select { 122 case err := <-c: 123 if err != nil { 124 t.Fatal(err) 125 } 126 case <-time.After(3 * time.Second): 127 t.Fatalf("timed out") 128 } 129} 130 131// BenchmarkEncode benchmarks the encoding of an image. 132func BenchmarkEncode(b *testing.B) { 133 img, err := openImage("video-001.bmp") 134 if err != nil { 135 b.Fatal(err) 136 } 137 s := img.Bounds().Size() 138 b.SetBytes(int64(s.X * s.Y * 4)) 139 b.ResetTimer() 140 for i := 0; i < b.N; i++ { 141 Encode(ioutil.Discard, img) 142 } 143} 144