diff --git a/api/scanner/exif/exif_parser_external.go b/api/scanner/exif/exif_parser_external.go index eb6d4d33..29940fea 100644 --- a/api/scanner/exif/exif_parser_external.go +++ b/api/scanner/exif/exif_parser_external.go @@ -2,6 +2,7 @@ package exif import ( "log" + "math" "time" "github.com/barasher/go-exiftool" @@ -28,6 +29,38 @@ func newExiftoolParser() (*externalExifParser, error) { }, nil } +// isFloatReal returns true when the float value represents a real number +// (different than +Inf, -Inf or NaN) +func isFloatReal(v float64) bool { + if math.IsInf(v, 1) { + return false + } else if math.IsInf(v, -1) { + return false + } else if math.IsNaN(v) { + return false + } + return true +} + +// sanitizeEXIF removes any EXIF float64 field that is not a real number (+Inf, +// -Inf or Nan) +func sanitizeEXIF(exif *models.MediaEXIF) { + if exif.Exposure != nil && !isFloatReal(*exif.Exposure) { + exif.Exposure = nil + } + if exif.Aperture != nil && !isFloatReal(*exif.Aperture) { + exif.Aperture = nil + } + if exif.FocalLength != nil && !isFloatReal(*exif.FocalLength) { + exif.FocalLength = nil + } + if (exif.GPSLatitude != nil && !isFloatReal(*exif.GPSLatitude)) || + (exif.GPSLongitude != nil && !isFloatReal(*exif.GPSLongitude)) { + exif.GPSLatitude = nil + exif.GPSLongitude = nil + } +} + func (p *externalExifParser) ParseExif(media_path string) (returnExif *models.MediaEXIF, returnErr error) { // ExifTool - No print conversion mode if p.et == nil { @@ -148,5 +181,6 @@ func (p *externalExifParser) ParseExif(media_path string) (returnExif *models.Me } returnExif = &newExif + sanitizeEXIF(returnExif) return } diff --git a/api/scanner/exif/exif_parser_internal.go b/api/scanner/exif/exif_parser_internal.go index 5897e6e5..1cb8a42f 100644 --- a/api/scanner/exif/exif_parser_internal.go +++ b/api/scanner/exif/exif_parser_internal.go @@ -62,11 +62,12 @@ func (p *internalExifParser) ParseExif(media_path string) (returnExif *models.Me newExif.DateShot = &date_utc } - exposure, err := exifTags.Get(exif.ExposureTime) + exposureTag, err := exifTags.Get(exif.ExposureTime) if err == nil { - exposureFloat, err := exposure.Float(0) + exposureRat, err := exposureTag.Rat(0) if err == nil { - newExif.Exposure = &exposureFloat + exposure, _ := exposureRat.Float64() + newExif.Exposure = &exposure } } diff --git a/api/scanner/exif/exif_test.go b/api/scanner/exif/exif_test.go index 538d7206..e586c2c6 100644 --- a/api/scanner/exif/exif_test.go +++ b/api/scanner/exif/exif_test.go @@ -51,6 +51,7 @@ func TestExifParsers(t *testing.T) { assert.EqualValues(t, *exif.Camera, "Canon EOS 600D") assert.EqualValues(t, *exif.Maker, "Canon") assert.WithinDuration(t, *exif.DateShot, time.Unix(1336318784, 0).UTC(), time.Minute) + assert.InDelta(t, *exif.Exposure, 1.0/4000.0, 0.0001) assert.EqualValues(t, *exif.Aperture, 6.3) assert.EqualValues(t, *exif.Iso, 800) assert.EqualValues(t, *exif.FocalLength, 300) @@ -66,6 +67,12 @@ func TestExifParsers(t *testing.T) { assert.Nil(t, exif) }, }, + { + path: "./test_data/bad-exif.jpg", + assert: func(t *testing.T, exif *models.MediaEXIF) { + assert.Nil(t, exif.Exposure) + }, + }, } for _, p := range parsers { diff --git a/api/scanner/exif/test_data/bad-exif.jpg b/api/scanner/exif/test_data/bad-exif.jpg new file mode 100644 index 00000000..62e5f900 Binary files /dev/null and b/api/scanner/exif/test_data/bad-exif.jpg differ