77 lines
2.3 KiB
Python
77 lines
2.3 KiB
Python
import datetime
|
|
from fractions import Fraction
|
|
from typing import Union
|
|
|
|
import piexif
|
|
|
|
"""
|
|
Inspiration: https://gist.github.com/c060604/8a51f8999be12fc2be498e9ca56adc72
|
|
"""
|
|
|
|
|
|
def to_deg(value, loc):
|
|
"""convert decimal coordinates into degrees, munutes and seconds tuple
|
|
|
|
Keyword arguments: value is float gps-value, loc is direction list ["S", "N"] or ["W", "E"]
|
|
return: tuple like (25, 13, 48.343 ,'N')
|
|
"""
|
|
if value < 0:
|
|
loc_value = loc[0]
|
|
elif value > 0:
|
|
loc_value = loc[1]
|
|
else:
|
|
loc_value = ""
|
|
abs_value = abs(value)
|
|
deg = int(abs_value)
|
|
t1 = (abs_value - deg) * 60
|
|
min = int(t1)
|
|
sec = round((t1 - min) * 60, 5)
|
|
return deg, min, sec, loc_value
|
|
|
|
|
|
def change_to_rational(number):
|
|
"""convert a number to rantional
|
|
|
|
Keyword arguments: number
|
|
return: tuple like (1, 2), (numerator, denominator)
|
|
"""
|
|
f = Fraction(str(number))
|
|
return f.numerator, f.denominator
|
|
|
|
|
|
def generate_geotags(lat: float, lon: float, alt: Union[int, float], timestamp_obj: datetime.datetime, original_exif: dict):
|
|
lat_deg = to_deg(lat, ["S", "N"])
|
|
lng_deg = to_deg(lon, ["W", "E"])
|
|
|
|
exiv_lat = (change_to_rational(lat_deg[0]), change_to_rational(lat_deg[1]), change_to_rational(lat_deg[2]))
|
|
exiv_lng = (change_to_rational(lng_deg[0]), change_to_rational(lng_deg[1]), change_to_rational(lng_deg[2]))
|
|
|
|
# Convert date and time to the format required by EXIF
|
|
datestamp = timestamp_obj.strftime("%Y:%m:%d")
|
|
timestamp = (change_to_rational(timestamp_obj.hour), change_to_rational(timestamp_obj.minute), change_to_rational(timestamp_obj.second))
|
|
|
|
if alt < 0:
|
|
altitude_ref = 1
|
|
altitude = abs(alt)
|
|
else:
|
|
altitude_ref = 0
|
|
altitude = alt
|
|
|
|
gps_ifd = {
|
|
piexif.GPSIFD.GPSVersionID: (2, 0, 0, 0),
|
|
piexif.GPSIFD.GPSAltitudeRef: altitude_ref,
|
|
piexif.GPSIFD.GPSAltitude: change_to_rational(round(altitude)),
|
|
piexif.GPSIFD.GPSLatitudeRef: lat_deg[3],
|
|
piexif.GPSIFD.GPSLatitude: exiv_lat,
|
|
piexif.GPSIFD.GPSLongitudeRef: lng_deg[3],
|
|
piexif.GPSIFD.GPSLongitude: exiv_lng,
|
|
piexif.GPSIFD.GPSDateStamp: datestamp,
|
|
piexif.GPSIFD.GPSTimeStamp: timestamp,
|
|
}
|
|
gps_exif = {"GPS": gps_ifd}
|
|
|
|
# Update original exif data to include GPS tag.
|
|
original_exif.update(gps_exif)
|
|
|
|
return original_exif
|