Batch png to pdf with Inkscape & PDFtk
Today, I had 57 png images of QR codes, and needed to create a single pdf document where each page contained a single QR code with the file's name shown centered above the QR. From start to finish, without planning ahead, it took me 23 minutes, a pace which would have required me to do 1 image every 24 seconds if I were to do them by hand. Plus, any subsequent tweaks can be done in a flash.
Create one svg manually
- Open Inkscape and adjust the document page size to your liking.
- Add the image to the page. I chose to embed the image rather than linking, but in retrospect, linking would have been the correct choice.
- Add the text box to the page. With the text selected, press CTRL+SHIFT+T to open the Text and Font menu, choose Center alignment, and click apply.
- Arrange the image and label to your liking.
- Save the document.
Generate svgs for all other images
- Open the template svg in a text editor and copy everything.
Create a Python file, and start by:
TEMPLATE = ''' paste the svg file here '''.strip()
If you chose to embed the image, it will be stored as base64. In that case, delete the actual base64 text, but leave the
data:image/png;base64,
prefix. After the comma, add{image_base64}
.xlink:href="data:image/png;base64,{image_base64}"
If you chose to link the image, you'll find the file path. Replace it with
{image_path}
.xlink:href="{image_path}"
Find the element that contains the label text, and replace the text with
{label_text}
.The rest of the Python script was as follows:
import base64 import glob filenames = glob.glob('*.png') for filename in filenames: label_text = f'...' # do some transformations on the filename data = open(filename, 'rb').read() image_base64 = base64.b64encode(data).decode('ascii') svg = TEMPLATE.format(image_base64=image_base64, label_text=label_text) open(filename.replace('.png', '.svg'), 'w').write(svg)
Using linking instead of embedding, this would have been more like:
for filename in filenames: label_text = f'...' # do some transformations on the filename svg = TEMPLATE.format(image_path=filename, label_text=label_text) open(filename.replace('.png', '.svg'), 'w').write(svg)
Convert svgs to pdf
On Windows, a for-loop in the command line looks like this:
for %x in (*.png) do (start /w inkscape --without-gui --export-pdf=%~nx.pdf %~nx.svg)
Combine all pages into single pdf
pdftk *.pdf cat output "all.pdf"
If I need to make any updates to the template, I can
- Open any of the svgs and make the changes.
- Copy it back into the Python file and redo the
{templating}
. - Run the python script, inkscape export loop, and pdftk merger.
- Add tag today_i_did_this.
- Use start /w to wait for the process to finish before next one.
- Add inkscape_batch_png_pdf.md.
If you would like to subscribe for more, add this to your RSS reader: https://voussoir.net/writing/writing.atom