mirror of
https://github.com/talgo-cloud/bimg.git
synced 2026-03-13 09:20:29 -07: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)
|
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)
|
inWidth := int(image.Xsize)
|
||||||
inHeight := int(image.Ysize)
|
inHeight := int(image.Ysize)
|
||||||
|
|
||||||
|
|
@ -68,12 +82,6 @@ func Resize(buf []byte, o Options) ([]byte, error) {
|
||||||
residual = float64(shrink) / factor
|
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
|
// Zoom image, if necessary
|
||||||
image, err = zoomImage(image, o.Zoom)
|
image, err = zoomImage(image, o.Zoom)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -249,8 +257,9 @@ func extractOrEmbedImage(image *C.VipsImage, o Options) (*C.VipsImage, error) {
|
||||||
return image, err
|
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 err error
|
||||||
|
var rotated bool
|
||||||
var direction Direction = -1
|
var direction Direction = -1
|
||||||
|
|
||||||
if o.NoAutoRotate == false {
|
if o.NoAutoRotate == false {
|
||||||
|
|
@ -264,6 +273,7 @@ func rotateAndFlipImage(image *C.VipsImage, o Options) (*C.VipsImage, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.Rotate > 0 {
|
if o.Rotate > 0 {
|
||||||
|
rotated = true
|
||||||
image, err = vipsRotate(image, getAngle(o.Rotate))
|
image, err = vipsRotate(image, getAngle(o.Rotate))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,10 +284,11 @@ func rotateAndFlipImage(image *C.VipsImage, o Options) (*C.VipsImage, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if direction != -1 {
|
if direction != -1 {
|
||||||
|
rotated = true
|
||||||
image, err = vipsFlip(image, direction)
|
image, err = vipsFlip(image, direction)
|
||||||
}
|
}
|
||||||
|
|
||||||
return image, err
|
return image, rotated, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func watermakImage(image *C.VipsImage, w Watermark) (*C.VipsImage, error) {
|
func watermakImage(image *C.VipsImage, w Watermark) (*C.VipsImage, error) {
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ func TestResizeCustomSizes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRotate(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")
|
buf, _ := Read("fixtures/test.jpg")
|
||||||
|
|
||||||
newImg, err := Resize(buf, options)
|
newImg, err := Resize(buf, options)
|
||||||
|
|
@ -122,19 +122,19 @@ func TestRotate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if DetermineImageType(newImg) != JPEG {
|
if DetermineImageType(newImg) != JPEG {
|
||||||
t.Fatal("Image is not jpeg")
|
t.Error("Image is not jpeg")
|
||||||
}
|
}
|
||||||
|
|
||||||
size, _ := Size(newImg)
|
size, _ := Size(newImg)
|
||||||
if size.Height != options.Width {
|
if size.Width != options.Width || size.Height != options.Height {
|
||||||
t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height)
|
t.Errorf("Invalid image size: %dx%d", size.Width, size.Height)
|
||||||
}
|
}
|
||||||
|
|
||||||
Write("fixtures/test_rotate_out.jpg", newImg)
|
Write("fixtures/test_rotate_out.jpg", newImg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvalidRotate(t *testing.T) {
|
func TestInvalidRotateDegrees(t *testing.T) {
|
||||||
options := Options{Width: 800, Height: 600, Rotate: 111}
|
options := Options{Width: 800, Height: 600, Rotate: 111, Crop: true}
|
||||||
buf, _ := Read("fixtures/test.jpg")
|
buf, _ := Read("fixtures/test.jpg")
|
||||||
|
|
||||||
newImg, err := Resize(buf, options)
|
newImg, err := Resize(buf, options)
|
||||||
|
|
@ -143,15 +143,15 @@ func TestInvalidRotate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if DetermineImageType(newImg) != JPEG {
|
if DetermineImageType(newImg) != JPEG {
|
||||||
t.Fatal("Image is not jpeg")
|
t.Errorf("Image is not jpeg")
|
||||||
}
|
}
|
||||||
|
|
||||||
size, _ := Size(newImg)
|
size, _ := Size(newImg)
|
||||||
if size.Height != options.Width {
|
if size.Width != options.Width || size.Height != options.Height {
|
||||||
t.Fatalf("Invalid image size: %dx%d", size.Width, size.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) {
|
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
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func max(x int) int {
|
func getImageBuffer(image *C.VipsImage) ([]byte, error) {
|
||||||
return int(math.Max(float64(x), 0))
|
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) {
|
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
|
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