EXIF data with a pelican-photos Gallery

:UPDATE:
I have done some work on how this works, and now its a CLI script (but no wheel) that I have on my gitea instance. You can find it here - EXIF2txt.
END
Way back in the day, when I was using Flickr as one of my daily visits, I really enjoyed learning HOW these amazing photographers made these pictures happen through the exif data. This is where I learned about the affect of aperature, etc. I would copy the settings with my old Canon XSi and grow.
When I added the galleries to this site with the pelican-photos the only way to do this was adding an exif.txt file to each folder. There is a recommended third-party software to do it, but I didn't find it intuitive and gave up.
This weekend however, I had a very little bit of time and decided to see what file metadata I could pull using python.
Using Python to extract EXIF data
I tried the piexif module without much luck, and then found this GIST from @jpstroop that did most of the work for me.
def _map_key(k): try: return TAGS[k] except KeyError: return GPSTAGS.get(k, k) # Creates a dictionary of image EXIF meta data from an image, borrowed from a github gist def get_exif(image_path): metadata = {} with Image.open(image_path) as i: info = i._getexif() try: [ metadata.__setitem__(_map_key(k), v) for k, v in info.items() ] return metadata except AttributeError: return None
I use the exact fucntions from @jpstroop.
Walking and writing with Python
The next step was to figure out how to walk all the directories in my photo gallery and make sure that I was getting them all, for that I do this:
# The directory of the source photos, the same as PHOTO_LIBRARY in pelicanconf.py # I run this in a WSL instance, but pelican is run on the host windows machine, hence the sample directory dir = '/mnt/c/Users/jeff/Pictures' for root, subdirectories, files in os.walk(dir): for subdirectory in subdirectories: print(os.path.join(root, subdirectory))
This is goes through each directory and prints the path. I don't need that for the final product, but I like knowing that something is happening when I run the script, so I kept it.
Creating a text file with everything
Once I made sure that was working the way that I hoped, I wrote a function that will be called for every subdirectory. I called it write_exif_file(directory), this creates the text file and then loops over every .jpg file there and writes the exif data in the way needed for pelican-photos and that I think looks "good". [*]
That function looks like this: [†]
def write_exif_file(directory): # Open the exif.txt file, create if it doesn't exist, in the current folder. txt = open(directory+'/exif.txt', 'w') for file in os.listdir(directory): # check the files which are end with specific extension # Everything that I want to have EXIF information for is a jpg, but you can add others too. if file.endswith(".jpg"): # Need to iterate through the files in the list and pass each to the image = get_exif(directory +'/'+os.path.join(file)) txt.write( os.path.join(file) + ': ' + str(image.get('Model')) + ' with a ' + str(image.get('LensModel')) + ' - ' + str(image.get('ExposureTime')) + 's, ' + # I want to change this to fractions, but it works for now. 'f/' + str(image.get('FNumber')) + ' at ISO-' + str(image.get('ISOSpeedRatings')) + '\n' ) # Close the text file now that we are done with it. txt.close() return None
For now I'm only including:
- Model,
- Lens,
- Exposure,
- F-Stop, and
- ISO
I may add GPS to them in the future, but as for the settings needed to replicate these shots with your own camera, I think this is enough.
Finding the code snippet
I created a GIST for this code snippet here - pelican-photos-create-exif-files. Until this weekend I didn't even know that GIST was a site. As I go through creating these little scripts for myself I am way more likely to neeed a function, or code-snippet than an entire repo. I will probably be adding some more here as I go along, as a backup storage if nothing else.
If you have any suggestions on how to make this "slicker". If you think its useful and want to copy/paste it as a function in the plugin be my guest. I don't have the bandwidth right now to figure out how to do a proper pull-request for the plugin, or the expereince to know how to update the code in a way that won't break everything else.
Footnotes
[*] | There is still some work to do there, especially for the exposure time. I want it to be fractional for less than a second, but its "good enough" for this iteration. |
[†] | If anyone knows CSS and wants to help me add syntac highlighting to this theme, let me know. |
This post is part 3 of the "How I Pelican" series: