Skip to content

Commit

Permalink
Add location data to allowable sort format
Browse files Browse the repository at this point in the history
Based on jaakla's work in andrewning#117
but replaces dependence on exifread back to original exiftool implementation.

Fixes andrewning#116
  • Loading branch information
edwardwbarber committed Aug 6, 2023
1 parent 9037913 commit ffc14b5
Showing 1 changed file with 73 additions and 9 deletions.
82 changes: 73 additions & 9 deletions src/sortphotos.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from datetime import datetime, timedelta
import re
import locale

import reverse_geocode

# Setting locale to the 'local' value
locale.setlocale(locale.LC_ALL, '')
Expand Down Expand Up @@ -178,6 +178,54 @@ def check_for_early_morning_photos(date, day_begins):

return date

# read tags using exifread
### helper functions, for geocoordinates

def _convert_to_degress(value):
"""
Helper function to convert the GPS coordinates stored in the EXIF to degress in float format
:param value:
:type value: exifread.utils.Ratio
:rtype: float
"""
d = float(value.values[0].num) / float(value.values[0].den)
m = float(value.values[1].num) / float(value.values[1].den)
s = float(value.values[2].num) / float(value.values[2].den)

return d + (m / 60.0) + (s / 3600.0)

def get_exif_location(exif_data):
"""
Returns the latitude and longitude, if available, from the provided exif_data (obtained through get_exif_data above)
"""
lat = None
lon = None

gps_latitude = _get_if_exist(exif_data, 'GPS GPSLatitude')
gps_latitude_ref = _get_if_exist(exif_data, 'GPS GPSLatitudeRef')
gps_longitude = _get_if_exist(exif_data, 'GPS GPSLongitude')
gps_longitude_ref = _get_if_exist(exif_data, 'GPS 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.values[0] != 'N':
lat = 0 - lat

lon = _convert_to_degress(gps_longitude)
if gps_longitude_ref.values[0] != 'E':
lon = 0 - lon

return lat, lon

def _get_if_exist(data, key):
if key in data:
return data[key]

return None

###

# Open image file for reading (binary mode)

# this class is based on code from Sven Marnach (http://stackoverflow.com/questions/10075115/call-exiftool-from-a-python-script)
class ExifTool(object):
Expand Down Expand Up @@ -213,14 +261,21 @@ def execute(self, *args):
return output.rstrip(' \t\n\r')[:-len(self.sentinel)]

def get_metadata(self, *args):

try:
return json.loads(self.execute(*args))
tags = json.loads(self.execute(*args))
lat, lon = get_exif_location(tags)
tags['EXIF:GpsLat'] = lat
tags['EXIF:GpsLon'] = lon
if lat and lon:
location = reverse_geocode.get([lat,lon])
tags['Location:country_code'] = location["country_code"]
tags['Location:city'] = location["city"]
tags['Location:country'] = location["country"]
return tags
except ValueError:
sys.stdout.write('No files to parse or invalid data\n')
exit()


# ---------------------------------------


Expand All @@ -239,10 +294,10 @@ def sortPhotos(src_dir, dest_dir, sort_format, rename_format, recursive=False,
dest_dir : str
directory where you want to move/copy the files to
sort_format : str
date format code for how you want your photos sorted
format code for how you want your photos sorted
(https://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior)
rename_format : str
date format code for how you want your files renamed
format code for how you want your files renamed
(https://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior)
None to not rename file
recursive : bool
Expand Down Expand Up @@ -359,7 +414,15 @@ def sortPhotos(src_dir, dest_dir, sort_format, rename_format, recursive=False,


# create folder structure
dir_structure = date.strftime(sort_format)

country = data.get("Location:country","")
city = data.get("Location:city", '')
country_code = data.get("Location:country_code", '')

sort_format_geo = sort_format.replace('%country',country)
sort_format_geo = sort_format_geo.replace('%city',city)
sort_format_geo = sort_format_geo.replace('%country_code',country_code)
dir_structure = date.strftime(sort_format_geo)
dirs = dir_structure.split('/')
dest_file = dest_dir
for thedir in dirs:
Expand Down Expand Up @@ -455,12 +518,13 @@ def main():
parser.add_argument('-c', '--copy', action='store_true', help='copy files instead of move')
parser.add_argument('-s', '--silent', action='store_true', help='don\'t display parsing details.')
parser.add_argument('-t', '--test', action='store_true', help='run a test. files will not be moved/copied\ninstead you will just a list of would happen')
parser.add_argument('--sort', type=str, default='%Y/%m-%b',
parser.add_argument('--sort', type=str, default='%Y/%m-%b-%country-%city',
help="choose destination folder structure using datetime format \n\
https://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior. \n\
Use forward slashes / to indicate subdirectory(ies) (independent of your OS convention). \n\
The default is '%%Y/%%m-%%b', which separates by year then month \n\
with both the month number and name (e.g., 2012/02-Feb).")
with both the month number and name (e.g., 2012/02-Feb). \n\
Use %%city, %%country and %%country_code for location.")
parser.add_argument('--rename', type=str, default=None,
help="rename file using format codes \n\
https://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior. \n\
Expand Down

0 comments on commit ffc14b5

Please sign in to comment.