A while back I had the sensibility to download all my pictures off Facebook to a local folder. In fact, I wrote a Chrome extension to do that because I couldn’t find that functionality in Facebook’s farcical interface. I’m kind of surprised I never hit a Facebook spamfilter while downloading a solid 550 pictures through essentially a bot-extension, but I guess they were too busy finding alternative ways to give Cambridge Analytica access to all their data back then.
Most of those pictures had gotten stripped of all their Exif data along the way. I had been smart enough to extract the upload date of the picture, and name the file after it, but Synology Moments doesn’t use the name of the file to set its date. It parses the Exif data only, and if that doesn’t exist, it will just use the day the files were created. Result: I had 550 pictures taken on a rainy October day in 2016. That can’t be right.
As luck would have it, all of these images got uploaded to the same directory in the ~/Drive/Moments/Drive/2016-10-05/
folder on my Synology. That means I had to do three things:
I won’t go through the details of mounting an NFS drive. Actually, I’m not going to go through the details of the rest either, you should be able to figure that out. The long and short of it: my function relies on piexif
and PIL
. The rest should be self-explanatory: loop through the files in the directory and call the function. This is all in python3
though I’m fairly certain it would work with minor adjustments in python2
as well.
def replace_exif(file, datetime_object):
"""
Replaces the createdTime Exif data of image with date parsed from the datetime_object
This function replaces the following three properties of the Exif data of
the image file that is passed to it:
Exif.Image.DateTime, at offset 306
Exif.Photo.DateTimeOriginal at offset 36867
Exif.Photo.DateTimeDigitized at offset 36868
This function expects that both PIL and piexif are imported
For more information about Exif and offsets, see http://www.exiv2.org/tags.html
Parameters
----------
file : string
Absolute or relative path to the relevant image file of which the Exif data should
be changed
datetime_object : datetime object
A datetime object generated by the standard datetime module which
contains the date to which the image's Exif data should be changed
"""
img = Image.open(file)
try:
# If the image already contains data, we only replace the relevant properties
exif_dict = piexif.load(img.info['exif'])
print(f"Exif load for file '{file}'' successful")
except KeyError:
# If the image has no Exif data, we create the relevant properties
print(f"No Exif data for file '{file}', creating Exif data instead...")
exif_dict = {}
exif_dict["0th"] = {}
exif_dict["Exif"] = {}
# We now have a useful Exif dict, time to adjust the values
d = datetime_object.strftime("%Y:%m:%d %H:%M:%S")
exif_dict["Exif"][36868] = d.encode("utf-8")
exif_dict["Exif"][36867] = d.encode("utf-8")
exif_dict["0th"][306] = d.encode("utf-8")
# Convert into bytes and dump into file
exif_bytes = piexif.dump(exif_dict)
piexif.insert(exif_bytes, file)
print(f"Exif data replacement for file '{file}' successful")