Spaces:
Sleeping
Sleeping
Merge branch 'feat/exif-metadata' into test/tests
Browse files- src/input_handling.py +39 -3
src/input_handling.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
from PIL import Image
|
| 2 |
from PIL import ExifTags
|
| 3 |
import re
|
|
@@ -185,14 +186,49 @@ def get_image_datetime(image_file: UploadedFile) -> str | None:
|
|
| 185 |
image = Image.open(image_file)
|
| 186 |
exif_data = image._getexif()
|
| 187 |
if exif_data is not None:
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
return value
|
| 191 |
except Exception as e: # FIXME: what types of exception?
|
| 192 |
st.warning(f"Could not extract date from image metadata. (file: {image_file.name})")
|
| 193 |
# TODO: add to logger
|
| 194 |
return None
|
| 195 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
|
| 197 |
# an arbitrary set of defaults so testing is less painful...
|
| 198 |
# ideally we add in some randomization to the defaults
|
|
|
|
| 1 |
+
from fractions import Fraction
|
| 2 |
from PIL import Image
|
| 3 |
from PIL import ExifTags
|
| 4 |
import re
|
|
|
|
| 186 |
image = Image.open(image_file)
|
| 187 |
exif_data = image._getexif()
|
| 188 |
if exif_data is not None:
|
| 189 |
+
if ExifTags.Base.DateTimeOriginal in exif_data:
|
| 190 |
+
return exif_data.get(ExifTags.Base.DateTimeOriginal)
|
|
|
|
| 191 |
except Exception as e: # FIXME: what types of exception?
|
| 192 |
st.warning(f"Could not extract date from image metadata. (file: {image_file.name})")
|
| 193 |
# TODO: add to logger
|
| 194 |
return None
|
| 195 |
|
| 196 |
+
def decimal_coords(coords:tuple, ref:str) -> Fraction:
|
| 197 |
+
# https://stackoverflow.com/a/73267185
|
| 198 |
+
decimal_degrees = coords[0] + coords[1] / 60 + coords[2] / 3600
|
| 199 |
+
if ref == "S" or ref =='W':
|
| 200 |
+
decimal_degrees = -decimal_degrees
|
| 201 |
+
return decimal_degrees
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
def get_image_latlon(image_file: UploadedFile) -> tuple[float, float] | None:
|
| 205 |
+
"""
|
| 206 |
+
Extracts the latitude and longitude from the EXIF metadata of an uploaded image file.
|
| 207 |
+
|
| 208 |
+
Args:
|
| 209 |
+
image_file (UploadedFile): The uploaded image file from which to extract the latitude and longitude.
|
| 210 |
+
|
| 211 |
+
Returns:
|
| 212 |
+
tuple[float, float]: The latitude and longitude as a tuple if available, otherwise None.
|
| 213 |
+
|
| 214 |
+
Raises:
|
| 215 |
+
Warning: If the latitude and longitude could not be extracted from the image metadata.
|
| 216 |
+
"""
|
| 217 |
+
try:
|
| 218 |
+
image = Image.open(image_file)
|
| 219 |
+
exif_data = image._getexif()
|
| 220 |
+
if exif_data is not None:
|
| 221 |
+
if ExifTags.Base.GPSInfo in exif_data:
|
| 222 |
+
gps_ifd = exif_data.get(ExifTags.Base.GPSInfo)
|
| 223 |
+
|
| 224 |
+
lat = float(decimal_coords(gps_ifd[ExifTags.GPS.GPSLatitude], gps_ifd[ExifTags.GPS.GPSLatitudeRef]))
|
| 225 |
+
lon = float(decimal_coords(gps_ifd[ExifTags.GPS.GPSLongitude], gps_ifd[ExifTags.GPS.GPSLongitudeRef]))
|
| 226 |
+
|
| 227 |
+
return lat, lon
|
| 228 |
+
|
| 229 |
+
except Exception as e: # FIXME: what types of exception?
|
| 230 |
+
st.warning(f"Could not extract latitude and longitude from image metadata. (file: {str(image_file)}")
|
| 231 |
+
|
| 232 |
|
| 233 |
# an arbitrary set of defaults so testing is less painful...
|
| 234 |
# ideally we add in some randomization to the defaults
|