h2non / bimg

Go package for fast high-level image processing powered by libvips C library
https://pkg.go.dev/github.com/h2non/bimg?tab=doc
MIT License
2.62k stars 339 forks source link

AutoRotate doesn't work with HEIC files #358

Open tonimelisma opened 3 years ago

tonimelisma commented 3 years ago

The AutoRotate() function only works on JPEG, not HEIC files even though both files have EXIF tags and bimg successfully detects and parses the EXIF tag also on the HEIFCfile.

Running the code below gives:

xyz:  jpeg : 6
xyz:  heif : 6

Indicating it correctly detects the EXIF orientation. However, it just doesn't rotate the picture.

Reproducible with all JPEG and HEIC files I have.



import (
    "fmt"
    "os"

    "github.com/h2non/bimg"
)

func checkError(e error) {
    if e != nil {
        fmt.Fprintln(os.Stderr, e)
    }
}

func transform(source string, dest string) {
    buffer, err := bimg.Read(source)

    image := bimg.NewImage(buffer)

    imageMetadata, err := bimg.Metadata(buffer)
    fmt.Println("xyz: ", imageMetadata.Type, ":", imageMetadata.EXIF.Orientation)

    _, err = image.Thumbnail(200)
    checkError(err)

    _, err = image.Convert(bimg.JPEG)
    checkError(err)

    newImage, err := image.AutoRotate()
    checkError(err)

    bimg.Write(dest, newImage)
}

func main() {
    transform("input1.jpg", "output1.jpg")
    transform("input2.heic", "output2.jpg")
}```
tonimelisma commented 3 years ago

I'm guessing there must be some automatic rotation happening behind the scenes. I can't find anything in the documentation.

Taking a JPEG with orientation 6 (90 degrees CCW) and: 1) Converting it to JPEG with no explicit rotation or autorotation, still automatically rotates the picture data 90 degrees CW yet keeps the EXIF tag as-is, causing the picture to be shown 90 degrees CW when viewing in program that autorotates picture 2) Converting it to JPEG and autorotating it, actually rotates it 180 degrees, maintaining EXIF data, picture is shown 180 degrees rotated 3) Converting it to JPEG and rotating it 180 degrees, actually rotates it 90 degrees CCW, maintaining EXIF data, picture is shown 90 degrees CCW rotated

Same transformations with similar HEIF image (orientation 6), causes same outcomes.

You can find the test scripts here:

https://github.com/tonimelisma/bimg-autorotate-test

If I don't use the fluent interface, but instead chain the bimg operations as follows:

buffer, err := bimg.Read(source)
checkError(err)

newImage1, err := bimg.NewImage(buffer).AutoRotate()
checkError(err)

newImage2, err := bimg.NewImage(newImage1).Thumbnail(200)
checkError(err)

newImage3, err := bimg.NewImage(newImage2).Convert(bimg.JPEG)
checkError(err)

bimg.Write(destination, newImage3)

The JPEG pictures get autorotated by an extra 90 degrees CW, while EXIF data is corrected (orientation 1), showing pictures 90 degrees CW while HEIF pictures get rotated 90 degrees CCW, EXIF data not corrected (still orientation 6), showing pictures 90 degrees CCW.

tonimelisma commented 3 years ago

This was all on Ubuntu 20.04 with libvips 8.9.1, libjpeg 8c and libheif 1.6.1.

Running the same repo on my Macbook with vips 8.10.1, libheif 1.9.1 and libjpeg 9d gives completely different results.

For JPEG, autorotation rotates 180 degrees (90 degrees CW too much) and squashes EXIF (to orientation 1), no rotation rotates 90 degrees yet leaves EXIF intact (orient 6) making picture appear 90 degrees CW in viewer, and 180 degree rotation causes picture to be rotated 90 degrees CCW, leaving EXIF intact. 😄

For HEIF, no rotation and autorotation both autorotate picture correctly and squash EXIF (to orientation 1), while rotate 180 degrees first autorotates and then correctly rotates picture 180 degrees, squashing EXIF.

Running the same repo on an upgrade Ubuntu 20.10 with libvips 8.10.2, libjpeg 8c and libheif 1.8.0 again gives completely different results, which seem mostly random so I won't take the time to write them here.

Considering the same code on different platforms causes completely different outcomes I guess this is a bug in bimg?

LarsFronius commented 3 years ago

Hi @tonimelisma - would you mind trying with libvips 8.10? I think it has a number of fixes around autoorientation. I think bimg actually doesn't handle autorotation itself but passes it on to libvips.

tonimelisma commented 3 years ago

Hey @LarsFronius! Can you please read all three messages by me above, I am using libvips 8.10.2 also. I've mostly moved on to govips.