purrpic/gps_location.py

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))