From 1e5b2cfe0230846ecf5593fd2f3d6b24a39ed48a Mon Sep 17 00:00:00 2001 From: songjiayang Date: Fri, 10 Nov 2023 13:31:53 +0800 Subject: [PATCH] vips crop support (#382) Signed-off-by: songjiayang --- vips/conversion.c | 6 ++++++ vips/conversion.go | 12 ++++++++++++ vips/conversion.h | 2 ++ vips/image.go | 10 ++++++++++ vips/image_golden_test.go | 9 +++++++++ 5 files changed, 39 insertions(+) diff --git a/vips/conversion.c b/vips/conversion.c index 9fbf111b..1862620d 100644 --- a/vips/conversion.c +++ b/vips/conversion.c @@ -223,6 +223,12 @@ int smartcrop(VipsImage *in, VipsImage **out, int width, int height, NULL); } +int crop(VipsImage *in, VipsImage **out, int left, int top, + int width, int height) { + return vips_crop(in, out, left, top, width, height, + NULL); +} + int flatten_image(VipsImage *in, VipsImage **out, double r, double g, double b) { if (is_16bit(in->Type)) { diff --git a/vips/conversion.go b/vips/conversion.go index 7ad5d19b..67e11925 100644 --- a/vips/conversion.go +++ b/vips/conversion.go @@ -274,6 +274,18 @@ func vipsSmartCrop(in *C.VipsImage, width int, height int, interesting Interesti return out, nil } +// http://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-crop +func vipsCrop(in *C.VipsImage, left int, top int, width int, height int) (*C.VipsImage, error) { + incOpCounter("crop") + var out *C.VipsImage + + if err := C.crop(in, &out, C.int(left), C.int(top), C.int(width), C.int(height)); err != 0 { + return nil, handleImageError(out) + } + + return out, nil +} + // https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-rot func vipsRotate(in *C.VipsImage, angle Angle) (*C.VipsImage, error) { incOpCounter("rot") diff --git a/vips/conversion.h b/vips/conversion.h index cfc9f110..bf978a93 100644 --- a/vips/conversion.h +++ b/vips/conversion.h @@ -33,6 +33,8 @@ int autorot_image(VipsImage *in, VipsImage **out); int zoom_image(VipsImage *in, VipsImage **out, int xfac, int yfac); int smartcrop(VipsImage *in, VipsImage **out, int width, int height, int interesting); +int crop(VipsImage *in, VipsImage **out, int left, int top, + int width, int height); int bandjoin(VipsImage **in, VipsImage **out, int n); int bandjoin_const(VipsImage *in, VipsImage **out, double constants[], int n); diff --git a/vips/image.go b/vips/image.go index 429ddd30..774f7e88 100644 --- a/vips/image.go +++ b/vips/image.go @@ -1845,6 +1845,16 @@ func (r *ImageRef) SmartCrop(width int, height int, interesting Interesting) err return nil } +// Crop will crop the image based on coordinate and box size +func (r *ImageRef) Crop(left int, top int, width int, height int) error { + out, err := vipsCrop(r.image, left, top, width, height) + if err != nil { + return err + } + r.setImage(out) + return nil +} + // Label overlays a label on top of the image func (r *ImageRef) Label(labelParams *LabelParams) error { out, err := labelImage(r.image, labelParams) diff --git a/vips/image_golden_test.go b/vips/image_golden_test.go index 9f88c196..d6ea9e4a 100644 --- a/vips/image_golden_test.go +++ b/vips/image_golden_test.go @@ -565,6 +565,15 @@ func TestImage_SmartCrop(t *testing.T) { }, nil) } +func TestImage_Crop(t *testing.T) { + goldenTest(t, resources+"jpg-24bit.jpg", func(img *ImageRef) error { + return img.Crop(10, 10, 60, 80) + }, func(result *ImageRef) { + assert.Equal(t, 60, result.Width()) + assert.Equal(t, 80, result.Height()) + }, nil) +} + func TestImage_Replicate(t *testing.T) { goldenTest(t, resources+"jpg-24bit.jpg", func(img *ImageRef) error { return img.Replicate(3, 2)