mirror of
https://github.com/talgo-cloud/bimg.git
synced 2026-03-07 21:48:13 -08:00
fix(resize): auto rotate image before resize calculus
This commit is contained in:
parent
da1108f1ad
commit
edeb809cc1
3 changed files with 50 additions and 20 deletions
27
resize.go
27
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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
23
vips.go
23
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))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue