Proper handling of the EXIF cases.
Kudos to https://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/ Signed-off-by: Yoan Blanc <yoan@dosimple.ch>
BIN
fixtures/exif/Landscape_1.jpg
Normal file
|
After Width: | Height: | Size: 186 KiB |
BIN
fixtures/exif/Landscape_1_out.jpg
Normal file
|
After Width: | Height: | Size: 198 KiB |
BIN
fixtures/exif/Landscape_2.jpg
Normal file
|
After Width: | Height: | Size: 187 KiB |
BIN
fixtures/exif/Landscape_2_out.jpg
Normal file
|
After Width: | Height: | Size: 199 KiB |
BIN
fixtures/exif/Landscape_3.jpg
Normal file
|
After Width: | Height: | Size: 187 KiB |
BIN
fixtures/exif/Landscape_3_out.jpg
Normal file
|
After Width: | Height: | Size: 199 KiB |
BIN
fixtures/exif/Landscape_4.jpg
Normal file
|
After Width: | Height: | Size: 186 KiB |
BIN
fixtures/exif/Landscape_4_out.jpg
Normal file
|
After Width: | Height: | Size: 198 KiB |
BIN
fixtures/exif/Landscape_5.jpg
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
fixtures/exif/Landscape_5_out.jpg
Normal file
|
After Width: | Height: | Size: 204 KiB |
BIN
fixtures/exif/Landscape_6.jpg
Normal file
|
After Width: | Height: | Size: 189 KiB |
BIN
fixtures/exif/Landscape_6_out.jpg
Normal file
|
After Width: | Height: | Size: 204 KiB |
BIN
fixtures/exif/Landscape_7.jpg
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
fixtures/exif/Landscape_7_out.jpg
Normal file
|
After Width: | Height: | Size: 204 KiB |
BIN
fixtures/exif/Landscape_8.jpg
Normal file
|
After Width: | Height: | Size: 189 KiB |
BIN
fixtures/exif/Landscape_8_out.jpg
Normal file
|
After Width: | Height: | Size: 205 KiB |
BIN
fixtures/exif/Portrait_1.jpg
Normal file
|
After Width: | Height: | Size: 153 KiB |
BIN
fixtures/exif/Portrait_1_out.jpg
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
fixtures/exif/Portrait_2.jpg
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
fixtures/exif/Portrait_2_out.jpg
Normal file
|
After Width: | Height: | Size: 165 KiB |
BIN
fixtures/exif/Portrait_3.jpg
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
fixtures/exif/Portrait_3_out.jpg
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
fixtures/exif/Portrait_4.jpg
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
fixtures/exif/Portrait_4_out.jpg
Normal file
|
After Width: | Height: | Size: 165 KiB |
BIN
fixtures/exif/Portrait_5.jpg
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
fixtures/exif/Portrait_5_out.jpg
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
fixtures/exif/Portrait_6.jpg
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
fixtures/exif/Portrait_6_out.jpg
Normal file
|
After Width: | Height: | Size: 174 KiB |
BIN
fixtures/exif/Portrait_7.jpg
Normal file
|
After Width: | Height: | Size: 153 KiB |
BIN
fixtures/exif/Portrait_7_out.jpg
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
fixtures/exif/Portrait_8.jpg
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
fixtures/exif/Portrait_8_out.jpg
Normal file
|
After Width: | Height: | Size: 174 KiB |
|
|
@ -518,7 +518,7 @@ func calculateRotationAndFlip(image *C.VipsImage, angle Angle) (Angle, bool) {
|
|||
break // flip 1
|
||||
case 7:
|
||||
flip = true
|
||||
rotate = D90
|
||||
rotate = D270
|
||||
break // flip 6
|
||||
case 4:
|
||||
flip = true
|
||||
|
|
@ -526,7 +526,7 @@ func calculateRotationAndFlip(image *C.VipsImage, angle Angle) (Angle, bool) {
|
|||
break // flip 3
|
||||
case 5:
|
||||
flip = true
|
||||
rotate = D270
|
||||
rotate = D90
|
||||
break // flip 8
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package bimg
|
|||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"io/ioutil"
|
||||
|
|
@ -393,6 +394,65 @@ func TestResizePngWithTransparency(t *testing.T) {
|
|||
Write("fixtures/transparent_out.png", newImg)
|
||||
}
|
||||
|
||||
func TestRotationAndFlip(t *testing.T) {
|
||||
files := []struct {
|
||||
Name string
|
||||
Angle Angle
|
||||
Flip bool
|
||||
}{
|
||||
{"Landscape_1", 0, false},
|
||||
{"Landscape_2", 0, true},
|
||||
{"Landscape_3", D180, false},
|
||||
{"Landscape_4", D180, true},
|
||||
{"Landscape_5", D90, true},
|
||||
{"Landscape_6", D90, false},
|
||||
{"Landscape_7", D270, true},
|
||||
{"Landscape_8", D270, false},
|
||||
{"Portrait_1", 0, false},
|
||||
{"Portrait_2", 0, true},
|
||||
{"Portrait_3", D180, false},
|
||||
{"Portrait_4", D180, true},
|
||||
{"Portrait_5", D90, true},
|
||||
{"Portrait_6", D90, false},
|
||||
{"Portrait_7", D270, true},
|
||||
{"Portrait_8", D270, false},
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
img, err := os.Open(fmt.Sprintf("fixtures/exif/%s.jpg", file.Name))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(img)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
img.Close()
|
||||
|
||||
image, _, err := loadImage(buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
angle, flip := calculateRotationAndFlip(image, D0)
|
||||
if angle != file.Angle {
|
||||
t.Errorf("Rotation for %v expected to be %v. got %v", file.Name, file.Angle, angle)
|
||||
}
|
||||
if flip != file.Flip {
|
||||
t.Errorf("Flip for %v expected to be %v. got %v", file.Name, file.Flip, flip)
|
||||
}
|
||||
|
||||
// Visual debugging.
|
||||
newImg, err := Resize(buf, Options{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Write(fmt.Sprintf("fixtures/exif/%s_out.jpg", file.Name), newImg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIfBothSmartCropOptionsAreIdentical(t *testing.T) {
|
||||
if !(VipsMajorVersion >= 8 && VipsMinorVersion > 4) {
|
||||
t.Skipf("Skipping this test, libvips doesn't meet version requirement %s > 8.4", VipsVersion)
|
||||
|
|
|
|||