Metadata: Ensure the altitude is not out of range and fix logs #3182

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer 2023-02-09 11:51:26 +01:00
parent eb6a7a82cc
commit ef6e3d3f9d
15 changed files with 211 additions and 54 deletions

View file

@ -239,6 +239,8 @@ func (m *Photo) String() string {
func (m *Photo) FirstOrCreate() *Photo {
if err := m.Create(); err == nil {
return m
} else {
log.Tracef("photo: %s in %s (create)", err, m.String())
}
return FindPhoto(*m)

View file

@ -16,7 +16,7 @@ import (
)
// SetCoordinates changes the photo lat, lng and altitude if not empty and from an acceptable source.
func (m *Photo) SetCoordinates(lat, lng float32, altitude int, source string) {
func (m *Photo) SetCoordinates(lat, lng float32, altitude float64, source string) {
m.SetAltitude(altitude, source)
if lat == 0.0 && lng == 0.0 {
@ -33,8 +33,10 @@ func (m *Photo) SetCoordinates(lat, lng float32, altitude int, source string) {
}
// SetAltitude sets the photo altitude if not empty and from an acceptable source.
func (m *Photo) SetAltitude(altitude int, source string) {
if altitude == 0 && source != SrcManual {
func (m *Photo) SetAltitude(altitude float64, source string) {
a := clean.Altitude(altitude)
if a == 0 && source != SrcManual {
return
}
@ -42,7 +44,7 @@ func (m *Photo) SetAltitude(altitude int, source string) {
return
}
m.PhotoAltitude = altitude
m.PhotoAltitude = a
}
// UnknownLocation tests if the photo has an unknown location.
@ -69,7 +71,7 @@ func (m *Photo) SetPosition(pos geo.Position, source string, force bool) {
m.PhotoLng = float32(pos.Lng)
m.PlaceSrc = source
m.CellAccuracy = pos.Accuracy
m.SetAltitude(pos.AltitudeInt(), source)
m.SetAltitude(pos.Altitude, source)
log.Debugf("photo: %s %s", m.String(), pos.String())

View file

@ -57,7 +57,7 @@ type Data struct {
GPSLongitude string `meta:"GPSLongitude"`
Lat float32 `meta:"-"`
Lng float32 `meta:"-"`
Altitude int `meta:"GlobalAltitude,GPSAltitude"`
Altitude float64 `meta:"GlobalAltitude,GPSAltitude"`
Width int `meta:"ImageWidth,PixelXDimension,ExifImageWidth,SourceImageWidth"`
Height int `meta:"ImageHeight,ImageLength,PixelYDimension,ExifImageHeight,SourceImageHeight"`
Orientation int `meta:"-"`

View file

@ -18,7 +18,7 @@ func TestData_AspectRatio(t *testing.T) {
Codec: "avc1",
Lat: 1.334,
Lng: 44.567,
Altitude: 5,
Altitude: 5.0,
Width: 500,
Height: 600,
Error: nil,
@ -38,7 +38,7 @@ func TestData_AspectRatio(t *testing.T) {
Codec: "avc1",
Lat: 1.334,
Lng: 44.567,
Altitude: 5,
Altitude: 5.0,
Width: 0,
Height: 600,
Error: nil,

View file

@ -113,7 +113,7 @@ func (data *Data) Exif(fileName string, fileFormat fs.Type, bruteForce bool) (er
}
if gi.Altitude != 0 {
data.Altitude = gi.Altitude
data.Altitude = float64(gi.Altitude)
}
if !gi.Timestamp.IsZero() {

View file

@ -5,6 +5,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/fs"
)
@ -27,7 +28,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 2100, data.Width)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "", data.Exposure)
assert.Equal(t, "", data.CameraMake)
assert.Equal(t, "", data.CameraModel)
@ -55,7 +56,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 2100, data.Width)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "", data.Exposure)
assert.Equal(t, "", data.CameraMake)
assert.Equal(t, "", data.CameraModel)
@ -85,7 +86,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 720, data.Width)
assert.Equal(t, float32(52.45969), data.Lat)
assert.Equal(t, float32(13.321832), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/50", data.Exposure)
assert.Equal(t, "HUAWEI", data.CameraMake)
assert.Equal(t, "ELE-L29", data.CameraModel)
@ -119,7 +120,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 720, data.Width)
assert.Equal(t, float32(51.254852), data.Lat)
assert.Equal(t, float32(7.389468), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/125", data.Exposure)
assert.Equal(t, "Canon", data.CameraMake)
assert.Equal(t, "Canon EOS 50D", data.CameraModel)
@ -151,7 +152,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 240, data.Width)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/2462", data.Exposure)
assert.Equal(t, "GoPro", data.CameraMake)
assert.Equal(t, "HD2", data.CameraModel)
@ -181,7 +182,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, "2018-09-10T12:16:13Z", data.TakenAtLocal.Format("2006-01-02T15:04:05Z"))
assert.Equal(t, float32(34.79745), data.Lat)
assert.Equal(t, float32(134.76463), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/4000", data.Exposure)
assert.Equal(t, "Apple", data.CameraMake)
assert.Equal(t, "iPhone 7", data.CameraModel)
@ -210,7 +211,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 0, data.Width)
assert.Equal(t, float32(-38.405193), data.Lat)
assert.Equal(t, float32(144.18896), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "", data.Exposure)
assert.Equal(t, "", data.CameraMake)
assert.Equal(t, "", data.CameraModel)
@ -247,7 +248,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, "2020-05-15T10:25:45Z", data.TakenAtLocal.Format("2006-01-02T15:04:05Z")) // TODO
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/1100", data.Exposure)
assert.Equal(t, "SAMSUNG", data.CameraMake)
assert.Equal(t, "GT-I9000", data.CameraModel)
@ -269,7 +270,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 955677000, data.TakenNs)
assert.Equal(t, float32(53.12349), data.Lat)
assert.Equal(t, float32(18.00152), data.Lng)
assert.Equal(t, 63, data.Altitude)
assert.Equal(t, 63, clean.Altitude(data.Altitude))
assert.Equal(t, "1/100", data.Exposure)
assert.Equal(t, "Xiaomi", data.CameraMake)
assert.Equal(t, "Mi A1", data.CameraModel)
@ -362,7 +363,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 695326000, data.TakenNs)
assert.Equal(t, float32(48.302776), data.Lat)
assert.Equal(t, float32(8.9275), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/110", data.Exposure)
assert.Equal(t, "HUAWEI", data.CameraMake)
assert.Equal(t, "ELE-L29", data.CameraModel)
@ -392,7 +393,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 7200, data.Width)
assert.Equal(t, float32(59.84083), data.Lat)
assert.Equal(t, float32(30.51), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/1250", data.Exposure)
assert.Equal(t, "SAMSUNG", data.CameraMake)
assert.Equal(t, "SM-C200", data.CameraModel)
@ -424,7 +425,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 65, data.Width)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "", data.Exposure)
assert.Equal(t, "", data.CameraMake)
assert.Equal(t, "", data.CameraModel)
@ -456,7 +457,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 3264, data.Width)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/387", data.Exposure)
assert.Equal(t, "Apple", data.CameraMake)
assert.Equal(t, "iPhone 5s", data.CameraModel)
@ -490,7 +491,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 3648, data.Width)
assert.Equal(t, float32(52.46052), data.Lat)
assert.Equal(t, float32(13.331402), data.Lng)
assert.Equal(t, 84, data.Altitude)
assert.Equal(t, 84, clean.Altitude(data.Altitude))
assert.Equal(t, "1/50", data.Exposure)
assert.Equal(t, "HUAWEI", data.CameraMake)
assert.Equal(t, "ELE-L29", data.CameraModel)
@ -516,7 +517,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 4000, data.Width)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/24", data.Exposure)
assert.Equal(t, "HMD Global", data.CameraMake)
assert.Equal(t, "Nokia X71", data.CameraModel)
@ -537,7 +538,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 4608, data.Width)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/1600", data.Exposure)
assert.Equal(t, "OLYMPUS IMAGING CORP.", data.CameraMake)
assert.Equal(t, "TG-830", data.CameraModel)
@ -585,7 +586,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 600, data.Width)
assert.Equal(t, float32(65.05558), data.Lat)
assert.Equal(t, float32(-16.625702), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/8", data.Exposure)
assert.Equal(t, "NIKON CORPORATION", data.CameraMake)
assert.Equal(t, "NIKON D800E", data.CameraModel)
@ -617,7 +618,7 @@ func TestExif(t *testing.T) {
assert.Equal(t, 600, data.Width)
assert.Equal(t, float32(65.05558), data.Lat)
assert.Equal(t, float32(-16.625702), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/8", data.Exposure)
assert.Equal(t, "NIKON CORPORATION", data.CameraMake)
assert.Equal(t, "NIKON D800E", data.CameraModel)
@ -667,6 +668,19 @@ func TestExif(t *testing.T) {
assert.Equal(t, 1, data.Orientation)
assert.Equal(t, float32(33.640007), data.Lat)
assert.Equal(t, float32(103.48), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
})
t.Run("altitude.jpg", func(t *testing.T) {
data, err := Exif("testdata/altitude.jpg", fs.ImageJPEG, false)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, float32(45.75285), data.Lat)
assert.Equal(t, float32(33.221977), data.Lng)
assert.InEpsilon(t, 4294967284, data.Altitude, 1000)
assert.Equal(t, 0, clean.Altitude(data.Altitude))
})
}

View file

@ -186,7 +186,7 @@ func (data *Data) Exiftool(jsonData []byte, originalName string) (err error) {
if fl := GpsFloatRegexp.FindAllString(data.json["GPSAltitude"], -1); len(fl) != 1 {
// Ignore.
} else if alt, err := strconv.ParseFloat(fl[0], 64); err == nil && alt != 0 {
data.Altitude = int(alt)
data.Altitude = alt
}
}

View file

@ -131,7 +131,7 @@ func (data *Data) GPhoto(jsonData []byte) (err error) {
}
if data.Altitude == 0 {
data.Altitude = int(p.Geo.Altitude)
data.Altitude = p.Geo.Altitude
}
}

View file

@ -6,6 +6,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/projection"
"github.com/photoprism/photoprism/pkg/video"
)
@ -434,7 +435,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "Europe/Berlin", data.TimeZone)
assert.Equal(t, float32(52.508522), data.Lat)
assert.Equal(t, float32(13.443206), data.Lng)
assert.Equal(t, 40, data.Altitude)
assert.Equal(t, 40, clean.Altitude(data.Altitude))
assert.Equal(t, 0, data.Views)
assert.Equal(t, "", data.DocumentID)
@ -463,7 +464,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "Europe/Berlin", data.TimeZone)
assert.Equal(t, float32(52.510796), data.Lat)
assert.Equal(t, float32(13.456387), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, 1118, data.Views)
})
@ -481,7 +482,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "", data.TimeZone)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, 177, data.Views)
})
@ -499,7 +500,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, "Europe/Berlin", data.TimeZone)
assert.Equal(t, float32(52.49967), data.Lat)
assert.Equal(t, float32(13.422334), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, 0, data.Views)
})
@ -541,7 +542,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 7200, data.Width)
assert.Equal(t, float32(59.84083), data.Lat)
assert.Equal(t, float32(30.51), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/1250", data.Exposure)
assert.Equal(t, "SAMSUNG", data.CameraMake)
assert.Equal(t, "SM-C200", data.CameraModel)
@ -572,7 +573,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 1920, data.Width)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "", data.Exposure)
assert.Equal(t, "OLYMPUS DIGITAL CAMERA", data.CameraMake)
assert.Equal(t, "E-PL7", data.CameraModel)
@ -628,7 +629,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 500, data.Width)
assert.Equal(t, float32(52.46052), data.Lat)
assert.Equal(t, float32(13.331403), data.Lng)
assert.Equal(t, 84, data.Altitude)
assert.Equal(t, 84, clean.Altitude(data.Altitude))
assert.Equal(t, "1/50", data.Exposure)
assert.Equal(t, "HUAWEI", data.CameraMake)
assert.Equal(t, "ELE-L29", data.CameraModel)
@ -894,7 +895,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 850, data.Width)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 30, data.Altitude)
assert.Equal(t, 30, clean.Altitude(data.Altitude))
assert.Equal(t, "1/6", data.Exposure)
assert.Equal(t, "Canon", data.CameraMake)
assert.Equal(t, "Canon EOS-1DS", data.CameraModel)
@ -991,7 +992,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 5472, data.Width)
assert.Equal(t, float32(32.843544), data.Lat)
assert.Equal(t, float32(-117.28025), data.Lng)
assert.Equal(t, 18, data.Altitude)
assert.Equal(t, 18, clean.Altitude(data.Altitude))
assert.Equal(t, "1/500", data.Exposure)
assert.Equal(t, "Canon", data.CameraMake)
assert.Equal(t, "Canon EOS 6D", data.CameraModel)
@ -1015,7 +1016,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 5472, data.Width)
assert.Equal(t, float32(32.843544), data.Lat)
assert.Equal(t, float32(-117.28025), data.Lng)
assert.Equal(t, 18, data.Altitude)
assert.Equal(t, 18, clean.Altitude(data.Altitude))
assert.Equal(t, "0.002", data.Exposure)
assert.Equal(t, "Canon", data.CameraMake)
assert.Equal(t, "Canon EOS 6D", data.CameraModel)
@ -1040,7 +1041,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 1920, data.Width)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, 1, data.Orientation)
})
@ -1058,7 +1059,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 1920, data.Width)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, 1, data.Orientation)
})
@ -1082,7 +1083,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 600, data.Width)
assert.Equal(t, float32(65.05558), data.Lat)
assert.Equal(t, float32(-16.625702), data.Lng)
assert.Equal(t, 30, data.Altitude)
assert.Equal(t, 30, clean.Altitude(data.Altitude))
assert.Equal(t, "1/8", data.Exposure)
assert.Equal(t, "NIKON CORPORATION", data.CameraMake)
assert.Equal(t, "NIKON D800E", data.CameraModel)
@ -1115,7 +1116,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 600, data.Width)
assert.Equal(t, float32(65.05558), data.Lat)
assert.Equal(t, float32(-16.625702), data.Lng)
assert.Equal(t, 30, data.Altitude)
assert.Equal(t, 30, clean.Altitude(data.Altitude))
assert.Equal(t, "0.125", data.Exposure)
assert.Equal(t, "NIKON CORPORATION", data.CameraMake)
assert.Equal(t, "NIKON D800E", data.CameraModel)
@ -1148,7 +1149,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 600, data.Width)
assert.Equal(t, float32(65.05558), data.Lat)
assert.Equal(t, float32(-16.625702), data.Lng)
assert.Equal(t, 30, data.Altitude)
assert.Equal(t, 30, clean.Altitude(data.Altitude))
assert.Equal(t, "1/8", data.Exposure)
assert.Equal(t, "NIKON CORPORATION", data.CameraMake)
assert.Equal(t, "NIKON D800E", data.CameraModel)
@ -1182,7 +1183,7 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 49*time.Second, data.Duration)
assert.Equal(t, float32(0), data.Lat)
assert.Equal(t, float32(0), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "", data.Exposure)
assert.Equal(t, "", data.CameraMake)
assert.Equal(t, "", data.CameraModel)
@ -1276,6 +1277,19 @@ func TestJSON(t *testing.T) {
assert.Equal(t, 1, data.Orientation)
assert.Equal(t, float32(33.640007), data.Lat)
assert.Equal(t, float32(103.48), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
})
t.Run("altitude.json", func(t *testing.T) {
data, err := JSON("testdata/altitude.json", "")
if err != nil {
t.Fatal(err)
}
assert.Equal(t, float32(45.75285), data.Lat)
assert.Equal(t, float32(33.221977), data.Lng)
assert.InEpsilon(t, 4294967284, data.Altitude, 1000)
assert.Equal(t, 0, clean.Altitude(data.Altitude))
})
}

BIN
internal/meta/testdata/altitude.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

90
internal/meta/testdata/altitude.json vendored Normal file
View file

@ -0,0 +1,90 @@
[{
"SourceFile": "/go/src/github.com/photoprism/photoprism/storage/originals/issues/3156/2013-08-25_15-54-06.jpg",
"ExifToolVersion": 12.40,
"FileName": "2013-08-25_15-54-06.jpg",
"Directory": "/go/src/github.com/photoprism/photoprism/storage/originals/issues/3156",
"FileSize": 116251,
"FileModifyDate": "2023:02:09 08:14:34+00:00",
"FileAccessDate": "2023:02:09 09:21:51+00:00",
"FileInodeChangeDate": "2023:02:09 08:14:34+00:00",
"FilePermissions": 100664,
"FileType": "JPEG",
"FileTypeExtension": "JPG",
"MIMEType": "image/jpeg",
"JFIFVersion": "1 1",
"ExifByteOrder": "MM",
"Make": "TCT",
"Model": "TCL S950",
"Orientation": 1,
"XResolution": 72,
"YResolution": 72,
"ResolutionUnit": 2,
"Software": "Microsoft Windows Photo Viewer 10.0.19041.1",
"ModifyDate": "2013:08:25 14:54:05",
"YCbCrPositioning": 2,
"ExposureTime": 0.000242,
"FNumber": 2,
"ExposureProgram": 0,
"ISO": 107,
"ExifVersion": "0220",
"DateTimeOriginal": "2013:08:25 14:54:05",
"CreateDate": "2013:08:25 14:54:05",
"ComponentsConfiguration": "1 2 3 0",
"ExposureCompensation": 0,
"MeteringMode": 2,
"LightSource": 255,
"Flash": 0,
"FocalLength": 3.5,
"FlashpixVersion": "0100",
"ColorSpace": 1,
"ExifImageWidth": 4224,
"ExifImageHeight": 3168,
"InteropIndex": "R98",
"InteropVersion": "0100",
"ExposureMode": 0,
"WhiteBalance": 0,
"DigitalZoomRatio": 1,
"SceneCaptureType": 0,
"GPSVersionID": "2 2 0 0",
"GPSLatitudeRef": "N",
"GPSLongitudeRef": "E",
"GPSAltitudeRef": 0,
"GPSTimeStamp": "11:54:03",
"GPSProcessingMethod": "GPS",
"GPSDateStamp": "2013:08:25",
"Padding": "(Binary data 2060 bytes, use -b option to extract)",
"Compression": 6,
"ThumbnailOffset": 5298,
"ThumbnailLength": 1333,
"XMPToolkit": "XMP Core 4.4.0-Exiv2",
"CreatorTool": "Microsoft Windows Photo Viewer 10.0.19041.1",
"MetadataDate": "2013:08:25 14:54:05",
"InstanceID": "uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b",
"Urgency": 0,
"DateTime": "2013:08:25 14:54:05",
"PickLabel": 0,
"ColorLabel": 0,
"CurrentIPTCDigest": "adc6b302dd6e5ec77837307d97fa2f6c",
"CodedCharacterSet": "\u001B%G",
"DateCreated": "2013:08:25",
"TimeCreated": "14:54:05+00:00",
"ImageWidth": 2112,
"ImageHeight": 1584,
"EncodingProcess": 0,
"BitsPerSample": 8,
"ColorComponents": 3,
"YCbCrSubSampling": "2 2",
"Aperture": 2,
"ImageSize": "2112 1584",
"Megapixels": 3.345408,
"ShutterSpeed": 0.000242,
"ThumbnailImage": "(Binary data 1333 bytes, use -b option to extract)",
"GPSAltitude": 4294967284,
"GPSDateTime": "2013:08:25 11:54:03Z",
"GPSLatitude": 45.7528495555556,
"GPSLongitude": 33.2219772222222,
"DateTimeCreated": "2013:08:25 14:54:05+00:00",
"FocalLength35efl": 3.5,
"GPSPosition": "45.7528495555556 33.2219772222222",
"LightValue": 13.9150945354232
}]

View file

@ -699,7 +699,7 @@ func (ind *Index) UserMediaFile(m *MediaFile, o IndexOptions, originalName, phot
} else {
if p := photo.FirstOrCreate(); p == nil {
result.Status = IndexFailed
result.Err = fmt.Errorf("index: %s in %s (find or create photo)", err, logName)
result.Err = fmt.Errorf("index: failed to create %s", logName)
return result
} else {
photo = *p

View file

@ -142,7 +142,7 @@ func TestMediaFile_Exif_JPEG(t *testing.T) {
assert.Equal(t, 200, data.Iso)
assert.Equal(t, float32(-33.45347), data.Lat)
assert.Equal(t, float32(25.764645), data.Lng)
assert.Equal(t, 190, data.Altitude)
assert.Equal(t, 190.0, data.Altitude)
assert.Equal(t, 497, data.Width)
assert.Equal(t, 331, data.Height)
assert.Equal(t, false, data.Flash)
@ -177,7 +177,7 @@ func TestMediaFile_Exif_JPEG(t *testing.T) {
assert.Equal(t, float32(6.644), info.Aperture)
assert.Equal(t, float32(10), info.FNumber)
assert.Equal(t, 200, info.Iso)
assert.Equal(t, 0, info.Altitude)
assert.Equal(t, 0.0, info.Altitude)
assert.Equal(t, 331, info.Width)
assert.Equal(t, 331, info.Height)
assert.Equal(t, true, info.Flash)
@ -224,7 +224,7 @@ func TestMediaFile_Exif_JPEG(t *testing.T) {
assert.Equal(t, 7200, data.Width)
assert.Equal(t, float32(59.84083), data.Lat)
assert.Equal(t, float32(30.51), data.Lng)
assert.Equal(t, 0, data.Altitude)
assert.Equal(t, 0.0, data.Altitude)
assert.Equal(t, "1/1250", data.Exposure)
assert.Equal(t, "SAMSUNG", data.CameraMake)
assert.Equal(t, "SM-C200", data.CameraModel)
@ -261,7 +261,7 @@ func TestMediaFile_Exif_JPEG(t *testing.T) {
assert.Equal(t, 500, data.Width)
assert.Equal(t, float32(52.46052), data.Lat)
assert.Equal(t, float32(13.331402), data.Lng)
assert.Equal(t, 84, data.Altitude)
assert.Equal(t, 84.0, data.Altitude)
assert.Equal(t, "1/50", data.Exposure)
assert.Equal(t, "HUAWEI", data.CameraMake)
assert.Equal(t, "ELE-L29", data.CameraModel)
@ -304,7 +304,7 @@ func TestMediaFile_Exif_DNG(t *testing.T) {
assert.Equal(t, 1000, info.Iso)
assert.Equal(t, float32(0), info.Lat)
assert.Equal(t, float32(0), info.Lng)
assert.Equal(t, 0, info.Altitude)
assert.Equal(t, 0.0, info.Altitude)
assert.Equal(t, false, info.Flash)
assert.Equal(t, "", info.Description)
@ -376,7 +376,7 @@ func TestMediaFile_Exif_HEIC(t *testing.T) {
assert.Equal(t, 20, jpegInfo.Iso)
assert.Equal(t, float32(34.79745), jpegInfo.Lat)
assert.Equal(t, float32(134.76463), jpegInfo.Lng)
assert.Equal(t, 0, jpegInfo.Altitude)
assert.Equal(t, 0.0, jpegInfo.Altitude)
assert.Equal(t, 4032, jpegInfo.Width)
assert.Equal(t, 3024, jpegInfo.Height)
assert.Equal(t, false, jpegInfo.Flash)

10
pkg/clean/altitude.go Normal file
View file

@ -0,0 +1,10 @@
package clean
// Altitude returns the altitude within a maximum range as an integer, or 0 if it is invalid.
func Altitude(a float64) int {
if a < -15000000 || a > 15000000 {
return 0
}
return int(a)
}

View file

@ -0,0 +1,25 @@
package clean
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestAltitude(t *testing.T) {
t.Run("0", func(t *testing.T) {
assert.Equal(t, 0, Altitude(0.0))
})
t.Run("Negative", func(t *testing.T) {
assert.Equal(t, -1234, Altitude(-1234.2))
})
t.Run("Positive", func(t *testing.T) {
assert.Equal(t, 9234, Altitude(9234.4))
})
t.Run("TooLarge", func(t *testing.T) {
assert.Equal(t, 0, Altitude(4294967284))
})
t.Run("TooSmall", func(t *testing.T) {
assert.Equal(t, 0, Altitude(-4294967284))
})
}