126 lines
3.4 KiB
Python
Executable File
126 lines
3.4 KiB
Python
Executable File
#!/usr/bin/python3
|
|
"""!@brief: helper routines for dealing with GPS Data from exif
|
|
@author: Luzia Christiane Tesar
|
|
@date Mi 12. Aug 13:12:33 CEST 2026
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import requests
|
|
import json
|
|
from datetime import datetime
|
|
from PIL import Image
|
|
from PIL.ExifTags import TAGS, GPSTAGS
|
|
|
|
REV_API_URL = "https://nominatim.openstreetmap.org/reverse"
|
|
headers = {"User-Agent": "Purrrrrpic :3"}
|
|
|
|
|
|
def get_exif_data(image):
|
|
"""Returns a dictionary from the exif data of an PIL Image item. Also converts the GPS Tags"""
|
|
exif_data = {}
|
|
try:
|
|
info = image._getexif()
|
|
if info:
|
|
for tag, value in info.items():
|
|
decoded = TAGS.get(tag, tag)
|
|
if decoded == "GPSInfo":
|
|
gps_data = {}
|
|
for t in value:
|
|
sub_decoded = GPSTAGS.get(t, t)
|
|
gps_data[sub_decoded] = value[t]
|
|
|
|
exif_data[decoded] = gps_data
|
|
else:
|
|
exif_data[decoded] = value
|
|
|
|
except:
|
|
pass
|
|
return exif_data
|
|
|
|
|
|
def _get_if_exist(data, key):
|
|
if key in data:
|
|
return data[key]
|
|
|
|
return None
|
|
|
|
|
|
def _convert_to_degress(value):
|
|
"""Helper function to convert the GPS coordinates stored in the EXIF to degress in float format"""
|
|
d = float(value[0])
|
|
|
|
m = float(value[1])
|
|
|
|
s = float(value[2])
|
|
|
|
return d + (m / 60.0) + (s / 3600.0)
|
|
|
|
|
|
def get_lat_lon(exif_data):
|
|
"""Returns the latitude and longitude, if available, from the provided exif_data (obtained through get_exif_data above)"""
|
|
lat = None
|
|
lon = None
|
|
|
|
if "GPSInfo" in exif_data:
|
|
gps_info = exif_data["GPSInfo"]
|
|
gps_latitude = _get_if_exist(gps_info, "GPSLatitude")
|
|
gps_latitude_ref = _get_if_exist(gps_info, "GPSLatitudeRef")
|
|
gps_longitude = _get_if_exist(gps_info, "GPSLongitude")
|
|
gps_longitude_ref = _get_if_exist(gps_info, "GPSLongitudeRef")
|
|
|
|
if gps_latitude and gps_latitude_ref and gps_longitude and gps_longitude_ref:
|
|
lat = _convert_to_degress(gps_latitude)
|
|
if gps_latitude_ref != "N":
|
|
lat = 0 - lat
|
|
|
|
lon = _convert_to_degress(gps_longitude)
|
|
if gps_longitude_ref != "E":
|
|
lon = 0 - lon
|
|
|
|
return lat, lon
|
|
|
|
def getReverseAPI(lat, lon):
|
|
try:
|
|
payload = {"lat": lat, "lon": lon, "format": "json", "addressdetails": "1"}
|
|
r = requests.get(REV_API_URL, headers=headers, params=payload)
|
|
return r.json()
|
|
except requests.exceptions.HTTPError as errh:
|
|
print ("Http Error:",errh)
|
|
except requests.exceptions.ConnectionError as errc:
|
|
print ("Error Connecting:",errc)
|
|
except requests.exceptions.Timeout as errt:
|
|
print ("Timeout Error:",errt)
|
|
except requests.exceptions.RequestException as err:
|
|
print ("OOps: Something Else",err)
|
|
|
|
def getCity(geo):
|
|
return geo["address"]["city"] or ""
|
|
|
|
|
|
def getCountry(geo):
|
|
return geo["address"]["country"] or ""
|
|
|
|
|
|
def getRoad(geo):
|
|
return geo["address"]["road"] or ""
|
|
|
|
|
|
def getHouseNumber(geo):
|
|
return geo["address"]["house_number"] or ""
|
|
|
|
|
|
def getPostCode(geo):
|
|
return geo["address"]["postcode"] or ""
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
img = Image.open("eh23/IMG20260403174725.jpg")
|
|
exifdata = get_exif_data(img)
|
|
lat, lon = get_lat_lon(exifdata)
|
|
geo = getReverseAPI(lat, lon)
|
|
print(getCity(geo))
|
|
print(getCountry(geo))
|
|
print(getRoad(geo))
|