From d18786b00028f73abf324c639cc362d2524445a2 Mon Sep 17 00:00:00 2001 From: rrr-marble Date: Sun, 19 Dec 2021 23:17:34 +0300 Subject: [PATCH 1/5] add: transform coordinates to decimal form --- util/import_photos.py | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/util/import_photos.py b/util/import_photos.py index 32a4065..401e750 100644 --- a/util/import_photos.py +++ b/util/import_photos.py @@ -6,9 +6,44 @@ import filetype from os import path, walk from sys import argv, stderr from shutil import move +from fractions import Fraction import sqlite3 +def decimal_from_rational64u(dms: str): + """Convert coordinates from rational64u EXIF uses to represent + degrees, minutes, and seconds of a point to decimal format + + General formula is + dec_degree = degreesNumerator / degreesDenominator + + minutesNumerator / minutesDenominator / 60 + + secondsNumerator / secondsDenominator / 3600 + + https://en.wikipedia.org/wiki/Geographic_coordinate_conversion + https://gis.stackexchange.com/questions/136925/how-to-parse-exif-gps-information-to-lat-lng-decimal-numbers + + >>> decimal_from_rational64u(dms="42/1, 18/1, 2914/100") + 42.30809 + """ + + # 1 split by comma + # 2 turn each into Fraction + # 3 zip fractions with their respective (degrees, minutes, seconds) denominator + # 4 divide the fraction + # 5 sum up the result + # 6 convert to decimal + # 7 round to 5th decimal point + return round( + float( + sum( + a / b + for (a, b) in zip((Fraction(f) for f in dms.split(",")), (1, 60, 3600)) + ) + ), + 5, + ) + + def process_pictures(source: str, dest_shrunk: str, dest_original: str): """Process images from the base directory in the first command line argument. Place the resized copies to dest_shrunk and @@ -53,9 +88,9 @@ def process_pictures(source: str, dest_shrunk: str, dest_original: str): "ResizedImage": path.join(dest_shrunk, filename), "OriginalImage": path.join(dest_original, filename), "DateTimeOriginal": exif["DateTimeOriginal"], # Q: normalize it? - "GPSLatitude": exif["GPSLatitude"], + "GPSLatitude": decimal_from_rational64u(exif["GPSLatitude"]), "GPSLatitudeRef": exif["GPSLatitudeRef"], - "GPSLongitude": exif["GPSLongitude"], + "GPSLongitude": decimal_from_rational64u(exif["GPSLongitude"]), "GPSLongitudeRef": exif["GPSLongitudeRef"], } except KeyError as e: From 6bd14777a38b88a24fe040373aebaee556337656 Mon Sep 17 00:00:00 2001 From: rrr-marble Date: Mon, 20 Dec 2021 12:52:28 +0300 Subject: [PATCH 2/5] add: take into account reference cardinal direction --- util/import_photos.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/util/import_photos.py b/util/import_photos.py index 401e750..1a9cf0e 100644 --- a/util/import_photos.py +++ b/util/import_photos.py @@ -10,9 +10,11 @@ from fractions import Fraction import sqlite3 -def decimal_from_rational64u(dms: str): +def decimal_from_rational64u(dms: str, ref): """Convert coordinates from rational64u EXIF uses to represent degrees, minutes, and seconds of a point to decimal format + Take into account reference cardinal direction and + turn [S]outh and [W]est coordinates negative General formula is dec_degree = degreesNumerator / degreesDenominator @@ -22,8 +24,8 @@ def decimal_from_rational64u(dms: str): https://en.wikipedia.org/wiki/Geographic_coordinate_conversion https://gis.stackexchange.com/questions/136925/how-to-parse-exif-gps-information-to-lat-lng-decimal-numbers - >>> decimal_from_rational64u(dms="42/1, 18/1, 2914/100") - 42.30809 + >>> decimal_from_rational64u(dms="42/1, 18/1, 2914/100", "S") + -42.30809 """ # 1 split by comma @@ -33,7 +35,7 @@ def decimal_from_rational64u(dms: str): # 5 sum up the result # 6 convert to decimal # 7 round to 5th decimal point - return round( + dec_coordinates = round( float( sum( a / b @@ -42,6 +44,10 @@ def decimal_from_rational64u(dms: str): ), 5, ) + if ref in ("S", "W"): + dec_coordinates = -dec_coordinates + + return dec_coordinates def process_pictures(source: str, dest_shrunk: str, dest_original: str): @@ -88,10 +94,12 @@ def process_pictures(source: str, dest_shrunk: str, dest_original: str): "ResizedImage": path.join(dest_shrunk, filename), "OriginalImage": path.join(dest_original, filename), "DateTimeOriginal": exif["DateTimeOriginal"], # Q: normalize it? - "GPSLatitude": decimal_from_rational64u(exif["GPSLatitude"]), - "GPSLatitudeRef": exif["GPSLatitudeRef"], - "GPSLongitude": decimal_from_rational64u(exif["GPSLongitude"]), - "GPSLongitudeRef": exif["GPSLongitudeRef"], + "GPSLatitude": decimal_from_rational64u( + exif["GPSLatitude"], exif["GPSLatitudeRef"] + ), + "GPSLongitude": decimal_from_rational64u( + exif["GPSLongitude"], exif["GPSLongitudeRef"] + ), } except KeyError as e: print(f"Image '{filename}' has no valid exif") From 2816355886e717106ece9b1770f2a2f95c453bb6 Mon Sep 17 00:00:00 2001 From: rrr-marble Date: Tue, 21 Dec 2021 01:27:34 +0300 Subject: [PATCH 3/5] del: redundant db columns --- util/import_photos.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/util/import_photos.py b/util/import_photos.py index 1a9cf0e..cfaf91e 100644 --- a/util/import_photos.py +++ b/util/import_photos.py @@ -130,9 +130,7 @@ def update_database(pic_info: dict, db_location: str): :OriginalImage, :DateTimeOriginal, :GPSLatitude, - :GPSLatitudeRef, - :GPSLongitude, - :GPSLongitudeRef) + :GPSLongitude) """, pic_info, ) @@ -164,9 +162,7 @@ def check_database(database_path: str): origpath TEXT NOT NULL, date TEXT, GPSLatitude TEXT, - GPSLatitudeRef TEXT, - GPSLongitude TEXT, - GPSLongitudeRef TEXT + GPSLongitude TEXT )""" ) con.commit() From be6a1f4eb797498f505e66acf54402100faf0a9b Mon Sep 17 00:00:00 2001 From: rrr-marble Date: Tue, 21 Dec 2021 01:31:19 +0300 Subject: [PATCH 4/5] del: redundant db columns in update requests --- util/import_photos.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/util/import_photos.py b/util/import_photos.py index cfaf91e..c0e7e09 100644 --- a/util/import_photos.py +++ b/util/import_photos.py @@ -121,10 +121,8 @@ def update_database(pic_info: dict, db_location: str): """INSERT INTO images(resizedpath, origpath, date, - GPSLatitude, - GPSLatitudeRef, - GPSLongitude, - GPSLongitudeRef) + GPSLatitude, + GPSLongitude) VALUES (:ResizedImage, :OriginalImage, From b601b106b4018699884ead60d1cf71a89c6f5d2a Mon Sep 17 00:00:00 2001 From: rrr-marble Date: Tue, 21 Dec 2021 01:47:32 +0300 Subject: [PATCH 5/5] ref: change coordinates db datatype --- util/import_photos.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/import_photos.py b/util/import_photos.py index c0e7e09..9fd21a7 100644 --- a/util/import_photos.py +++ b/util/import_photos.py @@ -159,8 +159,8 @@ def check_database(database_path: str): resizedpath TEXT NOT NULL, origpath TEXT NOT NULL, date TEXT, - GPSLatitude TEXT, - GPSLongitude TEXT + GPSLatitude REAL, + GPSLongitude REAL )""" ) con.commit()