diff --git a/README.md b/README.md index 5747278..9a7a18a 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ The [install script](https://github.com/lovell/sharp/blob/master/preinstall.sh) - Crop - Rotate - Flip +- Thumbnail - Extract area - Format conversion - EXIF metadata (size, alpha channel, profile, orientation...) diff --git a/image.go b/image.go index 45c7dcf..5889efc 100644 --- a/image.go +++ b/image.go @@ -31,6 +31,16 @@ func (i *Image) Crop(width, height int) ([]byte, error) { return i.Process(options) } +func (i *Image) Thumbnail(pixels int) ([]byte, error) { + options := Options{ + Width: pixels, + Height: pixels, + Crop: true, + Quality: 95, + } + return i.Process(options) +} + func (i *Image) Rotate(a Angle) ([]byte, error) { options := Options{Rotate: a} return i.Process(options) diff --git a/image_test.go b/image_test.go index 1f38610..46ccc52 100644 --- a/image_test.go +++ b/image_test.go @@ -37,6 +37,14 @@ func TestImageFlip(t *testing.T) { Write("fixtures/test_flip_out.jpg", buf) } +func TestImageThumbnail(t *testing.T) { + buf, err := initImage("test.jpg").Thumbnail(100) + if err != nil { + t.Errorf("Cannot process the image: %#v", err) + } + Write("fixtures/test_thumbnail_out.jpg", buf) +} + func TestImageRotate(t *testing.T) { buf, err := initImage("test_flip_out.jpg").Rotate(90) if err != nil { diff --git a/resize.go b/resize.go index 1a59421..89b963e 100644 --- a/resize.go +++ b/resize.go @@ -227,6 +227,7 @@ func imageCalculations(o Options, inWidth, inHeight int) float64 { factor := 1.0 xfactor := float64(inWidth) / float64(o.Width) yfactor := float64(inHeight) / float64(o.Height) + defer debug("Image calculations: %dx%d", o.Width, o.Height) switch { // Fixed width and height @@ -251,8 +252,6 @@ func imageCalculations(o Options, inWidth, inHeight int) float64 { break } - debug("Resolution %dx%d", o.Width, o.Height) - return factor } diff --git a/resize_test.go b/resize_test.go index 88428e0..79749e4 100644 --- a/resize_test.go +++ b/resize_test.go @@ -3,6 +3,7 @@ package bimg import ( "io/ioutil" "os" + "path" "testing" ) @@ -132,3 +133,27 @@ func TestResizePngWithTransparency(t *testing.T) { t.Fatal("Cannot save the image") } } + +func benchmarkResize(file string, o Options, b *testing.B) { + buf, _ := Read(path.Join("fixtures", file)) + + for n := 0; n < b.N; n++ { + Resize(buf, o) + } +} + +func BenchmarkResizeLargeJpeg(b *testing.B) { + options := Options{ + Width: 800, + Height: 600, + } + benchmarkResize("test.jpg", options, b) +} + +func BenchmarkResizePng(b *testing.B) { + options := Options{ + Width: 200, + Height: 200, + } + benchmarkResize("test.png", options, b) +} diff --git a/vips.go b/vips.go index b63a0d0..87805ce 100644 --- a/vips.go +++ b/vips.go @@ -8,6 +8,7 @@ import "C" import ( "errors" + //"fmt" "runtime" "strings" "sync" @@ -65,7 +66,6 @@ func vipsRotate(image *C.struct__VipsImage, angle Angle) (*C.struct__VipsImage, if err != 0 { return nil, catchVipsError() } - defer C.g_object_unref(C.gpointer(out)) return out, nil } @@ -78,7 +78,6 @@ func vipsFlip(image *C.struct__VipsImage, direction Direction) (*C.struct__VipsI if err != 0 { return nil, catchVipsError() } - defer C.g_object_unref(C.gpointer(out)) return out, nil } @@ -158,8 +157,8 @@ func vipsAffine(input *C.struct__VipsImage, residual float64, i Interpolator) (* istring := C.CString(i.String()) interpolator := C.vips_interpolate_new(istring) - defer C.g_object_unref(C.gpointer(input)) defer C.free(unsafe.Pointer(istring)) + defer C.g_object_unref(C.gpointer(input)) // Perform affine transformation err := C.vips_affine_interpolator(input, &image, C.double(residual), 0, 0, C.double(residual), interpolator) @@ -229,9 +228,7 @@ func vipsSave(image *C.struct__VipsImage, o vipsSaveOptions) ([]byte, error) { length := C.size_t(0) err := C.int(0) - // cleanup defer C.g_object_unref(C.gpointer(image)) - defer C.g_free(C.gpointer(ptr)) switch { case o.Type == PNG: @@ -245,11 +242,14 @@ func vipsSave(image *C.struct__VipsImage, o vipsSaveOptions) ([]byte, error) { break } - if err != 0 { + if int(err) != 0 { return nil, catchVipsError() } buf := C.GoBytes(ptr, C.int(length)) + + // Cleanup + C.g_free(C.gpointer(ptr)) C.vips_error_clear() return buf, nil