Pool Photo Generator
How to create multiple device dependent header photos with Node
Since the existence of this blog, the posts all have a custom header image that I generate from my own photos. Already three years ago (omg … really?) I described in an article how to do this with Hexo: Automatic Header Images in Hexo.
To keep it short, I use a pool folder for this, in which I keep in subfolders next to a meta.txt
, for the title of the image and an external url on 500px for interactions to the image, three variants that I need for a new post:
- mobile.jpg (width 480px)
- tablet.jpg (width 768px)
- normal.jpg (width 1280px)
The only piece of the puzzle that was still missing was the automatic generation of these three image variants and the meta file based on a selected photo that I want to add to the pool of available header images. So far it was fun to generate the header images manually either on the desktop or on the smartphone, but it really doesn’t have to be. My goal now was to write a script where I just throw a selected photo into a folder and the NodeJS script does the rest.
My photo workflow is based on Adobe Lightroom Classic and one of the steps is to give a title to the good ones I use here as well. So the script had to include four steps when iterating over the inbound folder’s JPG files:
- create new pool folder
- read meta data (IPTC -> title) and write it to meta.txt
- create the three image variants
- delete the processed image from the inbound folder
The Script
I implemented the script as a class with the following skeleton:
1 | ; |
Requirements
To handle files and folders in NodeJS you need at least fs
and path
:
1 | const fs = require("fs"); |
For image processing there’s no better solution as Sharp:
1 | const sharp = require('sharp'); |
Similarly powerful, but intended for reading image metadata is EXIFR:
1 | const exifr = require('exifr'); |
Vars
I just needed three vars for holding the full qualified path of the current execution folder and the names of the two incoming parameters:
1 | const _currentPath = __dirname; |
Constructor
In this case, the constructor only serves to provide and check the necessary parameters of the class:
1 | constructor(inboundFolder, poolFolder) { |
Function ‘generate’
This is the main function to call, and it first reads the input folder for JPG and cycles through all the hits. Then for each file the above four steps are executed:
1 | generate() { |
Function ‘createImageVariant’
This helper function reduces the original image to the desired size and saves it in the destination (pool) folder as a JPG:
1 | async createImageVariant(imgSource, imgTarget, sizeWidth) { |
In the above code I have omitted some syntactical sugar. You can find the complete script here: https://github.com/kristofzerbe/kiko.io/blob/master/lib/pool-photo-generator.cjs
The Runner
I integrated the call to the generator into my Hexo workflow, but also wrote a small runner to run it independently:
1 | /** |
Conclusion
Last but not least, in my existing Lightroom workflow, I configured the wonderful plugin Jeffrey’s “Collection Publisher” to create the new pool photos directly through it into the Inbound folder. Once the changes are committed to Github, where the blog is hosted and the deployment action happens, the new header images are created and displayed at https:\kiko.io\photos and are available for a new post.
You can interact with this article (applause, criticism, whatever) by mention it in one of your posts or by replying to its syndication on Mastodon, which will also be shown here as a Webmention ... or you leave a good old comment with your GitHub account.
Webmentions
No Webmentions yet...
In case your blog software can't send Webmentions, you can use this form to submit me a mention of this article...
Comments