فهرست منبع

more benchmarks, new test images

Grigory Dryapak 7 سال پیش
والد
کامیت
e855101abf

+ 20 - 21
README.md

@@ -5,7 +5,6 @@
 [![Coverage Status](https://coveralls.io/repos/github/disintegration/imaging/badge.svg?branch=master)](https://coveralls.io/github/disintegration/imaging?branch=master)
 
 Package imaging provides basic image manipulation functions (resize, rotate, flip, crop, etc.). 
-This package is based on the standard Go image package and works best along with it. 
 
 Image manipulation functions provided by the package take any image type 
 that implements `image.Image` interface as an input, and return a new image of 
@@ -56,9 +55,9 @@ The full list of supported filters:  NearestNeighbor, Box, Linear, Hermite, Mitc
 
 The original image.
 
-![srcImage](testdata/lena_512.png)
+![srcImage](testdata/branches.png)
 
-The same image resized from 512x512px to 128x128px using different resampling filters.
+The same image resized from 600x400px to 150x100px using different resampling filters.
 From faster (lower quality) to slower (higher quality):
 
 Filter                    | Resize result
@@ -79,7 +78,7 @@ Sigma parameter allows to control the strength of the blurring effect.
 
 Original image                     | Sigma = 0.5                            | Sigma = 1.5
 -----------------------------------|----------------------------------------|---------------------------------------
-![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png)
+![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png)
 
 ### Sharpening
 
@@ -91,7 +90,7 @@ dstImage := imaging.Sharpen(srcImage, 0.5)
 
 Original image                     | Sigma = 0.5                               | Sigma = 1.5
 -----------------------------------|-------------------------------------------|------------------------------------------
-![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png)
+![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png)
 
 ### Gamma correction
 
@@ -101,7 +100,7 @@ dstImage := imaging.AdjustGamma(srcImage, 0.75)
 
 Original image                     | Gamma = 0.75                             | Gamma = 1.25
 -----------------------------------|------------------------------------------|-----------------------------------------
-![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png)
+![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png)
 
 ### Contrast adjustment
 
@@ -109,9 +108,9 @@ Original image                     | Gamma = 0.75                             |
 dstImage := imaging.AdjustContrast(srcImage, 20)
 ```
 
-Original image                     | Contrast = 10                              | Contrast = -10
+Original image                     | Contrast = 15                              | Contrast = -15
 -----------------------------------|--------------------------------------------|-------------------------------------------
-![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_contrast_p10.png) | ![dstImage](testdata/out_contrast_m10.png)
+![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_contrast_p15.png) | ![dstImage](testdata/out_contrast_m15.png)
 
 ### Brightness adjustment
 
@@ -121,7 +120,7 @@ dstImage := imaging.AdjustBrightness(srcImage, 20)
 
 Original image                     | Brightness = 10                              | Brightness = -10
 -----------------------------------|----------------------------------------------|---------------------------------------------
-![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png)
+![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png)
 
 ## Example code
 
@@ -137,20 +136,20 @@ import (
 )
 
 func main() {
-	// Open the test image.
-	src, err := imaging.Open("testdata/lena_512.png")
+	// Open a test image.
+	src, err := imaging.Open("testdata/flowers.png")
 	if err != nil {
 		log.Fatalf("Open failed: %v", err)
 	}
 
-	// Crop the original image to 350x350px size using the center anchor.
-	src = imaging.CropAnchor(src, 350, 350, imaging.Center)
+	// Crop the original image to 300x300px size using the center anchor.
+	src = imaging.CropAnchor(src, 300, 300, imaging.Center)
 
-	// Resize the cropped image to width = 256px preserving the aspect ratio.
-	src = imaging.Resize(src, 256, 0, imaging.Lanczos)
+	// Resize the cropped image to width = 200px preserving the aspect ratio.
+	src = imaging.Resize(src, 200, 0, imaging.Lanczos)
 
 	// Create a blurred version of the image.
-	img1 := imaging.Blur(src, 2)
+	img1 := imaging.Blur(src, 5)
 
 	// Create a grayscale version of the image with higher contrast and sharpness.
 	img2 := imaging.Grayscale(src)
@@ -172,13 +171,13 @@ func main() {
 	)
 
 	// Create a new image and paste the four produced images into it.
-	dst := imaging.New(512, 512, color.NRGBA{0, 0, 0, 0})
+	dst := imaging.New(400, 400, color.NRGBA{0, 0, 0, 0})
 	dst = imaging.Paste(dst, img1, image.Pt(0, 0))
-	dst = imaging.Paste(dst, img2, image.Pt(0, 256))
-	dst = imaging.Paste(dst, img3, image.Pt(256, 0))
-	dst = imaging.Paste(dst, img4, image.Pt(256, 256))
+	dst = imaging.Paste(dst, img2, image.Pt(0, 200))
+	dst = imaging.Paste(dst, img3, image.Pt(200, 0))
+	dst = imaging.Paste(dst, img4, image.Pt(200, 200))
 
-	// Save the resulting image using JPEG format.
+	// Save the resulting image as JPEG.
 	err = imaging.Save(dst, "testdata/out_example.jpg")
 	if err != nil {
 		log.Fatalf("Save failed: %v", err)

+ 47 - 17
adjust_test.go

@@ -42,6 +42,13 @@ func TestGrayscale(t *testing.T) {
 	}
 }
 
+func BenchmarkGrayscale(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		Grayscale(testdataBranchesJPG)
+	}
+}
+
 func TestInvert(t *testing.T) {
 	td := []struct {
 		desc string
@@ -79,6 +86,13 @@ func TestInvert(t *testing.T) {
 	}
 }
 
+func BenchmarkInvert(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		Invert(testdataBranchesJPG)
+	}
+}
+
 func TestAdjustContrast(t *testing.T) {
 	td := []struct {
 		desc string
@@ -207,15 +221,11 @@ func TestAdjustContrast(t *testing.T) {
 }
 
 func TestAdjustContrastGolden(t *testing.T) {
-	src, err := Open("testdata/lena_128.png")
-	if err != nil {
-		t.Errorf("Open: %v", err)
-	}
 	for name, p := range map[string]float64{
-		"out_contrast_m10.png": -10,
-		"out_contrast_p10.png": 10,
+		"out_contrast_m15.png": -15,
+		"out_contrast_p15.png": 15,
 	} {
-		got := AdjustContrast(src, p)
+		got := AdjustContrast(testdataFlowersSmallPNG, p)
 		want, err := Open("testdata/" + name)
 		if err != nil {
 			t.Errorf("Open: %v", err)
@@ -226,6 +236,13 @@ func TestAdjustContrastGolden(t *testing.T) {
 	}
 }
 
+func BenchmarkAdjustContrast(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		AdjustContrast(testdataBranchesJPG, 10)
+	}
+}
+
 func TestAdjustBrightness(t *testing.T) {
 	td := []struct {
 		desc string
@@ -354,15 +371,11 @@ func TestAdjustBrightness(t *testing.T) {
 }
 
 func TestAdjustBrightnessGolden(t *testing.T) {
-	src, err := Open("testdata/lena_128.png")
-	if err != nil {
-		t.Errorf("Open: %v", err)
-	}
 	for name, p := range map[string]float64{
 		"out_brightness_m10.png": -10,
 		"out_brightness_p10.png": 10,
 	} {
-		got := AdjustBrightness(src, p)
+		got := AdjustBrightness(testdataFlowersSmallPNG, p)
 		want, err := Open("testdata/" + name)
 		if err != nil {
 			t.Errorf("Open: %v", err)
@@ -373,6 +386,13 @@ func TestAdjustBrightnessGolden(t *testing.T) {
 	}
 }
 
+func BenchmarkAdjustBrightness(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		AdjustBrightness(testdataBranchesJPG, 10)
+	}
+}
+
 func TestAdjustGamma(t *testing.T) {
 	td := []struct {
 		desc string
@@ -457,15 +477,11 @@ func TestAdjustGamma(t *testing.T) {
 }
 
 func TestAdjustGammaGolden(t *testing.T) {
-	src, err := Open("testdata/lena_128.png")
-	if err != nil {
-		t.Errorf("Open: %v", err)
-	}
 	for name, g := range map[string]float64{
 		"out_gamma_0.75.png": 0.75,
 		"out_gamma_1.25.png": 1.25,
 	} {
-		got := AdjustGamma(src, g)
+		got := AdjustGamma(testdataFlowersSmallPNG, g)
 		want, err := Open("testdata/" + name)
 		if err != nil {
 			t.Errorf("Open: %v", err)
@@ -476,6 +492,13 @@ func TestAdjustGammaGolden(t *testing.T) {
 	}
 }
 
+func BenchmarkAdjustGamma(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		AdjustGamma(testdataBranchesJPG, 1.5)
+	}
+}
+
 func TestAdjustSigmoid(t *testing.T) {
 	td := []struct {
 		desc string
@@ -562,3 +585,10 @@ func TestAdjustSigmoid(t *testing.T) {
 		}
 	}
 }
+
+func BenchmarkAdjustSigmoid(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		AdjustSigmoid(testdataBranchesJPG, 0.5, 3.0)
+	}
+}

+ 4 - 14
convolution_test.go

@@ -233,15 +233,10 @@ func TestConvolve5x5(t *testing.T) {
 }
 
 func BenchmarkConvolve3x3(b *testing.B) {
-	b.StopTimer()
-	img, err := Open("testdata/lena_512.png")
-	if err != nil {
-		b.Fatalf("Open: %v", err)
-	}
-	b.StartTimer()
+	b.ReportAllocs()
 	for i := 0; i < b.N; i++ {
 		Convolve3x3(
-			img,
+			testdataBranchesJPG,
 			[9]float64{
 				-1, -1, 0,
 				-1, 0, 1,
@@ -253,15 +248,10 @@ func BenchmarkConvolve3x3(b *testing.B) {
 }
 
 func BenchmarkConvolve5x5(b *testing.B) {
-	b.StopTimer()
-	img, err := Open("testdata/lena_512.png")
-	if err != nil {
-		b.Fatalf("Open: %v", err)
-	}
-	b.StartTimer()
+	b.ReportAllocs()
 	for i := 0; i < b.N; i++ {
 		Convolve5x5(
-			img,
+			testdataBranchesJPG,
 			[25]float64{
 				-1, -1, -1, -1, 0,
 				-1, -1, -1, 0, 1,

+ 2 - 0
doc.go

@@ -0,0 +1,2 @@
+// Package imaging provides basic image manipulation functions (resize, rotate, flip, crop, etc.).
+package imaging

+ 6 - 24
effects_test.go

@@ -89,15 +89,11 @@ func TestBlur(t *testing.T) {
 }
 
 func TestBlurGolden(t *testing.T) {
-	src, err := Open("testdata/lena_128.png")
-	if err != nil {
-		t.Errorf("Open: %v", err)
-	}
 	for name, sigma := range map[string]float64{
 		"out_blur_0.5.png": 0.5,
 		"out_blur_1.5.png": 1.5,
 	} {
-		got := Blur(src, sigma)
+		got := Blur(testdataFlowersSmallPNG, sigma)
 		want, err := Open("testdata/" + name)
 		if err != nil {
 			t.Errorf("Open: %v", err)
@@ -109,14 +105,9 @@ func TestBlurGolden(t *testing.T) {
 }
 
 func BenchmarkBlur(b *testing.B) {
-	b.StopTimer()
-	img, err := Open("testdata/lena_512.png")
-	if err != nil {
-		b.Fatalf("Open: %v", err)
-	}
-	b.StartTimer()
+	b.ReportAllocs()
 	for i := 0; i < b.N; i++ {
-		Blur(img, 3)
+		Blur(testdataBranchesJPG, 3)
 	}
 }
 
@@ -222,15 +213,11 @@ func TestSharpen(t *testing.T) {
 }
 
 func TestSharpenGolden(t *testing.T) {
-	src, err := Open("testdata/lena_128.png")
-	if err != nil {
-		t.Errorf("Open: %v", err)
-	}
 	for name, sigma := range map[string]float64{
 		"out_sharpen_0.5.png": 0.5,
 		"out_sharpen_1.5.png": 1.5,
 	} {
-		got := Sharpen(src, sigma)
+		got := Sharpen(testdataFlowersSmallPNG, sigma)
 		want, err := Open("testdata/" + name)
 		if err != nil {
 			t.Errorf("Open: %v", err)
@@ -242,13 +229,8 @@ func TestSharpenGolden(t *testing.T) {
 }
 
 func BenchmarkSharpen(b *testing.B) {
-	b.StopTimer()
-	img, err := Open("testdata/lena_512.png")
-	if err != nil {
-		b.Fatalf("Open: %v", err)
-	}
-	b.StartTimer()
+	b.ReportAllocs()
 	for i := 0; i < b.N; i++ {
-		Sharpen(img, 3)
+		Sharpen(testdataBranchesJPG, 3)
 	}
 }

+ 12 - 12
example_test.go

@@ -9,20 +9,20 @@ import (
 )
 
 func Example() {
-	// Open the test image.
-	src, err := imaging.Open("testdata/lena_512.png")
+	// Open a test image.
+	src, err := imaging.Open("testdata/flowers.png")
 	if err != nil {
 		log.Fatalf("Open failed: %v", err)
 	}
 
-	// Crop the original image to 350x350px size using the center anchor.
-	src = imaging.CropAnchor(src, 350, 350, imaging.Center)
+	// Crop the original image to 300x300px size using the center anchor.
+	src = imaging.CropAnchor(src, 300, 300, imaging.Center)
 
-	// Resize the cropped image to width = 256px preserving the aspect ratio.
-	src = imaging.Resize(src, 256, 0, imaging.Lanczos)
+	// Resize the cropped image to width = 200px preserving the aspect ratio.
+	src = imaging.Resize(src, 200, 0, imaging.Lanczos)
 
 	// Create a blurred version of the image.
-	img1 := imaging.Blur(src, 2)
+	img1 := imaging.Blur(src, 5)
 
 	// Create a grayscale version of the image with higher contrast and sharpness.
 	img2 := imaging.Grayscale(src)
@@ -44,13 +44,13 @@ func Example() {
 	)
 
 	// Create a new image and paste the four produced images into it.
-	dst := imaging.New(512, 512, color.NRGBA{0, 0, 0, 0})
+	dst := imaging.New(400, 400, color.NRGBA{0, 0, 0, 0})
 	dst = imaging.Paste(dst, img1, image.Pt(0, 0))
-	dst = imaging.Paste(dst, img2, image.Pt(0, 256))
-	dst = imaging.Paste(dst, img3, image.Pt(256, 0))
-	dst = imaging.Paste(dst, img4, image.Pt(256, 256))
+	dst = imaging.Paste(dst, img2, image.Pt(0, 200))
+	dst = imaging.Paste(dst, img3, image.Pt(200, 0))
+	dst = imaging.Paste(dst, img4, image.Pt(200, 200))
 
-	// Save the resulting image using JPEG format.
+	// Save the resulting image as JPEG.
 	err = imaging.Save(dst, "testdata/out_example.jpg")
 	if err != nil {
 		log.Fatalf("Save failed: %v", err)

+ 2 - 12
helpers.go

@@ -1,9 +1,3 @@
-// Package imaging provides basic image manipulation functions (resize, rotate, flip, crop, etc.).
-// This package is based on the standard Go image package and works best along with it.
-//
-// Image manipulation functions provided by the package take any image type
-// that implements `image.Image` interface as an input, and return a new image of
-// `*image.NRGBA` type (32bit RGBA colors, not premultiplied by alpha).
 package imaging
 
 import (
@@ -59,10 +53,7 @@ var (
 // Decode reads an image from r.
 func Decode(r io.Reader) (image.Image, error) {
 	img, _, err := image.Decode(r)
-	if err != nil {
-		return nil, err
-	}
-	return toNRGBA(img), nil
+	return img, err
 }
 
 // Open loads an image from file
@@ -72,8 +63,7 @@ func Open(filename string) (image.Image, error) {
 		return nil, err
 	}
 	defer file.Close()
-	img, err := Decode(file)
-	return img, err
+	return Decode(file)
 }
 
 type encodeConfig struct {

+ 7 - 0
helpers_test.go

@@ -140,6 +140,13 @@ func TestNew(t *testing.T) {
 	}
 }
 
+func BenchmarkNew(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		New(1024, 1024, color.White)
+	}
+}
+
 func TestFormats(t *testing.T) {
 	formatNames := map[Format]string{
 		JPEG:       "JPEG",

+ 7 - 0
histogram_test.go

@@ -40,3 +40,10 @@ func TestHistogram(t *testing.T) {
 		}
 	}
 }
+
+func BenchmarkHistogram(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		Histogram(testdataBranchesJPG)
+	}
+}

+ 39 - 35
resize_test.go

@@ -1,6 +1,7 @@
 package imaging
 
 import (
+	"fmt"
 	"image"
 	"testing"
 )
@@ -202,17 +203,13 @@ func TestResize(t *testing.T) {
 }
 
 func TestResizeGolden(t *testing.T) {
-	src, err := Open("testdata/lena_512.png")
-	if err != nil {
-		t.Errorf("Open: %v", err)
-	}
 	for name, filter := range map[string]ResampleFilter{
 		"out_resize_nearest.png": NearestNeighbor,
 		"out_resize_linear.png":  Linear,
 		"out_resize_catrom.png":  CatmullRom,
 		"out_resize_lanczos.png": Lanczos,
 	} {
-		got := Resize(src, 128, 0, filter)
+		got := Resize(testdataBranchesPNG, 150, 0, filter)
 		want, err := Open("testdata/" + name)
 		if err != nil {
 			t.Errorf("Open: %v", err)
@@ -591,38 +588,45 @@ func TestThumbnail(t *testing.T) {
 	}
 }
 
-func BenchmarkResizeLanczosUp(b *testing.B) {
-	benchmarkResize(b, "testdata/lena_128.png", 512, Lanczos)
-}
+func BenchmarkResize(b *testing.B) {
+	for _, dir := range []string{"Down", "Up"} {
+		for _, filter := range []string{"NearestNeighbor", "Linear", "CatmullRom", "Lanczos"} {
+			for _, format := range []string{"JPEG", "PNG"} {
+				var size int
+				switch dir {
+				case "Down":
+					size = 100
+				case "Up":
+					size = 1000
+				}
 
-func BenchmarkResizeLinearUp(b *testing.B) {
-	benchmarkResize(b, "testdata/lena_128.png", 512, Linear)
-}
+				var f ResampleFilter
+				switch filter {
+				case "NearestNeighbor":
+					f = NearestNeighbor
+				case "Linear":
+					f = Linear
+				case "CatmullRom":
+					f = CatmullRom
+				case "Lanczos":
+					f = Lanczos
+				}
 
-func BenchmarkResizeNearestNeighborUp(b *testing.B) {
-	benchmarkResize(b, "testdata/lena_128.png", 512, NearestNeighbor)
-}
+				var img image.Image
+				switch format {
+				case "JPEG":
+					img = testdataBranchesJPG
+				case "PNG":
+					img = testdataBranchesPNG
+				}
 
-func BenchmarkResizeLanczosDown(b *testing.B) {
-	benchmarkResize(b, "testdata/lena_512.png", 128, Lanczos)
-}
-
-func BenchmarkResizeLinearDown(b *testing.B) {
-	benchmarkResize(b, "testdata/lena_512.png", 128, Linear)
-}
-
-func BenchmarkResizeNearestNeighborDown(b *testing.B) {
-	benchmarkResize(b, "testdata/lena_512.png", 128, NearestNeighbor)
-}
-
-func benchmarkResize(b *testing.B, filename string, size int, f ResampleFilter) {
-	b.StopTimer()
-	img, err := Open(filename)
-	if err != nil {
-		b.Fatalf("Open: %v", err)
-	}
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		Resize(img, size, size, f)
+				b.Run(fmt.Sprintf("%s %s %s", dir, filter, format), func(b *testing.B) {
+					b.ReportAllocs()
+					for i := 0; i < b.N; i++ {
+						Resize(img, size, size, f)
+					}
+				})
+			}
+		}
 	}
 }

BIN
testdata/branches.jpg


BIN
testdata/branches.png


BIN
testdata/flowers.png


BIN
testdata/flowers_small.png


BIN
testdata/out_blur_0.5.png


BIN
testdata/out_blur_1.5.png


BIN
testdata/out_brightness_m10.png


BIN
testdata/out_brightness_p10.png


BIN
testdata/out_contrast_m15.png


BIN
testdata/out_contrast_p15.png


BIN
testdata/out_example.jpg


BIN
testdata/out_gamma_0.75.png


BIN
testdata/out_gamma_1.25.png


BIN
testdata/out_resize_catrom.png


BIN
testdata/out_resize_lanczos.png


BIN
testdata/out_resize_linear.png


BIN
testdata/out_resize_nearest.png


BIN
testdata/out_sharpen_0.5.png


BIN
testdata/out_sharpen_1.5.png


+ 21 - 0
tools_test.go

@@ -42,6 +42,13 @@ func TestCrop(t *testing.T) {
 	}
 }
 
+func BenchmarkCrop(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		Crop(testdataBranchesJPG, image.Rect(100, 100, 300, 300))
+	}
+}
+
 func TestCropCenter(t *testing.T) {
 	td := []struct {
 		desc string
@@ -481,6 +488,13 @@ func TestPaste(t *testing.T) {
 	}
 }
 
+func BenchmarkPaste(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		Paste(testdataBranchesJPG, testdataFlowersSmallPNG, image.Pt(100, 100))
+	}
+}
+
 func TestPasteCenter(t *testing.T) {
 	td := []struct {
 		desc string
@@ -604,6 +618,13 @@ func TestOverlay(t *testing.T) {
 	}
 }
 
+func BenchmarkOverlay(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		Overlay(testdataBranchesJPG, testdataFlowersSmallPNG, image.Pt(100, 100), 0.5)
+	}
+}
+
 func TestOverlayCenter(t *testing.T) {
 	td := []struct {
 		desc string

+ 56 - 0
transform_test.go

@@ -43,6 +43,13 @@ func TestFlipH(t *testing.T) {
 	}
 }
 
+func BenchmarkFlipH(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		FlipH(testdataBranchesJPG)
+	}
+}
+
 func TestFlipV(t *testing.T) {
 	td := []struct {
 		desc string
@@ -80,6 +87,13 @@ func TestFlipV(t *testing.T) {
 	}
 }
 
+func BenchmarkFlipV(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		FlipV(testdataBranchesJPG)
+	}
+}
+
 func TestTranspose(t *testing.T) {
 	td := []struct {
 		desc string
@@ -116,6 +130,13 @@ func TestTranspose(t *testing.T) {
 	}
 }
 
+func BenchmarkTranspose(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		Transpose(testdataBranchesJPG)
+	}
+}
+
 func TestTransverse(t *testing.T) {
 	td := []struct {
 		desc string
@@ -152,6 +173,13 @@ func TestTransverse(t *testing.T) {
 	}
 }
 
+func BenchmarkTransverse(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		Transverse(testdataBranchesJPG)
+	}
+}
+
 func TestRotate90(t *testing.T) {
 	td := []struct {
 		desc string
@@ -188,6 +216,13 @@ func TestRotate90(t *testing.T) {
 	}
 }
 
+func BenchmarkRotate90(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		Rotate90(testdataBranchesJPG)
+	}
+}
+
 func TestRotate180(t *testing.T) {
 	td := []struct {
 		desc string
@@ -225,6 +260,13 @@ func TestRotate180(t *testing.T) {
 	}
 }
 
+func BenchmarkRotate180(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		Rotate180(testdataBranchesJPG)
+	}
+}
+
 func TestRotate270(t *testing.T) {
 	td := []struct {
 		desc string
@@ -261,6 +303,13 @@ func TestRotate270(t *testing.T) {
 	}
 }
 
+func BenchmarkRotate270(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		Rotate270(testdataBranchesJPG)
+	}
+}
+
 func TestRotate(t *testing.T) {
 	testCases := []struct {
 		desc  string
@@ -579,3 +628,10 @@ func TestRotate(t *testing.T) {
 		}
 	}
 }
+
+func BenchmarkRotate(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		Rotate(testdataBranchesJPG, 30, color.Transparent)
+	}
+}

+ 22 - 8
utils_test.go

@@ -1,11 +1,27 @@
 package imaging
 
 import (
+	"image"
 	"runtime"
 	"testing"
 )
 
-func testParallelN(enabled bool, n, procs int) bool {
+var (
+	testdataBranchesJPG     = mustOpen("testdata/branches.jpg")
+	testdataBranchesPNG     = mustOpen("testdata/branches.png")
+	testdataFlowersPNG      = mustOpen("testdata/flowers.png")
+	testdataFlowersSmallPNG = mustOpen("testdata/flowers_small.png")
+)
+
+func mustOpen(filename string) image.Image {
+	img, err := Open(filename)
+	if err != nil {
+		panic(err)
+	}
+	return img
+}
+
+func testParallelN(n, procs int) bool {
 	data := make([]bool, n)
 	before := runtime.GOMAXPROCS(0)
 	runtime.GOMAXPROCS(procs)
@@ -14,22 +30,20 @@ func testParallelN(enabled bool, n, procs int) bool {
 			data[i] = true
 		}
 	})
+	runtime.GOMAXPROCS(before)
 	for i := 0; i < n; i++ {
 		if !data[i] {
 			return false
 		}
 	}
-	runtime.GOMAXPROCS(before)
 	return true
 }
 
 func TestParallel(t *testing.T) {
-	for _, e := range []bool{true, false} {
-		for _, n := range []int{1, 10, 100, 1000} {
-			for _, p := range []int{1, 2, 4, 8, 16, 100} {
-				if !testParallelN(e, n, p) {
-					t.Errorf("test [parallel %v %d %d] failed", e, n, p)
-				}
+	for _, n := range []int{0, 1, 10, 100, 1000} {
+		for _, p := range []int{1, 2, 4, 8, 16, 100} {
+			if !testParallelN(n, p) {
+				t.Errorf("test [parallel %d %d] failed", n, p)
 			}
 		}
 	}