go-exif/exif.go

96 lines
2.2 KiB
Go

package exif
import (
"fmt"
"errors"
"bytes"
"encoding/binary"
"github.com/dsoprea/go-logging"
)
var (
exifLogger = log.NewLogger("exif.exif")
ErrNotExif = errors.New("not exif data")
)
type Exif struct {
}
func NewExif() *Exif {
return new(Exif)
}
func (e *Exif) IsExif(data []byte) (ok bool) {
if bytes.Compare(data[:6], []byte("Exif\000\000")) == 0 {
return true
}
return false
}
func (e *Exif) Parse(data []byte) (err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()
if e.IsExif(data) == false {
// TODO(dustin): !! Debugging.
fmt.Printf("AppData doesn't look like EXIF. BYTES=(%d)\n", len(data))
return ErrNotExif
}
// Good reference:
//
// CIPA DC-008-2016; JEITA CP-3451D
// -> http://www.cipa.jp/std/documents/e/DC-008-Translation-2016-E.pdf
fmt.Printf("AppData DOES look like EXIF. BYTES=(%d)\n", len(data))
byteOrderSignature := data[6:8]
byteOrder := IfdByteOrder(BigEndianByteOrder)
if string(byteOrderSignature) == "II" {
byteOrder = IfdByteOrder(LittleEndianByteOrder)
} else if string(byteOrderSignature) != "MM" {
log.Panicf("byte-order not recognized: [%v]", byteOrderSignature)
}
fmt.Printf("BYTE-ORDER: [%s]\n", byteOrderSignature)
fixedBytes := data[8:10]
if fixedBytes[0] != 0x2a || fixedBytes[1] != 0x00 {
exifLogger.Warningf(nil, "EXIF app-data header fixed-bytes should be 0x002a but are: [%v]", fixedBytes)
// TODO(dustin): Debugging.
fmt.Printf("EXIF app-data header fixed-bytes should be 0x002a but are: [%v]\n", fixedBytes)
return nil
}
firstIfdOffset := uint32(0)
if byteOrder.IsLittleEndian() == true {
firstIfdOffset = binary.LittleEndian.Uint32(data[10:14])
} else {
firstIfdOffset = binary.BigEndian.Uint32(data[10:14])
}
ifd := NewIfd(data, byteOrder)
visitor := func() error {
// TODO(dustin): !! Debugging.
fmt.Printf("IFD visitor.\n")
return nil
}
err = ifd.Scan(visitor, firstIfdOffset)
log.PanicIf(err)
return nil
}