diff --git a/README.md b/README.md index 8b351b1..5747278 100644 --- a/README.md +++ b/README.md @@ -3,16 +3,13 @@ Small but featured Go library for blazing fast image processing based on [libvips](https://github.com/jcupitt/libvips) using C bindings. bimg is designed to be a small and efficient library with a specific but useful and generic set of features. -It uses internally libvips, which is typically 4x faster than using the quickest ImageMagick and GraphicsMagick settings or Go native `image` package, and in some cases it's even 8x faster processing JPEG images. -bimg can read JPEG, PNG, WEBP, TIFF and Magick formats and it can output to JPEG, PNG and WEBP. - -It supports common [image transformation](#supported-image-operations) operations such as crop, resize, rotate... and conversion into multiple formats. +It uses internally libvips, which is typically 4x faster than using the quickest ImageMagick and GraphicsMagick settings or Go native `image` package, and in some cases it's even 8x faster processing JPEG images. It can read JPEG, PNG, WEBP, TIFF and Magick formats and it can output to JPEG, PNG and WEBP. It supports common [image transformation](#supported-image-operations) operations such as crop, resize, rotate... and conversion into multiple formats. To getting start take a look to the [examples](#examples) and [programmatic API](https://godoc.org/github.com/h2non/bimg) documentation. bimg was heavily inspired in [sharp](https://github.com/lovell/sharp), a great node.js package for image processing build by [Lovell Fuller](https://github.com/lovell). -**Note**: bimg is still a beta package. Pull requests and issues are highly appreciated +**Note**: bimg is still beta. Pull requests and issues are highly appreciated ## Prerequisites @@ -43,8 +40,8 @@ The [install script](https://github.com/lovell/sharp/blob/master/preinstall.sh) - Rotate - Flip - Extract area +- Format conversion - EXIF metadata (size, alpha channel, profile, orientation...) -- Format conversion ## Performance diff --git a/resize.go b/resize.go index e1cfd7a..1a59421 100644 --- a/resize.go +++ b/resize.go @@ -62,7 +62,7 @@ func Resize(buf []byte, o Options) ([]byte, error) { // Try to use libjpeg shrink-on-load if imageType == JPEG && shrink >= 2 { - tmpImage, factor, err := shrinkJpegImage(buf, factor, shrink) + tmpImage, factor, err := shrinkJpegImage(buf, image, factor, shrink) if err != nil { return nil, err } @@ -197,7 +197,7 @@ func shrinkImage(image *C.struct__VipsImage, o Options, residual float64, shrink return image, residual, nil } -func shrinkJpegImage(buf []byte, factor float64, shrink int) (*C.struct__VipsImage, float64, error) { +func shrinkJpegImage(buf []byte, input *C.struct__VipsImage, factor float64, shrink int) (*C.struct__VipsImage, float64, error) { var image *C.struct__VipsImage var err error shrinkOnLoad := 1 @@ -217,7 +217,7 @@ func shrinkJpegImage(buf []byte, factor float64, shrink int) (*C.struct__VipsIma // Reload input using shrink-on-load if shrinkOnLoad > 1 { - image, err = vipsShrinkJpeg(buf, shrinkOnLoad) + image, err = vipsShrinkJpeg(buf, input, shrinkOnLoad) } return image, factor, err diff --git a/vips.go b/vips.go index fb415af..b63a0d0 100644 --- a/vips.go +++ b/vips.go @@ -59,9 +59,9 @@ func Shutdown() { func vipsRotate(image *C.struct__VipsImage, angle Angle) (*C.struct__VipsImage, error) { var out *C.struct__VipsImage + defer C.g_object_unref(C.gpointer(image)) err := C.vips_rotate(image, &out, C.int(angle)) - C.g_object_unref(C.gpointer(image)) if err != 0 { return nil, catchVipsError() } @@ -72,9 +72,9 @@ func vipsRotate(image *C.struct__VipsImage, angle Angle) (*C.struct__VipsImage, func vipsFlip(image *C.struct__VipsImage, direction Direction) (*C.struct__VipsImage, error) { var out *C.struct__VipsImage + defer C.g_object_unref(C.gpointer(image)) err := C.vips_flip_bridge(image, &out, C.int(direction)) - C.g_object_unref(C.gpointer(image)) if err != 0 { return nil, catchVipsError() } @@ -106,9 +106,9 @@ func vipsRead(buf []byte) (*C.struct__VipsImage, ImageType, error) { func vipsExtract(image *C.struct__VipsImage, left, top, width, height int) (*C.struct__VipsImage, error) { var buf *C.struct__VipsImage + defer C.g_object_unref(C.gpointer(image)) err := C.vips_extract_area_bridge(image, &buf, C.int(left), C.int(top), C.int(width), C.int(height)) - C.g_object_unref(C.gpointer(image)) if err != 0 { return nil, catchVipsError() } @@ -116,11 +116,11 @@ func vipsExtract(image *C.struct__VipsImage, left, top, width, height int) (*C.s return buf, nil } -func vipsShrinkJpeg(buf []byte, shrink int) (*C.struct__VipsImage, error) { +func vipsShrinkJpeg(buf []byte, input *C.struct__VipsImage, shrink int) (*C.struct__VipsImage, error) { var image *C.struct__VipsImage + defer C.g_object_unref(C.gpointer(input)) err := C.vips_jpegload_buffer_shrink(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), &image, C.int(shrink)) - C.g_object_unref(C.gpointer(image)) if err != 0 { return nil, catchVipsError() } @@ -130,9 +130,9 @@ func vipsShrinkJpeg(buf []byte, shrink int) (*C.struct__VipsImage, error) { func vipsShrink(input *C.struct__VipsImage, shrink int) (*C.struct__VipsImage, error) { var image *C.struct__VipsImage + defer C.g_object_unref(C.gpointer(input)) err := C.vips_shrink_0(input, &image, C.double(float64(shrink)), C.double(float64(shrink))) - C.g_object_unref(C.gpointer(image)) if err != 0 { return nil, catchVipsError() } @@ -142,9 +142,9 @@ func vipsShrink(input *C.struct__VipsImage, shrink int) (*C.struct__VipsImage, e func vipsEmbed(input *C.struct__VipsImage, left, top, width, height, extend int) (*C.struct__VipsImage, error) { var image *C.struct__VipsImage + defer C.g_object_unref(C.gpointer(input)) err := C.vips_embed_bridge(input, &image, C.int(left), C.int(top), C.int(width), C.int(height), C.int(extend)) - C.g_object_unref(C.gpointer(image)) if err != 0 { return nil, catchVipsError() } @@ -158,10 +158,11 @@ 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)) + // Perform affine transformation err := C.vips_affine_interpolator(input, &image, C.double(residual), 0, 0, C.double(residual), interpolator) - C.g_object_unref(C.gpointer(image)) - C.free(unsafe.Pointer(istring)) if err != 0 { return nil, catchVipsError() }