Spaces:
Running
Running
File size: 4,603 Bytes
55d18b1 8cbe888 55d18b1 8cbe888 55d18b1 8cbe888 55d18b1 8cbe888 5a8836e 8cbe888 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
import random
import string
import hashlib
import re
import streamlit as st
from fractions import Fraction
from PIL import Image
from PIL import ExifTags
from streamlit.runtime.uploaded_file_manager import UploadedFile
def generate_random_md5():
# Generate a random string
random_string = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
# Encode the string and compute its MD5 hash
md5_hash = hashlib.md5(random_string.encode()).hexdigest()
return md5_hash
def is_valid_number(number:str) -> bool:
"""
Check if the given string is a valid number (int or float, sign ok)
Args:
number (str): The string to be checked.
Returns:
bool: True if the string is a valid number, False otherwise.
"""
pattern = r'^[-+]?[0-9]*\.?[0-9]+$'
return re.match(pattern, number) is not None
# Function to validate email address
def is_valid_email(email:str) -> bool:
"""
Validates if the provided email address is in a correct format.
Args:
email (str): The email address to validate.
Returns:
bool: True if the email address is valid, False otherwise.
"""
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return re.match(pattern, email) is not None
# Function to extract date and time from image metadata
def get_image_datetime(image_file):
"""
Extracts the original date and time from the EXIF metadata of an uploaded image file.
Args:
image_file (UploadedFile): The uploaded image file from which to extract the date and time.
Returns:
str: The original date and time as a string if available, otherwise None.
Raises:
Warning: If the date and time could not be extracted from the image metadata.
"""
try:
image = Image.open(image_file)
exif_data = image._getexif()
if exif_data is not None:
if ExifTags.Base.DateTimeOriginal in exif_data:
return exif_data.get(ExifTags.Base.DateTimeOriginal)
except Exception as e: # FIXME: what types of exception?
st.warning(f"Could not extract date from image metadata. (file: {image_file.name})")
# TODO: add to logger
return None
def decimal_coords(coords:tuple, ref:str) -> Fraction:
"""
Converts coordinates from degrees, minutes, and seconds to decimal degrees.
Args:
coords (tuple): A tuple containing three elements representing degrees, minutes, and seconds.
ref (str): A string representing the reference direction ('N', 'S', 'E', 'W').
Returns:
Fraction: The coordinates in decimal degrees. Negative if the reference is 'S' or 'W'.
Example:
decimal_coords((40, 26, 46), 'N') -> 40.44611111111111
decimal_coords((40, 26, 46), 'W') -> -40.44611111111111
"""
# https://stackoverflow.com/a/73267185
if ref not in ['N', 'S', 'E', 'W']:
raise ValueError("Invalid reference direction. Must be 'N', 'S', 'E', or 'W'.")
if len(coords) != 3:
raise ValueError("Coordinates must be a tuple of three elements (degrees, minutes, seconds).")
decimal_degrees = coords[0] + coords[1] / 60 + coords[2] / 3600
if ref == "S" or ref =='W':
decimal_degrees = -decimal_degrees
return decimal_degrees
#def get_image_latlon(image_file: UploadedFile) -> tuple[float, float] | None:
def get_image_latlon(image_file: UploadedFile) :
"""
Extracts the latitude and longitude from the EXIF metadata of an uploaded image file.
Args:
image_file (UploadedFile): The uploaded image file from which to extract the latitude and longitude.
Returns:
tuple[float, float]: The latitude and longitude as a tuple if available, otherwise None.
Raises:
Warning: If the latitude and longitude could not be extracted from the image metadata.
"""
try:
image = Image.open(image_file)
exif_data = image._getexif()
if exif_data is not None:
if ExifTags.Base.GPSInfo in exif_data:
gps_ifd = exif_data.get(ExifTags.Base.GPSInfo)
lat = float(decimal_coords(gps_ifd[ExifTags.GPS.GPSLatitude], gps_ifd[ExifTags.GPS.GPSLatitudeRef]))
lon = float(decimal_coords(gps_ifd[ExifTags.GPS.GPSLongitude], gps_ifd[ExifTags.GPS.GPSLongitudeRef]))
return lat, lon
except Exception as e: # FIXME: what types of exception?
st.warning(f"Could not extract latitude and longitude from image metadata. (file: {str(image_file)}") |