diff --git a/LICENSE_1_0.txt b/LICENSE_1_0.txt new file mode 100644 index 0000000..36b7cd9 --- /dev/null +++ b/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/ReadMe.md b/ReadMe.md new file mode 100644 index 0000000..118cc0b --- /dev/null +++ b/ReadMe.md @@ -0,0 +1,21 @@ + + + + + + + +# Photo Manager + +This script will rename all photos in a directory +have the same naming scheme based on the time that +the photo was taken. + +This will allow the user to combine photos taken on +different devices and maintain the ordering based +on the file name. + +## Dependencies: +* Python +* [ExifTool](https://www.sno.phy.queensu.ca/~phil/exiftool/) + diff --git a/photo_manager.py b/photo_manager.py new file mode 100644 index 0000000..0fd54d6 --- /dev/null +++ b/photo_manager.py @@ -0,0 +1,120 @@ +# Copyright (c) 2018-2019 Adrian Serio +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import sys +import argparse +import re +import csv +from datetime import datetime, timedelta +from math import log10 +from os import system, path as os_path + +# Discover Patform +plat = sys.platform + +# Setup +parser = argparse.ArgumentParser(description= + "Hi! I am your photo album manager. If you provide me with an album name " + "and a path I will rename all photos (.jpg) in the current directory to the " + "album name and append a number to the end based on the time the photo " + "was taken. These photos will be copied to the path supplied. ") + +parser.add_argument('album_name', help='The first compoent of the photos new name') +parser.add_argument('path', help='The path to the location ' + 'where the photos will be copied.') +args = parser.parse_args() + +album_name = args.album_name +path = args.path + +# Handle Windows +if plat == "win32" or plat == "win64": + path='"'+path+'\\"' +#print(path) + +# Read in photos and meta data +print("Reading in photos and meta data...") + +if plat == "win32" or plat == "win64": + system("exiftool.exe -datetimeoriginal -csv *.jpg > pm_output.txt") +else: + system("exiftool -datetimeoriginal -csv *.jpg > pm_output.txt") + +file_names=list() +dates=list() + +with open("pm_output.txt") as f: + reader = csv.DictReader(f) + for row in reader: + file_names.append(row['SourceFile']) + dates.append(datetime.strptime(row['DateTimeOriginal'],"%Y:%m:%d %H:%M:%S")) + +#print(file_names) +#print(dates) + +# Preserve file extentions +exten=list() +for x in file_names: + match = re.search(r'.(\w+)$', x) + exten.append(match.group(0)) +#print (exten) + +# Check that lists are the same length +if len(file_names) == len(dates): + print("Parsing complete! Photo Manager will rename", len(file_names), "photos.") +else: + print("Parsing error!") + +# Determine the padding for the number of days +diff = max(dates)-min(dates) +if diff.days == 0: + pad = 1 +else: + pad = int(log10(diff.days))+1 + +print("The supplied photos span", diff.days, "days.") + +# Create the list of new names +new_name=list() +for x in dates: + d = x-min(dates) + new_name.append(album_name+"_"+str(d.days).zfill(pad)+str(x.hour).zfill(2)+str(x.minute).zfill(2)+str(x.second).zfill(2)) +#print (new_name) + +# Rename photos +for i in range(len(file_names)): + # Check for duplicate names + # Escape Whitespace + if " " in file_names[i]: + if plat == "win32" or plat == "win64": + file_names_w = "\"" + file_names[i] + "\"" + else: + file_names_w = file_names[i].replace(' ','\ ') + else: + file_names_w = file_names[i] + #print (repr(file_names_w)) + if os_path.exists(path[1:-1] + new_name[i] + exten[i]): + tag = 2 + new_name[i] += "_" + str(tag) + while os_path.exists(path[1:-1] + new_name[i] + exten[i]): + tag += 1 + # Remove the previous tag and underscore. int(log10(tag)) + # will return 0 for tags <10, 1 for tags <100 etc. + new_name[i] = new_name[i][:-(int(log10(tag))+2)] + new_name[i] += "_" + str(tag) + if plat == "win32" or plat == "win64": + cmd = "copy " + file_names_w + " " + path + new_name[i] + exten[i] + else: + cmd = "cp " + file_names_w + " " + path + new_name[i] + exten[i] + print(cmd) + system(cmd) + +# Cleanup + +if plat == "win32" or plat == "win64": + system("del pm_output.txt") +else: + system("rm pm_output.txt")