From f97cf5b587aa803495dd28b889327baab066cef8 Mon Sep 17 00:00:00 2001 From: mpl <mathieu.lonjaret@gmail.com> Date: Wed, 29 Oct 2014 00:30:02 +0100 Subject: [PATCH] third_party/goexif: bump to 9fb3b23c1aaada5775178242884b75d4f4a330d3 Change-Id: I31f509f32ec6a2fe93cd78a9d09146b0bb6b302e --- .../github.com/rwcarlsen/goexif/exif/exif.go | 88 +++++++++++++++++-- 1 file changed, 83 insertions(+), 5 deletions(-) diff --git a/third_party/github.com/rwcarlsen/goexif/exif/exif.go b/third_party/github.com/rwcarlsen/goexif/exif/exif.go index 5df619393..e8d08ecae 100644 --- a/third_party/github.com/rwcarlsen/goexif/exif/exif.go +++ b/third_party/github.com/rwcarlsen/goexif/exif/exif.go @@ -62,6 +62,69 @@ func RegisterParsers(ps ...Parser) { type parser struct{} +type tiffErrors map[tiffError]string + +func (te tiffErrors) Error() string { + var allErrors []string + for k, v := range te { + allErrors = append(allErrors, fmt.Sprintf("%s: %v\n", stagePrefix[k], v)) + } + return strings.Join(allErrors, "\n") +} + +// IsCriticalError, given the error returned by Decode, reports whether the +// returned *Exif may contain usable information. +func IsCriticalError(err error) bool { + _, ok := err.(tiffErrors) + return !ok +} + +// IsExifError reports whether the error happened while decoding the EXIF +// sub-IFD. +func IsExifError(err error) bool { + if te, ok := err.(tiffErrors); ok { + _, isExif := te[loadExif] + return isExif + } + return false +} + +// IsGPSError reports whether the error happened while decoding the GPS sub-IFD. +func IsGPSError(err error) bool { + if te, ok := err.(tiffErrors); ok { + _, isGPS := te[loadExif] + return isGPS + } + return false +} + +// IsInteroperabilityError reports whether the error happened while decoding the +// Interoperability sub-IFD. +func IsInteroperabilityError(err error) bool { + if te, ok := err.(tiffErrors); ok { + _, isInterop := te[loadInteroperability] + return isInterop + } + return false +} + +type tiffError int + +const ( + loadExif tiffError = iota + loadGPS + loadInteroperability +) + +var stagePrefix = map[tiffError]string{ + loadExif: "loading EXIF sub-IFD", + loadGPS: "loading GPS sub-IFD", + loadInteroperability: "loading Interoperability sub-IFD", +} + +// Parse reads data from the tiff data in x and populates the tags +// in x. If parsing a sub-IFD fails, the error is recorded and +// parsing continues with the remaining sub-IFDs. func (p *parser) Parse(x *Exif) error { x.LoadTags(x.Tiff.Dirs[0], exifFields, false) @@ -70,15 +133,23 @@ func (p *parser) Parse(x *Exif) error { x.LoadTags(x.Tiff.Dirs[1], thumbnailFields, false) } + te := make(tiffErrors) + // recurse into exif, gps, and interop sub-IFDs if err := loadSubDir(x, ExifIFDPointer, exifFields); err != nil { - return err + te[loadExif] = err.Error() } if err := loadSubDir(x, GPSInfoIFDPointer, gpsFields); err != nil { - return err + te[loadGPS] = err.Error() } - return loadSubDir(x, InteroperabilityIFDPointer, interopFields) + if err := loadSubDir(x, InteroperabilityIFDPointer, interopFields); err != nil { + te[loadInteroperability] = err.Error() + } + if len(te) > 0 { + return te + } + return nil } func loadSubDir(x *Exif, ptr FieldName, fieldMap map[uint16]FieldName) error { @@ -95,11 +166,11 @@ func loadSubDir(x *Exif, ptr FieldName, fieldMap map[uint16]FieldName) error { _, err = r.Seek(offset, 0) if err != nil { - return errors.New("exif: seek to sub-IFD failed: " + err.Error()) + return fmt.Errorf("exif: seek to sub-IFD %s failed: %v", ptr, err) } subDir, _, err := tiff.DecodeDir(r, x.Tiff.Order) if err != nil { - return errors.New("exif: sub-IFD decode failed: " + err.Error()) + return fmt.Errorf("exif: sub-IFD %s decode failed: %v", ptr, err) } x.LoadTags(subDir, fieldMap, false) return nil @@ -117,6 +188,8 @@ type Exif struct { // 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. @@ -194,6 +267,11 @@ func Decode(r io.Reader) (*Exif, error) { for i, p := range parsers { if err := p.Parse(x); err != nil { + if _, ok := err.(tiffErrors); ok { + return x, err + } + // This should never happen, as Parse always returns a tiffError + // for now, but that could change. return x, fmt.Errorf("exif: parser %v failed (%v)", i, err) } }