aboutsummaryrefslogtreecommitdiff
path: root/pkg/fileop
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/fileop')
-rw-r--r--pkg/fileop/exif.go165
1 files changed, 165 insertions, 0 deletions
diff --git a/pkg/fileop/exif.go b/pkg/fileop/exif.go
new file mode 100644
index 0000000..48e495c
--- /dev/null
+++ b/pkg/fileop/exif.go
@@ -0,0 +1,165 @@
+package fileop
+
+import (
+ "math"
+ "time"
+
+ "git.sr.ht/~gabrielgio/img/pkg/components/media"
+ "github.com/barasher/go-exiftool"
+)
+
+func ReadExif(path string) (*media.MediaEXIF, error) {
+ et, err := exiftool.NewExiftool()
+ if err != nil {
+ return nil, err
+ }
+ defer et.Close()
+
+ newExif := &media.MediaEXIF{}
+ fileInfo := et.ExtractMetadata(path)[0]
+
+ // Get description
+ description, err := fileInfo.GetString("ImageDescription")
+ if err == nil {
+ newExif.Description = &description
+ }
+
+ // Get camera model
+ model, err := fileInfo.GetString("Model")
+ if err == nil {
+ newExif.Camera = &model
+ }
+
+ // Get Camera make
+ make, err := fileInfo.GetString("Make")
+ if err == nil {
+ newExif.Maker = &make
+ }
+
+ // Get lens
+ lens, err := fileInfo.GetString("LensModel")
+ if err == nil {
+ newExif.Lens = &lens
+ }
+
+ //Get time of photo
+ createDateKeys := []string{
+ "CreationDate",
+ "DateTimeOriginal",
+ "CreateDate",
+ "TrackCreateDate",
+ "MediaCreateDate",
+ "FileCreateDate",
+ "ModifyDate",
+ "TrackModifyDate",
+ "MediaModifyDate",
+ "FileModifyDate",
+ }
+ for _, createDateKey := range createDateKeys {
+ date, err := fileInfo.GetString(createDateKey)
+ if err == nil {
+ layout := "2006:01:02 15:04:05"
+ dateTime, err := time.Parse(layout, date)
+ if err == nil {
+ newExif.DateShot = &dateTime
+ } else {
+ layoutWithOffset := "2006:01:02 15:04:05+02:00"
+ dateTime, err = time.Parse(layoutWithOffset, date)
+ if err == nil {
+ newExif.DateShot = &dateTime
+ }
+ }
+ break
+ }
+ }
+
+ // Get exposure time
+ exposureTime, err := fileInfo.GetFloat("ExposureTime")
+ if err == nil {
+ newExif.Exposure = &exposureTime
+ }
+
+ // Get aperture
+ aperture, err := fileInfo.GetFloat("Aperture")
+ if err == nil {
+ newExif.Aperture = &aperture
+ }
+
+ // Get ISO
+ iso, err := fileInfo.GetInt("ISO")
+ if err == nil {
+ newExif.Iso = &iso
+ }
+
+ // Get focal length
+ focalLen, err := fileInfo.GetFloat("FocalLength")
+ if err == nil {
+ newExif.FocalLength = &focalLen
+ }
+
+ // Get flash info
+ flash, err := fileInfo.GetInt("Flash")
+ if err == nil {
+ newExif.Flash = &flash
+ }
+
+ // Get orientation
+ orientation, err := fileInfo.GetInt("Orientation")
+ if err == nil {
+ newExif.Orientation = &orientation
+ }
+
+ // Get exposure program
+ expProgram, err := fileInfo.GetInt("ExposureProgram")
+ if err == nil {
+ newExif.ExposureProgram = &expProgram
+ }
+
+ // GPS coordinates - longitude
+ longitudeRaw, err := fileInfo.GetFloat("GPSLongitude")
+ if err == nil {
+ newExif.GPSLongitude = &longitudeRaw
+ }
+
+ // GPS coordinates - latitude
+ latitudeRaw, err := fileInfo.GetFloat("GPSLatitude")
+ if err == nil {
+ newExif.GPSLatitude = &latitudeRaw
+ }
+
+ sanitizeEXIF(newExif)
+
+ return newExif, 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 *media.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
+ }
+}