from PIL import Image from PIL.ExifTags import TAGS, GPSTAGS import os import math """ Copyright (c) 2025 by Robert Strutts License: MIT """ def get_exif_data(image_path): """Get EXIF data from image file""" try: with Image.open(image_path) as img: exif_data = img._getexif() if exif_data is not None: return {TAGS.get(tag, tag): value for tag, value in exif_data.items()} except (AttributeError, IOError, KeyError, IndexError) as e: print(f"Error reading EXIF data: {e}") return None def get_camera_info(exif): if not exif: return None camera_info = { 'Make': exif.get('Make', 'Unknown'), 'Model': exif.get('Model', 'Unknown') } # Some cameras store model in 'Camera Model Name' instead if camera_info['Model'] == 'Unknown': camera_info['Model'] = exif.get('Camera Model Name', 'Unknown') return camera_info def get_gps_info(exif_data): """Extract GPS information from EXIF data""" if not exif_data or 'GPSInfo' not in exif_data: return None gps_info = {} for key in exif_data['GPSInfo'].keys(): decode = GPSTAGS.get(key, key) gps_info[decode] = exif_data['GPSInfo'][key] return gps_info def convert_to_degrees(value): """Convert GPS coordinates stored in EXIF to degrees in decimal format""" d, m, s = value return d + (m / 60.0) + (s / 3600.0) def get_lat_lon(gps_info): """Get latitude and longitude from GPSInfo dictionary""" if not gps_info: return None, None try: lat_ref = gps_info.get('GPSLatitudeRef', 'N') lat = gps_info.get('GPSLatitude') lon_ref = gps_info.get('GPSLongitudeRef', 'E') lon = gps_info.get('GPSLongitude') if lat and lon: lat_degrees = convert_to_degrees(lat) if lat_ref == 'S': lat_degrees = -lat_degrees lon_degrees = convert_to_degrees(lon) if lon_ref == 'W': lon_degrees = -lon_degrees return lat_degrees, lon_degrees except (TypeError, AttributeError) as e: print(f"Error converting coordinates: {e}") return None, None import math def haversine_distance_feet(coord1, coord2): """ Calculate the Haversine distance between two coordinates in feet. Returns: float: distance in feet """ # Earth radius in meters R = 6371000 lat1, lon1 = math.radians(coord1[0]), math.radians(coord1[1]) lat2, lon2 = math.radians(coord2[0]), math.radians(coord2[1]) dlat = lat2 - lat1 dlon = lon2 - lon1 a = (math.sin(dlat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2)**2) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) # Distance in meters distance_meters = R * c # Convert to feet return distance_meters * 3.28084 """ Example points: point1 = (40.7484, -73.9857) # Empire State Building coordinates (approximately) point2 = (40.748405, -73.985685) # about 10 feet northeast of point1 """ def get_coordinates_from_image(image_path): """Main function to get coordinates from image file""" exif_data = get_exif_data(image_path) if not exif_data: print("No EXIF data found in image.") return None gps_info = get_gps_info(exif_data) if not gps_info: print("No GPS information found in EXIF data.") return None camera_info = get_camera_info(exif_data) latitude, longitude = get_lat_lon(gps_info) if latitude is not None and longitude is not None: return (camera_info, latitude, longitude) else: print("Could not extract valid coordinates.") return None