package fileop import ( "math" "time" "github.com/barasher/go-exiftool" "git.sr.ht/~gabrielgio/img/pkg/components/media" ) 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 } }