diff --git a/resizer.go b/resizer.go index 02ebf88..65edca3 100644 --- a/resizer.go +++ b/resizer.go @@ -263,9 +263,19 @@ func extractOrEmbedImage(image *C.VipsImage, o Options) (*C.VipsImage, error) { switch { case o.Gravity == GravitySmart, o.SmartCrop: - image, err = vipsSmartCrop(image, o.Width, o.Height) + // it's already at an appropriate size, return immediately + if inWidth <= o.Width && inHeight <= o.Height { + break + } + width := int(math.Min(float64(inWidth), float64(o.Width))) + height := int(math.Min(float64(inHeight), float64(o.Height))) + image, err = vipsSmartCrop(image, width, height) break case o.Crop: + // it's already at an appropriate size, return immediately + if inWidth <= o.Width && inHeight <= o.Height { + break + } width := int(math.Min(float64(inWidth), float64(o.Width))) height := int(math.Min(float64(inHeight), float64(o.Height))) left, top := calculateCrop(inWidth, inHeight, o.Width, o.Height, o.Gravity) diff --git a/resizer_test.go b/resizer_test.go index 4b2d4a1..7dff7ab 100644 --- a/resizer_test.go +++ b/resizer_test.go @@ -590,6 +590,76 @@ func TestIfBothSmartCropOptionsAreIdentical(t *testing.T) { } } +func TestSkipCropIfTooSmall(t *testing.T) { + testCases := [] struct { + name string + options Options + } { + { + name: "smart crop", + options: Options{ + Width: 140, + Height: 140, + Crop: true, + Gravity: GravitySmart, + }, + }, + { + name: "centre crop", + options: Options{ + Width: 140, + Height: 140, + Crop: true, + Gravity: GravityCentre, + }, + }, + { + name: "embed", + options: Options{ + Width: 140, + Height: 140, + Embed: true, + }, + }, + { + name: "extract", + options: Options{ + Top: 0, + Left: 0, + AreaWidth: 140, + AreaHeight: 140, + }, + }, + } + + testImg, err := os.Open("testdata/test_bad_extract_area.jpg") + if err != nil { + t.Fatal(err) + } + defer testImg.Close() + + testImgByte, err := ioutil.ReadAll(testImg) + if err != nil { + t.Fatal(err) + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + croppedImage, err := Resize(testImgByte, tc.options) + if err != nil { + t.Fatal(err) + } + + size, _ := Size(croppedImage) + if tc.options.Height-size.Height > 1 || tc.options.Width-size.Width > 1 { + t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height) + } + t.Logf("size for %s is %dx%d", tc.name, size.Width, size.Height) + }) + } +} + func runBenchmarkResize(file string, o Options, b *testing.B) { buf, _ := Read(path.Join("testdata", file)) diff --git a/testdata/test_bad_extract_area.jpg b/testdata/test_bad_extract_area.jpg new file mode 100644 index 0000000..9ce3cd5 Binary files /dev/null and b/testdata/test_bad_extract_area.jpg differ