2012-08-02 19:59:40 +00:00
|
|
|
package resize
|
|
|
|
|
|
|
|
import (
|
|
|
|
"image"
|
|
|
|
"image/color"
|
2014-09-15 09:58:05 +00:00
|
|
|
"runtime"
|
2012-08-02 19:59:40 +00:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2012-08-03 16:12:26 +00:00
|
|
|
var img = image.NewGray16(image.Rect(0, 0, 3, 3))
|
|
|
|
|
2012-08-31 22:21:10 +00:00
|
|
|
func init() {
|
2014-09-15 09:58:05 +00:00
|
|
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
2012-08-03 16:12:26 +00:00
|
|
|
img.Set(1, 1, color.White)
|
2012-08-31 22:21:10 +00:00
|
|
|
}
|
2012-08-03 16:12:26 +00:00
|
|
|
|
|
|
|
func Test_Param1(t *testing.T) {
|
2012-08-09 16:56:42 +00:00
|
|
|
m := Resize(0, 0, img, NearestNeighbor)
|
|
|
|
if m.Bounds() != img.Bounds() {
|
2012-08-03 16:12:26 +00:00
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_Param2(t *testing.T) {
|
2012-08-09 16:56:42 +00:00
|
|
|
m := Resize(100, 0, img, NearestNeighbor)
|
|
|
|
if m.Bounds() != image.Rect(0, 0, 100, 100) {
|
2012-08-03 16:12:26 +00:00
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_ZeroImg(t *testing.T) {
|
|
|
|
zeroImg := image.NewGray16(image.Rect(0, 0, 0, 0))
|
|
|
|
|
2012-08-09 16:56:42 +00:00
|
|
|
m := Resize(0, 0, zeroImg, NearestNeighbor)
|
|
|
|
if m.Bounds() != zeroImg.Bounds() {
|
2012-08-02 19:59:40 +00:00
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
}
|
2012-08-31 22:21:10 +00:00
|
|
|
|
2013-03-10 09:58:08 +00:00
|
|
|
func Test_CorrectResize(t *testing.T) {
|
2013-03-10 10:55:50 +00:00
|
|
|
zeroImg := image.NewGray16(image.Rect(0, 0, 256, 256))
|
2013-03-10 09:58:08 +00:00
|
|
|
|
|
|
|
m := Resize(60, 0, zeroImg, NearestNeighbor)
|
2013-03-10 10:55:50 +00:00
|
|
|
if m.Bounds() != image.Rect(0, 0, 60, 60) {
|
2013-03-10 09:58:08 +00:00
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-19 11:19:31 +00:00
|
|
|
func Test_SameColor(t *testing.T) {
|
|
|
|
img := image.NewRGBA(image.Rect(0, 0, 20, 20))
|
|
|
|
for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
|
|
|
|
for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
|
|
|
|
img.SetRGBA(x, y, color.RGBA{0x80, 0x80, 0x80, 0xFF})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out := Resize(10, 10, img, Lanczos3)
|
|
|
|
for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
|
|
|
|
for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
|
|
|
|
color := img.At(x, y).(color.RGBA)
|
|
|
|
if color.R != 0x80 || color.G != 0x80 || color.B != 0x80 || color.A != 0xFF {
|
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-13 18:12:18 +00:00
|
|
|
func Test_Bounds(t *testing.T) {
|
|
|
|
img := image.NewRGBA(image.Rect(20, 10, 200, 99))
|
|
|
|
out := Resize(80, 80, img, Lanczos2)
|
|
|
|
out.At(0, 0)
|
|
|
|
}
|
|
|
|
|
2014-12-17 10:10:53 +00:00
|
|
|
func Test_SameSizeReturnsOriginal(t *testing.T) {
|
|
|
|
img := image.NewRGBA(image.Rect(0, 0, 10, 10))
|
|
|
|
out := Resize(0, 0, img, Lanczos2)
|
|
|
|
|
|
|
|
if img != out {
|
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
|
|
|
|
out = Resize(10, 10, img, Lanczos2)
|
|
|
|
|
|
|
|
if img != out {
|
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-27 18:48:18 +00:00
|
|
|
func Test_PixelCoordinates(t *testing.T) {
|
|
|
|
checkers := image.NewGray(image.Rect(0, 0, 4, 4))
|
|
|
|
checkers.Pix = []uint8{
|
|
|
|
255, 0, 255, 0,
|
|
|
|
0, 255, 0, 255,
|
|
|
|
255, 0, 255, 0,
|
|
|
|
0, 255, 0, 255,
|
|
|
|
}
|
|
|
|
|
|
|
|
resized := Resize(12, 12, checkers, NearestNeighbor).(*image.Gray)
|
|
|
|
|
|
|
|
if resized.Pix[0] != 255 || resized.Pix[1] != 255 || resized.Pix[2] != 255 {
|
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
|
|
|
|
if resized.Pix[3] != 0 || resized.Pix[4] != 0 || resized.Pix[5] != 0 {
|
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-15 21:40:38 +00:00
|
|
|
const (
|
|
|
|
// Use a small image size for benchmarks. We don't want memory performance
|
|
|
|
// to affect the benchmark results.
|
|
|
|
benchMaxX = 250
|
|
|
|
benchMaxY = 250
|
|
|
|
|
|
|
|
// Resize values near the original size require increase the amount of time
|
|
|
|
// resize spends converting the image.
|
|
|
|
benchWidth = 200
|
|
|
|
benchHeight = 200
|
|
|
|
)
|
|
|
|
|
|
|
|
func benchRGBA(b *testing.B, interp InterpolationFunction) {
|
|
|
|
m := image.NewRGBA(image.Rect(0, 0, benchMaxX, benchMaxY))
|
|
|
|
// Initialize m's pixels to create a non-uniform image.
|
|
|
|
for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ {
|
|
|
|
for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ {
|
|
|
|
i := m.PixOffset(x, y)
|
|
|
|
m.Pix[i+0] = uint8(y + 4*x)
|
|
|
|
m.Pix[i+1] = uint8(y + 4*x)
|
|
|
|
m.Pix[i+2] = uint8(y + 4*x)
|
|
|
|
m.Pix[i+3] = uint8(4*y + x)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var out image.Image
|
|
|
|
b.ResetTimer()
|
2012-09-19 17:32:00 +00:00
|
|
|
for i := 0; i < b.N; i++ {
|
2015-03-15 21:40:38 +00:00
|
|
|
out = Resize(benchWidth, benchHeight, m, interp)
|
2012-09-19 17:32:00 +00:00
|
|
|
}
|
2015-03-15 21:40:38 +00:00
|
|
|
out.At(0, 0)
|
2012-08-31 22:21:10 +00:00
|
|
|
}
|
2012-09-19 19:03:56 +00:00
|
|
|
|
2015-03-15 21:40:38 +00:00
|
|
|
// The names of some interpolation functions are truncated so that the columns
|
|
|
|
// of 'go test -bench' line up.
|
|
|
|
func Benchmark_Nearest_RGBA(b *testing.B) {
|
|
|
|
benchRGBA(b, NearestNeighbor)
|
|
|
|
}
|
2012-09-19 19:03:56 +00:00
|
|
|
|
2015-03-15 21:40:38 +00:00
|
|
|
func Benchmark_Bilinear_RGBA(b *testing.B) {
|
|
|
|
benchRGBA(b, Bilinear)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Benchmark_Bicubic_RGBA(b *testing.B) {
|
|
|
|
benchRGBA(b, Bicubic)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Benchmark_Mitchell_RGBA(b *testing.B) {
|
|
|
|
benchRGBA(b, MitchellNetravali)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Benchmark_Lanczos2_RGBA(b *testing.B) {
|
|
|
|
benchRGBA(b, Lanczos2)
|
2012-09-19 19:03:56 +00:00
|
|
|
}
|
2014-01-18 10:55:34 +00:00
|
|
|
|
2015-03-15 21:40:38 +00:00
|
|
|
func Benchmark_Lanczos3_RGBA(b *testing.B) {
|
|
|
|
benchRGBA(b, Lanczos3)
|
|
|
|
}
|
2014-01-18 10:55:34 +00:00
|
|
|
|
2015-03-15 21:40:38 +00:00
|
|
|
func benchYCbCr(b *testing.B, interp InterpolationFunction) {
|
|
|
|
m := image.NewYCbCr(image.Rect(0, 0, benchMaxX, benchMaxY), image.YCbCrSubsampleRatio422)
|
|
|
|
// Initialize m's pixels to create a non-uniform image.
|
|
|
|
for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ {
|
|
|
|
for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ {
|
|
|
|
yi := m.YOffset(x, y)
|
|
|
|
ci := m.COffset(x, y)
|
|
|
|
m.Y[yi] = uint8(16*y + x)
|
|
|
|
m.Cb[ci] = uint8(y + 16*x)
|
|
|
|
m.Cr[ci] = uint8(y + 16*x)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var out image.Image
|
|
|
|
b.ResetTimer()
|
2014-01-18 10:55:34 +00:00
|
|
|
for i := 0; i < b.N; i++ {
|
2015-03-15 21:40:38 +00:00
|
|
|
out = Resize(benchWidth, benchHeight, m, interp)
|
2014-01-18 10:55:34 +00:00
|
|
|
}
|
2015-03-15 21:40:38 +00:00
|
|
|
out.At(0, 0)
|
2014-01-18 10:55:34 +00:00
|
|
|
}
|
|
|
|
|
2015-03-15 21:40:38 +00:00
|
|
|
func Benchmark_Nearest_YCC(b *testing.B) {
|
|
|
|
benchYCbCr(b, NearestNeighbor)
|
2014-01-18 10:55:34 +00:00
|
|
|
}
|
|
|
|
|
2015-03-15 21:40:38 +00:00
|
|
|
func Benchmark_Bilinear_YCC(b *testing.B) {
|
|
|
|
benchYCbCr(b, Bilinear)
|
2014-01-18 10:55:34 +00:00
|
|
|
}
|
|
|
|
|
2015-03-15 21:40:38 +00:00
|
|
|
func Benchmark_Bicubic_YCC(b *testing.B) {
|
|
|
|
benchYCbCr(b, Bicubic)
|
2014-01-18 10:55:34 +00:00
|
|
|
}
|
|
|
|
|
2015-03-15 21:40:38 +00:00
|
|
|
func Benchmark_Mitchell_YCC(b *testing.B) {
|
|
|
|
benchYCbCr(b, MitchellNetravali)
|
2014-01-18 10:55:34 +00:00
|
|
|
}
|
|
|
|
|
2015-03-15 21:40:38 +00:00
|
|
|
func Benchmark_Lanczos2_YCC(b *testing.B) {
|
|
|
|
benchYCbCr(b, Lanczos2)
|
2014-01-18 10:55:34 +00:00
|
|
|
}
|
|
|
|
|
2015-03-15 21:40:38 +00:00
|
|
|
func Benchmark_Lanczos3_YCC(b *testing.B) {
|
|
|
|
benchYCbCr(b, Lanczos3)
|
2014-01-18 10:55:34 +00:00
|
|
|
}
|