vancauwe commited on
Commit
6662228
·
1 Parent(s): 330b67d

feat: merge dev and into image batch

Browse files
src/input/input_validator.py CHANGED
@@ -3,10 +3,13 @@ import string
3
  import hashlib
4
  import re
5
  import streamlit as st
 
6
 
7
  from PIL import Image
8
  from PIL import ExifTags
9
 
 
 
10
  def generate_random_md5():
11
  # Generate a random string
12
  random_string = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
@@ -59,10 +62,64 @@ def get_image_datetime(image_file):
59
  image = Image.open(image_file)
60
  exif_data = image._getexif()
61
  if exif_data is not None:
62
- for tag, value in exif_data.items():
63
- if ExifTags.TAGS.get(tag) == 'DateTimeOriginal':
64
- return value
65
  except Exception as e: # FIXME: what types of exception?
66
  st.warning(f"Could not extract date from image metadata. (file: {image_file.name})")
67
  # TODO: add to logger
68
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  import hashlib
4
  import re
5
  import streamlit as st
6
+ from fractions import Fraction
7
 
8
  from PIL import Image
9
  from PIL import ExifTags
10
 
11
+ from streamlit.runtime.uploaded_file_manager import UploadedFile
12
+
13
  def generate_random_md5():
14
  # Generate a random string
15
  random_string = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
 
62
  image = Image.open(image_file)
63
  exif_data = image._getexif()
64
  if exif_data is not None:
65
+ if ExifTags.Base.DateTimeOriginal in exif_data:
66
+ return exif_data.get(ExifTags.Base.DateTimeOriginal)
 
67
  except Exception as e: # FIXME: what types of exception?
68
  st.warning(f"Could not extract date from image metadata. (file: {image_file.name})")
69
  # TODO: add to logger
70
+ return None
71
+
72
+ def decimal_coords(coords:tuple, ref:str) -> Fraction:
73
+ """
74
+ Converts coordinates from degrees, minutes, and seconds to decimal degrees.
75
+
76
+ Args:
77
+ coords (tuple): A tuple containing three elements representing degrees, minutes, and seconds.
78
+ ref (str): A string representing the reference direction ('N', 'S', 'E', 'W').
79
+
80
+ Returns:
81
+ Fraction: The coordinates in decimal degrees. Negative if the reference is 'S' or 'W'.
82
+
83
+ Example:
84
+ decimal_coords((40, 26, 46), 'N') -> 40.44611111111111
85
+ decimal_coords((40, 26, 46), 'W') -> -40.44611111111111
86
+ """
87
+ # https://stackoverflow.com/a/73267185
88
+ if ref not in ['N', 'S', 'E', 'W']:
89
+ raise ValueError("Invalid reference direction. Must be 'N', 'S', 'E', or 'W'.")
90
+ if len(coords) != 3:
91
+ raise ValueError("Coordinates must be a tuple of three elements (degrees, minutes, seconds).")
92
+
93
+ decimal_degrees = coords[0] + coords[1] / 60 + coords[2] / 3600
94
+ if ref == "S" or ref =='W':
95
+ decimal_degrees = -decimal_degrees
96
+ return decimal_degrees
97
+
98
+
99
+ def get_image_latlon(image_file: UploadedFile) -> tuple[float, float] | None:
100
+ """
101
+ Extracts the latitude and longitude from the EXIF metadata of an uploaded image file.
102
+
103
+ Args:
104
+ image_file (UploadedFile): The uploaded image file from which to extract the latitude and longitude.
105
+
106
+ Returns:
107
+ tuple[float, float]: The latitude and longitude as a tuple if available, otherwise None.
108
+
109
+ Raises:
110
+ Warning: If the latitude and longitude could not be extracted from the image metadata.
111
+ """
112
+ try:
113
+ image = Image.open(image_file)
114
+ exif_data = image._getexif()
115
+ if exif_data is not None:
116
+ if ExifTags.Base.GPSInfo in exif_data:
117
+ gps_ifd = exif_data.get(ExifTags.Base.GPSInfo)
118
+
119
+ lat = float(decimal_coords(gps_ifd[ExifTags.GPS.GPSLatitude], gps_ifd[ExifTags.GPS.GPSLatitudeRef]))
120
+ lon = float(decimal_coords(gps_ifd[ExifTags.GPS.GPSLongitude], gps_ifd[ExifTags.GPS.GPSLongitudeRef]))
121
+
122
+ return lat, lon
123
+
124
+ except Exception as e: # FIXME: what types of exception?
125
+ st.warning(f"Could not extract latitude and longitude from image metadata. (file: {str(image_file)}")
tests/test_input_handling.py CHANGED
@@ -2,7 +2,7 @@ import pytest
2
  from pathlib import Path
3
 
4
  from input_handling import is_valid_email, is_valid_number
5
- from input_handling import get_image_datetime, get_image_latlon, decimal_coords
6
 
7
  # generate tests for is_valid_email
8
  # - test with valid email
 
2
  from pathlib import Path
3
 
4
  from input_handling import is_valid_email, is_valid_number
5
+ from input.input_validator import get_image_latlon, decimal_coords, get_image_datetime
6
 
7
  # generate tests for is_valid_email
8
  # - test with valid email