1package fileop
2
3import (
4 "math"
5 "time"
6
7 "github.com/barasher/go-exiftool"
8
9 "git.sr.ht/~gabrielgio/img/pkg/components/media"
10)
11
12func ReadExif(path string) (*media.MediaEXIF, error) {
13 et, err := exiftool.NewExiftool()
14 if err != nil {
15 return nil, err
16 }
17 defer et.Close()
18
19 newExif := &media.MediaEXIF{}
20 fileInfo := et.ExtractMetadata(path)[0]
21
22 // Get description
23 description, err := fileInfo.GetString("ImageDescription")
24 if err == nil {
25 newExif.Description = &description
26 }
27
28 // Get camera model
29 model, err := fileInfo.GetString("Model")
30 if err == nil {
31 newExif.Camera = &model
32 }
33
34 // Get Camera make
35 make, err := fileInfo.GetString("Make")
36 if err == nil {
37 newExif.Maker = &make
38 }
39
40 // Get Image Size
41 width, err := fileInfo.GetFloat("ImageWidth")
42 if err == nil {
43 newExif.Width = &width
44 }
45
46 height, err := fileInfo.GetFloat("ImageHeight")
47 if err == nil {
48 newExif.Height = &height
49 }
50
51 // Get lens
52 lens, err := fileInfo.GetString("LensModel")
53 if err == nil {
54 newExif.Lens = &lens
55 }
56
57 //Get time of photo
58 createDateKeys := []string{
59 "CreationDate",
60 "DateTimeOriginal",
61 "CreateDate",
62 "TrackCreateDate",
63 "MediaCreateDate",
64 "FileCreateDate",
65 "ModifyDate",
66 "TrackModifyDate",
67 "MediaModifyDate",
68 "FileModifyDate",
69 }
70 for _, createDateKey := range createDateKeys {
71 date, err := fileInfo.GetString(createDateKey)
72 if err == nil {
73 layout := "2006:01:02 15:04:05"
74 dateTime, err := time.Parse(layout, date)
75 if err == nil {
76 newExif.DateShot = &dateTime
77 } else {
78 layoutWithOffset := "2006:01:02 15:04:05+02:00"
79 dateTime, err = time.Parse(layoutWithOffset, date)
80 if err == nil {
81 newExif.DateShot = &dateTime
82 }
83 }
84 break
85 }
86 }
87
88 // Get exposure time
89 exposureTime, err := fileInfo.GetFloat("ExposureTime")
90 if err == nil {
91 newExif.Exposure = &exposureTime
92 }
93
94 // Get aperture
95 aperture, err := fileInfo.GetFloat("Aperture")
96 if err == nil {
97 newExif.Aperture = &aperture
98 }
99
100 // Get ISO
101 iso, err := fileInfo.GetInt("ISO")
102 if err == nil {
103 newExif.Iso = &iso
104 }
105
106 // Get focal length
107 focalLen, err := fileInfo.GetFloat("FocalLength")
108 if err == nil {
109 newExif.FocalLength = &focalLen
110 }
111
112 // Get flash info
113 flash, err := fileInfo.GetInt("Flash")
114 if err == nil {
115 newExif.Flash = &flash
116 }
117
118 // Get orientation
119 orientation, err := fileInfo.GetInt("Orientation")
120 if err == nil {
121 newExif.Orientation = &orientation
122 }
123
124 // Get exposure program
125 expProgram, err := fileInfo.GetInt("ExposureProgram")
126 if err == nil {
127 newExif.ExposureProgram = &expProgram
128 }
129
130 // GPS coordinates - longitude
131 longitudeRaw, err := fileInfo.GetFloat("GPSLongitude")
132 if err == nil {
133 newExif.GPSLongitude = &longitudeRaw
134 }
135
136 // GPS coordinates - latitude
137 latitudeRaw, err := fileInfo.GetFloat("GPSLatitude")
138 if err == nil {
139 newExif.GPSLatitude = &latitudeRaw
140 }
141
142 sanitizeEXIF(newExif)
143
144 return newExif, nil
145}
146
147// isFloatReal returns true when the float value represents a real number
148// (different than +Inf, -Inf or NaN)
149func isFloatReal(v float64) bool {
150 if math.IsInf(v, 1) {
151 return false
152 } else if math.IsInf(v, -1) {
153 return false
154 } else if math.IsNaN(v) {
155 return false
156 }
157 return true
158}
159
160// sanitizeEXIF removes any EXIF float64 field that is not a real number (+Inf,
161// -Inf or Nan)
162func sanitizeEXIF(exif *media.MediaEXIF) {
163 if exif.Exposure != nil && !isFloatReal(*exif.Exposure) {
164 exif.Exposure = nil
165 }
166 if exif.Aperture != nil && !isFloatReal(*exif.Aperture) {
167 exif.Aperture = nil
168 }
169 if exif.FocalLength != nil && !isFloatReal(*exif.FocalLength) {
170 exif.FocalLength = nil
171 }
172 if (exif.GPSLatitude != nil && !isFloatReal(*exif.GPSLatitude)) ||
173 (exif.GPSLongitude != nil && !isFloatReal(*exif.GPSLongitude)) {
174 exif.GPSLatitude = nil
175 exif.GPSLongitude = nil
176 }
177}