diff options
author | Christopher Speller <crspeller@gmail.com> | 2018-04-16 05:37:14 -0700 |
---|---|---|
committer | Joram Wilander <jwawilander@gmail.com> | 2018-04-16 08:37:14 -0400 |
commit | 6e2cb00008cbf09e556b00f87603797fcaa47e09 (patch) | |
tree | 3c0eb55ff4226a3f024aad373140d1fb860a6404 /vendor/github.com/rwcarlsen/goexif/exif/exif.go | |
parent | bf24f51c4e1cc6286885460672f7f449e8c6f5ef (diff) | |
download | chat-6e2cb00008cbf09e556b00f87603797fcaa47e09.tar.gz chat-6e2cb00008cbf09e556b00f87603797fcaa47e09.tar.bz2 chat-6e2cb00008cbf09e556b00f87603797fcaa47e09.zip |
Depenancy upgrades and movign to dep. (#8630)
Diffstat (limited to 'vendor/github.com/rwcarlsen/goexif/exif/exif.go')
-rw-r--r-- | vendor/github.com/rwcarlsen/goexif/exif/exif.go | 69 |
1 files changed, 51 insertions, 18 deletions
diff --git a/vendor/github.com/rwcarlsen/goexif/exif/exif.go b/vendor/github.com/rwcarlsen/goexif/exif/exif.go index b420729da..87166ee4e 100644 --- a/vendor/github.com/rwcarlsen/goexif/exif/exif.go +++ b/vendor/github.com/rwcarlsen/goexif/exif/exif.go @@ -201,14 +201,16 @@ type Exif struct { Raw []byte } -// Decode parses EXIF-encoded data from r and returns a queryable Exif -// object. After the exif data section is called and the tiff structure -// decoded, each registered parser is called (in order of registration). If -// one parser returns an error, decoding terminates and the remaining -// parsers are not called. -// The error can be inspected with functions such as IsCriticalError to -// determine whether the returned object might still be usable. +// Decode parses EXIF data from r (a TIFF, JPEG, or raw EXIF block) +// and returns a queryable Exif object. After the EXIF data section is +// called and the TIFF structure is decoded, each registered parser is +// called (in order of registration). If one parser returns an error, +// decoding terminates and the remaining parsers are not called. +// +// The error can be inspected with functions such as IsCriticalError +// to determine whether the returned object might still be usable. func Decode(r io.Reader) (*Exif, error) { + // EXIF data in JPEG is stored in the APP1 marker. EXIF data uses the TIFF // format to store data. // If we're parsing a TIFF image, we don't need to strip away any data. @@ -216,15 +218,14 @@ func Decode(r io.Reader) (*Exif, error) { // marker and also the EXIF header. header := make([]byte, 4) - n, err := r.Read(header) + n, err := io.ReadFull(r, header) if err != nil { - return nil, err - } - if n < len(header) { - return nil, errors.New("exif: short read on header") + return nil, fmt.Errorf("exif: error reading 4 byte header, got %d, %v", n, err) } var isTiff bool + var isRawExif bool + var assumeJPEG bool switch string(header) { case "II*\x00": // TIFF - Little endian (Intel) @@ -232,8 +233,11 @@ func Decode(r io.Reader) (*Exif, error) { case "MM\x00*": // TIFF - Big endian (Motorola) isTiff = true + case "Exif": + isRawExif = true default: // Not TIFF, assume JPEG + assumeJPEG = true } // Put the header bytes back into the reader. @@ -241,9 +245,20 @@ func Decode(r io.Reader) (*Exif, error) { var ( er *bytes.Reader tif *tiff.Tiff + sec *appSec ) - if isTiff { + switch { + case isRawExif: + var header [6]byte + if _, err := io.ReadFull(r, header[:]); err != nil { + return nil, fmt.Errorf("exif: unexpected raw exif header read error") + } + if got, want := string(header[:]), "Exif\x00\x00"; got != want { + return nil, fmt.Errorf("exif: unexpected raw exif header; got %q, want %q", got, want) + } + fallthrough + case isTiff: // Functions below need the IFDs from the TIFF data to be stored in a // *bytes.Reader. We use TeeReader to get a copy of the bytes as a // side-effect of tiff.Decode() doing its work. @@ -251,9 +266,8 @@ func Decode(r io.Reader) (*Exif, error) { tr := io.TeeReader(r, b) tif, err = tiff.Decode(tr) er = bytes.NewReader(b.Bytes()) - } else { + case assumeJPEG: // Locate the JPEG APP1 header. - var sec *appSec sec, err = newAppSec(jpeg_APP1, r) if err != nil { return nil, err @@ -368,8 +382,27 @@ func (x *Exif) DateTime() (time.Time, error) { exifTimeLayout := "2006:01:02 15:04:05" dateStr := strings.TrimRight(string(tag.Val), "\x00") // TODO(bradfitz,mpl): look for timezone offset, GPS time, etc. - // For now, just always return the time.Local timezone. - return time.ParseInLocation(exifTimeLayout, dateStr, time.Local) + timeZone := time.Local + if tz, _ := x.TimeZone(); tz != nil { + timeZone = tz + } + return time.ParseInLocation(exifTimeLayout, dateStr, timeZone) +} + +func (x *Exif) TimeZone() (*time.Location, error) { + // TODO: parse more timezone fields (e.g. Nikon WorldTime). + timeInfo, err := x.Get("Canon.TimeInfo") + if err != nil { + return nil, err + } + if timeInfo.Count < 2 { + return nil, errors.New("Canon.TimeInfo does not contain timezone") + } + offsetMinutes, err := timeInfo.Int(1) + if err != nil { + return nil, err + } + return time.FixedZone("", offsetMinutes*60), nil } func ratFloat(num, dem int64) float64 { @@ -574,7 +607,7 @@ func newAppSec(marker byte, r io.Reader) (*appSec, error) { } dataLenBytes := make([]byte, 2) - for k,_ := range dataLenBytes { + for k, _ := range dataLenBytes { c, err := br.ReadByte() if err != nil { return nil, err |