blob: d8897f9cea98e285e9b46900f95c7abb69b33d6c [file] [log] [blame]
package imaging
import (
"fmt"
"image"
"path/filepath"
"testing"
)
func TestResize(t *testing.T) {
testCases := []struct {
name string
src image.Image
w, h int
f ResampleFilter
want *image.NRGBA
}{
{
"Resize 2x2 1x1 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
1, 1,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 1),
Stride: 1 * 4,
Pix: []uint8{0x55, 0x55, 0x55, 0xc0},
},
},
{
"Resize 2x2 1x2 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
1, 2,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{
0xff, 0x00, 0x00, 0x80,
0x00, 0x80, 0x80, 0xff,
},
},
},
{
"Resize 2x2 2x1 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
2, 1,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 2, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0xff, 0x00, 0x80, 0x80, 0x00, 0x80, 0xff,
},
},
},
{
"Resize 2x2 2x2 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
2, 2,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 2, 2),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
},
{
"Resize 3x1 1x1 nearest",
&image.NRGBA{
Rect: image.Rect(-1, -1, 2, 0),
Stride: 3 * 4,
Pix: []uint8{
0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
1, 1,
NearestNeighbor,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 1),
Stride: 1 * 4,
Pix: []uint8{0x00, 0xff, 0x00, 0xff},
},
},
{
"Resize 2x2 0x4 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
0, 4,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 4, 4),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
},
{
"Resize 2x2 4x0 linear",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
4, 0,
Linear,
&image.NRGBA{
Rect: image.Rect(0, 0, 4, 4),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x40, 0xff, 0x00, 0x00, 0xbf, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0x40, 0x6e, 0x6d, 0x25, 0x70, 0xb0, 0x14, 0x3b, 0xcf, 0xbf, 0x00, 0x40, 0xff,
0x00, 0xff, 0x00, 0xbf, 0x14, 0xb0, 0x3b, 0xcf, 0x33, 0x33, 0x99, 0xef, 0x40, 0x00, 0xbf, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0xbf, 0x40, 0xff, 0x00, 0x40, 0xbf, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
},
{
"Resize 0x0 1x1 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, -1, -1),
Stride: 0,
Pix: []uint8{},
},
1, 1,
Box,
&image.NRGBA{},
},
{
"Resize 2x2 0x0 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
0, 0,
Box,
&image.NRGBA{},
},
{
"Resize 2x2 -1x0 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
-1, 0,
Box,
&image.NRGBA{},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got := Resize(tc.src, tc.w, tc.h, tc.f)
if !compareNRGBA(got, tc.want, 0) {
t.Fatalf("got result %#v want %#v", got, tc.want)
}
})
}
}
func TestResampleFilters(t *testing.T) {
for _, filter := range []ResampleFilter{
NearestNeighbor,
Box,
Linear,
Hermite,
MitchellNetravali,
CatmullRom,
BSpline,
Gaussian,
Lanczos,
Hann,
Hamming,
Blackman,
Bartlett,
Welch,
Cosine,
} {
t.Run("", func(t *testing.T) {
src := image.NewNRGBA(image.Rect(-1, -1, 2, 3))
got := Resize(src, 5, 6, filter)
want := image.NewNRGBA(image.Rect(0, 0, 5, 6))
if !compareNRGBA(got, want, 0) {
t.Fatalf("got result %#v want %#v", got, want)
}
if filter.Kernel != nil {
if x := filter.Kernel(filter.Support + 0.0001); x != 0 {
t.Fatalf("got kernel value %f want 0", x)
}
}
})
}
}
func TestResizeGolden(t *testing.T) {
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(testdataBranchesPNG, 150, 0, filter)
want, err := Open("testdata/" + name)
if err != nil {
t.Fatalf("failed to open image: %v", err)
}
if !compareNRGBAGolden(got, toNRGBA(want)) {
t.Fatalf("resulting image differs from golden: %s", name)
}
}
}
func TestFit(t *testing.T) {
testCases := []struct {
name string
src image.Image
w, h int
f ResampleFilter
want *image.NRGBA
}{
{
"Fit 2x2 1x10 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
1, 10,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 1),
Stride: 1 * 4,
Pix: []uint8{0x55, 0x55, 0x55, 0xc0},
},
},
{
"Fit 2x2 10x1 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
10, 1,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 1),
Stride: 1 * 4,
Pix: []uint8{0x55, 0x55, 0x55, 0xc0},
},
},
{
"Fit 2x2 10x10 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
10, 10,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 2, 2),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
},
{
"Fit 0x0 1x1 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, -1, -1),
Stride: 0,
Pix: []uint8{},
},
1, 1,
Box,
&image.NRGBA{},
},
{
"Fit 2x2 0x0 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
0, 0,
Box,
&image.NRGBA{},
},
{
"Fit 2x2 -1x0 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
},
},
-1, 0,
Box,
&image.NRGBA{},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got := Fit(tc.src, tc.w, tc.h, tc.f)
if !compareNRGBA(got, tc.want, 0) {
t.Fatalf("got result %#v want %#v", got, tc.want)
}
})
}
}
func TestFitGolden(t *testing.T) {
got := Fit(testdataBranchesPNG, 150, 150, Box)
name := filepath.Join("testdata", "out_fit.png")
want, err := Open(name)
if err != nil {
t.Fatalf("failed to open image: %v", err)
}
if !compareNRGBAGolden(got, toNRGBA(want)) {
t.Fatalf("resulting image differs from golden: %s", name)
}
}
func TestFill(t *testing.T) {
testCases := []struct {
name string
src image.Image
w, h int
a Anchor
f ResampleFilter
want *image.NRGBA
}{
{
"Fill 4x4 4x4 TopRight Box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
4, 4,
TopRight,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 4, 4),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
},
{
"Fill 4x4 0x4 Left Box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
0, 4,
Left,
Box,
&image.NRGBA{},
},
{
"Fill 0x0 4x4 Right Box",
&image.NRGBA{},
4, 4,
Right,
Box,
&image.NRGBA{},
},
{
"Fill 100x200 20x10 Center Linear",
image.NewRGBA(image.Rect(0, 0, 100, 200)),
20, 10,
Center,
Linear,
image.NewNRGBA(image.Rect(0, 0, 20, 10)),
},
{
"Fill 10x20 20x10 Center Linear",
image.NewRGBA(image.Rect(0, 0, 10, 20)),
20, 10,
Center,
Linear,
image.NewNRGBA(image.Rect(0, 0, 20, 10)),
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got := Fill(tc.src, tc.w, tc.h, tc.a, tc.f)
if !compareNRGBA(got, tc.want, 0) {
t.Fatalf("got result %#v want %#v", got, tc.want)
}
})
}
}
func TestFillGolden(t *testing.T) {
anchorPoints := map[string]Anchor{
"left": Left,
"center": Center,
"right": Right,
}
for apName, ap := range anchorPoints {
got := Fill(testdataBranchesPNG, 150, 150, ap, Box)
name := filepath.Join("testdata", "out_fill_"+apName+".png")
want, err := Open(name)
if err != nil {
t.Fatalf("failed to open image: %v", err)
}
if !compareNRGBAGolden(got, toNRGBA(want)) {
t.Fatalf("resulting image differs from golden: %s", name)
}
}
}
func TestResizeAndCrop(t *testing.T) {
testCases := []struct {
name string
src image.Image
w, h int
a Anchor
f ResampleFilter
want *image.NRGBA
}{
{
"resizeAndCrop 4x4 2x2 Center Nearest",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
2, 2,
Center,
NearestNeighbor,
&image.NRGBA{
Rect: image.Rect(0, 0, 2, 2),
Stride: 2 * 4,
Pix: []uint8{
0x14, 0x15, 0x16, 0x17, 0x1c, 0x1d, 0x1e, 0x1f,
0x34, 0x35, 0x36, 0x37, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
},
{
"resizeAndCrop 4x4 1x4 TopLeft Nearest",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
1, 4,
TopLeft,
NearestNeighbor,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 4),
Stride: 1 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03,
0x10, 0x11, 0x12, 0x13,
0x20, 0x21, 0x22, 0x23,
0x30, 0x31, 0x32, 0x33,
},
},
},
{
"resizeAndCrop 4x4 8x2 Bottom Nearest",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
8, 2,
Bottom,
NearestNeighbor,
&image.NRGBA{
Rect: image.Rect(0, 0, 8, 2),
Stride: 8 * 4,
Pix: []uint8{
0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x3c, 0x3d, 0x3e, 0x3f,
0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
},
{
"resizeAndCrop 4x4 2x8 Top Nearest",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
2, 8,
Top,
NearestNeighbor,
&image.NRGBA{
Rect: image.Rect(0, 0, 2, 8),
Stride: 2 * 4,
Pix: []uint8{
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
},
},
},
{
"resizeAndCrop 4x4 4x4 TopRight Box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
4, 4,
TopRight,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 4, 4),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got := resizeAndCrop(tc.src, tc.w, tc.h, tc.a, tc.f)
if !compareNRGBA(got, tc.want, 0) {
t.Fatalf("got result %#v want %#v", got, tc.want)
}
})
}
}
func TestCropAndResize(t *testing.T) {
testCases := []struct {
name string
src image.Image
w, h int
a Anchor
f ResampleFilter
want *image.NRGBA
}{
{
"cropAndResize 4x4 2x2 Center Nearest",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
2, 2,
Center,
NearestNeighbor,
&image.NRGBA{
Rect: image.Rect(0, 0, 2, 2),
Stride: 2 * 4,
Pix: []uint8{
0x14, 0x15, 0x16, 0x17, 0x1c, 0x1d, 0x1e, 0x1f,
0x34, 0x35, 0x36, 0x37, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
},
{
"cropAndResize 4x4 1x4 TopLeft Nearest",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
1, 4,
TopLeft,
NearestNeighbor,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 4),
Stride: 1 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03,
0x10, 0x11, 0x12, 0x13,
0x20, 0x21, 0x22, 0x23,
0x30, 0x31, 0x32, 0x33,
},
},
},
{
"cropAndResize 4x4 8x2 Bottom Nearest",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
8, 2,
Bottom,
NearestNeighbor,
&image.NRGBA{
Rect: image.Rect(0, 0, 8, 2),
Stride: 8 * 4,
Pix: []uint8{
0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x3c, 0x3d, 0x3e, 0x3f,
0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
},
{
"cropAndResize 4x4 2x8 Top Nearest",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
2, 8,
Top,
NearestNeighbor,
&image.NRGBA{
Rect: image.Rect(0, 0, 2, 8),
Stride: 2 * 4,
Pix: []uint8{
0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07,
0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07,
0x14, 0x15, 0x16, 0x17, 0x14, 0x15, 0x16, 0x17,
0x14, 0x15, 0x16, 0x17, 0x14, 0x15, 0x16, 0x17,
0x24, 0x25, 0x26, 0x27, 0x24, 0x25, 0x26, 0x27,
0x24, 0x25, 0x26, 0x27, 0x24, 0x25, 0x26, 0x27,
0x34, 0x35, 0x36, 0x37, 0x34, 0x35, 0x36, 0x37,
0x34, 0x35, 0x36, 0x37, 0x34, 0x35, 0x36, 0x37,
},
},
},
{
"cropAndResize 4x4 4x4 TopRight Box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 3, 3),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
4, 4,
TopRight,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 4, 4),
Stride: 4 * 4,
Pix: []uint8{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got := cropAndResize(tc.src, tc.w, tc.h, tc.a, tc.f)
if !compareNRGBA(got, tc.want, 0) {
t.Fatalf("got result %#v want %#v", got, tc.want)
}
})
}
}
func TestThumbnail(t *testing.T) {
testCases := []struct {
name string
src image.Image
w, h int
f ResampleFilter
want *image.NRGBA
}{
{
"Thumbnail 6x2 1x1 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 5, 1),
Stride: 6 * 4,
Pix: []uint8{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
},
},
1, 1,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 1),
Stride: 1 * 4,
Pix: []uint8{0x55, 0x55, 0x55, 0xc0},
},
},
{
"Thumbnail 2x6 1x1 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 1, 5),
Stride: 2 * 4,
Pix: []uint8{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
},
},
1, 1,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 1),
Stride: 1 * 4,
Pix: []uint8{0x55, 0x55, 0x55, 0xc0},
},
},
{
"Thumbnail 1x3 2x2 box",
&image.NRGBA{
Rect: image.Rect(-1, -1, 0, 2),
Stride: 1 * 4,
Pix: []uint8{
0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0xff,
},
},
2, 2,
Box,
&image.NRGBA{
Rect: image.Rect(0, 0, 2, 2),
Stride: 2 * 4,
Pix: []uint8{
0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
},
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got := Thumbnail(tc.src, tc.w, tc.h, tc.f)
if !compareNRGBA(got, tc.want, 0) {
t.Fatalf("got result %#v want %#v", got, tc.want)
}
})
}
}
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
}
var f ResampleFilter
switch filter {
case "NearestNeighbor":
f = NearestNeighbor
case "Linear":
f = Linear
case "CatmullRom":
f = CatmullRom
case "Lanczos":
f = Lanczos
}
var img image.Image
switch format {
case "JPEG":
img = testdataBranchesJPG
case "PNG":
img = testdataBranchesPNG
}
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)
}
})
}
}
}
}
func BenchmarkFill(b *testing.B) {
for _, dir := range []string{"Vertical", "Horizontal"} {
for _, filter := range []string{"NearestNeighbor", "Linear", "CatmullRom", "Lanczos"} {
for _, format := range []string{"JPEG", "PNG"} {
var width, height int
switch dir {
case "Vertical":
width = 100
height = 1000
case "Horizontal":
width = 1000
height = 100
}
var f ResampleFilter
switch filter {
case "NearestNeighbor":
f = NearestNeighbor
case "Linear":
f = Linear
case "CatmullRom":
f = CatmullRom
case "Lanczos":
f = Lanczos
}
var img image.Image
switch format {
case "JPEG":
img = testdataBranchesJPG
case "PNG":
img = testdataBranchesPNG
}
b.Run(fmt.Sprintf("%s %s %s", dir, filter, format), func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
Fill(img, width, height, Center, f)
}
})
}
}
}
}