76 lines
1.9 KiB
Go
76 lines
1.9 KiB
Go
package imaging
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
)
|
|
|
|
const (
|
|
tiffOrientationTag = 0x0112
|
|
tiffTypeShort = 3
|
|
tiffHeaderSize = 8
|
|
tiffEntrySize = 12
|
|
tiffMagic = 42
|
|
uprightOrientation = 1
|
|
maxOrientation = 8
|
|
)
|
|
|
|
var exifHeader = []byte("Exif\x00\x00")
|
|
|
|
func exifOrientation(payload []byte) (uint16, bool) {
|
|
tiff := bytes.TrimPrefix(payload, exifHeader)
|
|
if len(tiff) < tiffHeaderSize {
|
|
return 0, false
|
|
}
|
|
var order binary.ByteOrder
|
|
switch string(tiff[:2]) {
|
|
case "II":
|
|
order = binary.LittleEndian
|
|
case "MM":
|
|
order = binary.BigEndian
|
|
default:
|
|
return 0, false
|
|
}
|
|
if order.Uint16(tiff[2:]) != tiffMagic {
|
|
return 0, false
|
|
}
|
|
ifd := int(order.Uint32(tiff[4:]))
|
|
if ifd < tiffHeaderSize || ifd+2 > len(tiff) {
|
|
return 0, false
|
|
}
|
|
count := int(order.Uint16(tiff[ifd:]))
|
|
for i := range count {
|
|
entry := ifd + 2 + i*tiffEntrySize
|
|
if entry+tiffEntrySize > len(tiff) {
|
|
return 0, false
|
|
}
|
|
if order.Uint16(tiff[entry:]) != tiffOrientationTag || order.Uint16(tiff[entry+2:]) != tiffTypeShort {
|
|
continue
|
|
}
|
|
value := order.Uint16(tiff[entry+8:])
|
|
if value < uprightOrientation || value > maxOrientation {
|
|
return 0, false
|
|
}
|
|
return value, true
|
|
}
|
|
return 0, false
|
|
}
|
|
|
|
func needsOrientation(orientation uint16) bool {
|
|
return orientation > uprightOrientation
|
|
}
|
|
|
|
func orientationOnlyTIFF(orientation uint16) []byte {
|
|
tiff := make([]byte, 0, tiffHeaderSize+2+tiffEntrySize+4)
|
|
tiff = append(tiff, 'M', 'M')
|
|
tiff = binary.BigEndian.AppendUint16(tiff, tiffMagic)
|
|
tiff = binary.BigEndian.AppendUint32(tiff, tiffHeaderSize)
|
|
tiff = binary.BigEndian.AppendUint16(tiff, 1)
|
|
tiff = binary.BigEndian.AppendUint16(tiff, tiffOrientationTag)
|
|
tiff = binary.BigEndian.AppendUint16(tiff, tiffTypeShort)
|
|
tiff = binary.BigEndian.AppendUint32(tiff, 1)
|
|
tiff = binary.BigEndian.AppendUint16(tiff, orientation)
|
|
tiff = binary.BigEndian.AppendUint16(tiff, 0)
|
|
return binary.BigEndian.AppendUint32(tiff, 0)
|
|
}
|