From 58b2be80a536d39fec6571b2626de07f4cfd5e45 Mon Sep 17 00:00:00 2001 From: Tomas Aparicio Date: Thu, 9 Apr 2015 02:08:07 +0200 Subject: [PATCH] feat(#26): support zoom. several refactors and fixes --- README.md | 6 +++--- image.go | 6 ++++++ image_test.go | 20 +++++++++++++++++--- options.go | 1 + resize.go | 20 +++++++++++++++++--- vips.go | 17 ++++++++++++++--- vips.h | 8 ++++---- 7 files changed, 62 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index c69fa20..9e1071f 100644 --- a/README.md +++ b/README.md @@ -41,10 +41,10 @@ The [install script](https://github.com/lovell/sharp/blob/master/preinstall.sh) - Resize - Enlarge - Crop -- Rotate -- Auto-rotate (based on EXIF orientation) -- Flip +- Rotate (and auto-rotate based on EXIF orientation) +- Flip (and auto-flip based on EXIF metadata) - Flop +- Zoom - Thumbnail - Extract area - Format conversion diff --git a/image.go b/image.go index bf6d03a..ea276f5 100644 --- a/image.go +++ b/image.go @@ -92,6 +92,12 @@ func (i *Image) Watermark(image []byte, left, top int) ([]byte, error) { return i.Process(options) } +// Zoom the image by the given factor +func (i *Image) Zoom(level int) ([]byte, error) { + options := Options{Zoom: level} + return i.Process(options) +} + // Rotate the image by given angle degrees (0, 90, 180 or 270) func (i *Image) Rotate(a Angle) ([]byte, error) { options := Options{Rotate: a} diff --git a/image_test.go b/image_test.go index f5310d1..7564780 100644 --- a/image_test.go +++ b/image_test.go @@ -119,16 +119,30 @@ func TestImageWatermark(t *testing.T) { err = assertSize(buf, 800, 600) if err != nil { - //t.Error(err) + t.Error(err) } - if DetermineImageType(buf) != PNG { - //t.Fatal("Image is not jpeg") + if DetermineImageType(buf) != JPEG { + t.Fatal("Image is not jpeg") } Write("fixtures/test_watermark_out.jpg", buf) } +func TestImageZoom(t *testing.T) { + buf, err := initImage("test.jpg").Zoom(1) + if err != nil { + t.Errorf("Cannot process the image: %#v", err) + } + + err = assertSize(buf, 3360, 2100) + if err != nil { + t.Error(err) + } + + Write("fixtures/test_zoom_out.jpg", buf) +} + func TestImageFlip(t *testing.T) { buf, err := initImage("test.jpg").Flip() if err != nil { diff --git a/options.go b/options.go index e5025ce..d530e51 100644 --- a/options.go +++ b/options.go @@ -71,6 +71,7 @@ type Options struct { Extend int Quality int Compression int + Zoom int Crop bool Enlarge bool Embed bool diff --git a/resize.go b/resize.go index a69b1fd..d0970e8 100644 --- a/resize.go +++ b/resize.go @@ -106,6 +106,12 @@ func Resize(buf []byte, o Options) ([]byte, error) { } } + // Zoom image if necessary + image, err = zoomImage(image, o.Zoom) + if err != nil { + return nil, err + } + // Rotate / flip image if necessary image, err = rotateImage(image, o) if err != nil { @@ -205,23 +211,31 @@ func insertImage(image *C.struct__VipsImage, t ImageType, o Insert, save vipsSav if imageType != t { save.Type = t - debug("Image type insert: %s", save.Type) buf, err := vipsSave(insert, save) if err != nil { return nil, err } + insert, imageType, err = vipsRead(buf) - debug("New type image: %s", imageType) if err != nil { return nil, err } } - debug("Insert images: %#v", insert) + debug("Insert image: %#v", insert) return vipsInsert(image, insert, o.Left, o.Top) } +func zoomImage(image *C.struct__VipsImage, zoom int) (*C.struct__VipsImage, error) { + if zoom == 0 { + return image, nil + } + zoom += 1 + + return vipsZoom(image, zoom) +} + func shrinkImage(image *C.struct__VipsImage, o Options, residual float64, shrink int) (*C.struct__VipsImage, float64, error) { // Use vips_shrink with the integral reduction image, err := vipsShrink(image, shrink) diff --git a/vips.go b/vips.go index daa89d2..32c8fc6 100644 --- a/vips.go +++ b/vips.go @@ -76,7 +76,7 @@ func VipsDebug() { C.im__print_all() } -// Get the allocated memory by vips in bytes +// Get memory info stats from vips func VipsMemory() VipsMemoryInfo { return VipsMemoryInfo{ Memory: int64(C.vips_tracked_get_mem()), @@ -109,14 +109,25 @@ func vipsFlip(image *C.struct__VipsImage, direction Direction) (*C.struct__VipsI return out, nil } +func vipsZoom(image *C.struct__VipsImage, zoom int) (*C.struct__VipsImage, error) { + var out *C.struct__VipsImage + defer C.g_object_unref(C.gpointer(image)) + + err := C.vips_zoom_bridge(image, &out, C.int(zoom), C.int(zoom)) + if err != 0 { + return nil, catchVipsError() + } + + return out, nil +} + func vipsInsert(image *C.struct__VipsImage, sub *C.struct__VipsImage, left, top int) (*C.struct__VipsImage, error) { var out *C.struct__VipsImage - var cache *C.struct__VipsImage defer C.g_object_unref(C.gpointer(image)) defer C.g_object_unref(C.gpointer(sub)) - err = C.vips_insert_bridge(image, sub, &out, C.int(left), C.int(top)) + err := C.vips_insert_bridge(image, sub, &out, C.int(left), C.int(top)) if err != 0 { return nil, catchVipsError() } diff --git a/vips.h b/vips.h index 1813f82..f2c76a5 100644 --- a/vips.h +++ b/vips.h @@ -92,15 +92,15 @@ vips_enum_nick_bridge(VipsImage *image) { }; int -vips_insert_bridge(VipsImage *in, VipsImage *sub, VipsImage **out, int left, int top) +vips_zoom_bridge(VipsImage *in, VipsImage **out, int xfac, int yfac) { - return vips_insert(in, sub, out, left, top, NULL); + return vips_zoom(in, out, xfac, yfac, NULL); }; int -vips_bandjoin2_bridge(VipsImage *in, VipsImage *sub, VipsImage **out) +vips_insert_bridge(VipsImage *in, VipsImage *sub, VipsImage **out, int left, int top) { - return vips_bandjoin2(in, sub, out, NULL); + return vips_insert(in, sub, out, left, top, NULL); }; int