gpx-to-geotags/main.py

58 lines
2.4 KiB
Python

import argparse
from pathlib import Path
import gpxpy
import piexif
import pytz
from PIL import Image
from lib.geotags import generate_geotags
from lib.gpx import get_closest_point
from lib.image import get_image_timestamp
from lib.time import get_local_timezone
def main(args):
with open(args.gpx, 'r') as gpxfile:
gpx = gpxpy.parse(gpxfile)
for file in args.photos.glob('*'):
if file.name.lower().endswith(('.jpg', '.jpeg')):
img = Image.open(file)
timestamp = get_image_timestamp(img, args.timezone)
del img
if not timestamp:
print(f'FAIL - "{file.name}" does not have a timestamp.')
continue
point = get_closest_point(gpx, timestamp, args.max_diff)
if not point:
point_forced = get_closest_point(gpx, timestamp, 99999999999999999999999999)
print(f'FAIL - Could not match image "{file.name}" @ {timestamp}. Closest point: {point_forced.latitude},{point_forced.longitude} @ {point_forced.time.astimezone(pytz.timezone(args.timezone))}')
continue
else:
original_exif = piexif.load(str(file))
geotags = generate_geotags(point.latitude, point.longitude, point.elevation, point.time, original_exif)
exif_bytes = piexif.dump(geotags)
piexif.insert(exif_bytes, str(file))
print('OKAY - ', file.name)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Add location tags to photos based on a GPX track.')
parser.add_argument('photos', help='Path to the directory containing the photos')
parser.add_argument('gpx', help='Path to the GPX file')
parser.add_argument('--max-diff', type=int, default=300, help='Maximum allowed difference in seconds between image timestamp and track point. Default: 300')
parser.add_argument('--timezone', default=get_local_timezone(), help='Three letter timezone the photos are in (e.g. EST). Default: auto-detect your local timezone')
args = parser.parse_args()
args.photos = Path(args.photos).expanduser().absolute().resolve()
if args.photos.is_file() or not args.photos.exists():
print('Invalid path to photos. Must be a directory.')
quit(1)
args.gpx = Path(args.gpx).expanduser().absolute().resolve()
if args.gpx.is_dir() or not args.gpx.exists():
print('Invalid path to GPX file.')
quit(1)
main(args)