diff --git a/resize.go b/resize.go index 3bdb2ea..1623910 100644 --- a/resize.go +++ b/resize.go @@ -32,6 +32,20 @@ func Resize(buf []byte, o Options) ([]byte, error) { debug("Options: %#v", o) + // Auto rotate image based on EXIF orientation header + image, rotated, err := rotateAndFlipImage(image, o) + if err != nil { + return nil, err + } + + // If JPEG image, retrieve the buffer + if rotated && imageType == JPEG && !o.NoAutoRotate { + buf, err = getImageBuffer(image) + if err != nil { + return nil, err + } + } + inWidth := int(image.Xsize) inHeight := int(image.Ysize) @@ -68,12 +82,6 @@ func Resize(buf []byte, o Options) ([]byte, error) { residual = float64(shrink) / factor } - // Explicit or auto rotate image based on EXIF header - image, err = rotateAndFlipImage(image, o) - if err != nil { - return nil, err - } - // Zoom image, if necessary image, err = zoomImage(image, o.Zoom) if err != nil { @@ -249,8 +257,9 @@ func extractOrEmbedImage(image *C.VipsImage, o Options) (*C.VipsImage, error) { return image, err } -func rotateAndFlipImage(image *C.VipsImage, o Options) (*C.VipsImage, error) { +func rotateAndFlipImage(image *C.VipsImage, o Options) (*C.VipsImage, bool, error) { var err error + var rotated bool var direction Direction = -1 if o.NoAutoRotate == false { @@ -264,6 +273,7 @@ func rotateAndFlipImage(image *C.VipsImage, o Options) (*C.VipsImage, error) { } if o.Rotate > 0 { + rotated = true image, err = vipsRotate(image, getAngle(o.Rotate)) } @@ -274,10 +284,11 @@ func rotateAndFlipImage(image *C.VipsImage, o Options) (*C.VipsImage, error) { } if direction != -1 { + rotated = true image, err = vipsFlip(image, direction) } - return image, err + return image, rotated, err } func watermakImage(image *C.VipsImage, w Watermark) (*C.VipsImage, error) { diff --git a/resize_test.go b/resize_test.go index 7b4759a..b359abb 100644 --- a/resize_test.go +++ b/resize_test.go @@ -113,7 +113,7 @@ func TestResizeCustomSizes(t *testing.T) { } func TestRotate(t *testing.T) { - options := Options{Width: 800, Height: 600, Rotate: 270} + options := Options{Width: 800, Height: 600, Rotate: 270, Crop: true} buf, _ := Read("fixtures/test.jpg") newImg, err := Resize(buf, options) @@ -122,19 +122,19 @@ func TestRotate(t *testing.T) { } if DetermineImageType(newImg) != JPEG { - t.Fatal("Image is not jpeg") + t.Error("Image is not jpeg") } size, _ := Size(newImg) - if size.Height != options.Width { - t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height) + if size.Width != options.Width || size.Height != options.Height { + t.Errorf("Invalid image size: %dx%d", size.Width, size.Height) } Write("fixtures/test_rotate_out.jpg", newImg) } -func TestInvalidRotate(t *testing.T) { - options := Options{Width: 800, Height: 600, Rotate: 111} +func TestInvalidRotateDegrees(t *testing.T) { + options := Options{Width: 800, Height: 600, Rotate: 111, Crop: true} buf, _ := Read("fixtures/test.jpg") newImg, err := Resize(buf, options) @@ -143,15 +143,15 @@ func TestInvalidRotate(t *testing.T) { } if DetermineImageType(newImg) != JPEG { - t.Fatal("Image is not jpeg") + t.Errorf("Image is not jpeg") } size, _ := Size(newImg) - if size.Height != options.Width { - t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height) + if size.Width != options.Width || size.Height != options.Height { + t.Errorf("Invalid image size: %dx%d", size.Width, size.Height) } - Write("fixtures/test_invalid_rotate_out.jpg", newImg) + Write("fixtures/test_rotate_invalid_out.jpg", newImg) } func TestCorruptedImage(t *testing.T) { diff --git a/version.go b/version.go index c38f217..bde7c07 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package bimg -const Version = "0.1.23" +const Version = "0.1.24" diff --git a/vips.go b/vips.go index 989b864..0aeb655 100644 --- a/vips.go +++ b/vips.go @@ -341,8 +341,23 @@ func vipsSave(image *C.VipsImage, o vipsSaveOptions) ([]byte, error) { return buf, nil } -func max(x int) int { - return int(math.Max(float64(x), 0)) +func getImageBuffer(image *C.VipsImage) ([]byte, error) { + var ptr unsafe.Pointer + + length := C.size_t(0) + interlace := C.int(0) + quality := C.int(100) + + err := C.int(0) + err = C.vips_jpegsave_bridge(image, &ptr, &length, 1, quality, interlace) + if int(err) != 0 { + return nil, catchVipsError() + } + + defer C.g_free(C.gpointer(ptr)) + defer C.vips_error_clear() + + return C.GoBytes(ptr, C.int(length)), nil } func vipsExtract(image *C.VipsImage, left, top, width, height int) (*C.VipsImage, error) { @@ -484,3 +499,7 @@ func vipsSharpen(image *C.VipsImage, o Sharpen) (*C.VipsImage, error) { } return out, nil } + +func max(x int) int { + return int(math.Max(float64(x), 0)) +}