Using QR Codes in printed books.

September 7, 2020. Filed under python 59 elegant-puzzle 9

Probably my favorite parts of An Elegant Puzzle is the QR codes we created for each link as an exploration of how print and digital can comingle a bit more easily.

As I start thinking about how to turn staffeng.com into a book, I'm keen to recreate this feature, but even moreso I'm curious if this time I can push it a bit closer to the original vision.

Cool URIs don't change

Ok, so we know that Cool URIs don't change, but now that the book has been out in the wild for over a year, the biggest issue by far has been URLs bit-rotting into 404s. This really highlighted for me how important it is to use a URL shortener to indirect the links, making it possible to fix 404s as links expire.

The other advantage is that QR codes get more complex the longer they are, so simpler ones can be much smaller. For example, let's generate QR codes for these three URLs:

https://lethain.com
https://lethain.com/thisis/a/verylong/url
https://lethain.com/thisis/a/verylong/urlforsomereasonletsjustkeeptyingalothere

Then you can see the corresponding QR codes from left to right, which requrie more and more complexity to represent the underlying URL.

Three different qr codes from least to most complex.

The image complexity matters, because it determines just how small you can get the codes, which in turn impacts either the cost to print or the viability of printing at all.

So, let's 's play around with scaling the images a bit, how small can we get the, such that an iPhone can still read the images?

Let's imagine we can generate a short code for every link in the book and that there are fewer than 10,000 links. Then we can use a URL like this one to reason about rendering sizes.

https://staffeng.com/l/1234

Ok, so looking at it scaled to one, two, three and six pixels, we can get a sense of various scales (scale is the number of pixels used to represent a single module within the QRCode).

Different scales of qrcodes

Even zooming my phone in on my high definition monitor I can't get the smallest QR code to parse, but I can get the second smallest to work reliably, and looking at a printed copy of An Elegant Puzzle, I believe we ended up with a three scale there despite the much longer URLs we were representing.

If you're self-publishing and printing via Kindle Direct Publishing, they print at 300 dots-per-inch, which ought to be more than enough for these images.

Experimenting with format

Ok, now that we have the QRCode sizing, next is to experiment with how to use them. In particular, I want to play around with how to inline them so the QRCodes are close to the link they represent rather than at the end of the book. A compromise would be collecting them all into the end of each chapter rather than the entire book, but inline would be better!

Different scales of qrcodes

It's a bit verbose though, so interesting to try inlining them even more.

Different scales of qrcodes

Both of those could work quite nicely, I think, if I can get the layout to work properly, which I suspect will be quite hard! Will see if this is actually possible.

It also makes me have a bunch of other ideas, e.g. should print layout of ever blog post do something similar? An experiment for another time.

Code for QR codes

The script I used for these QRCodes was modeled off this tutorial:

import argparse
import pyqrcode
import png
from pyqrcode import QRCode


def qr(txt):
    code = pyqrcode.create(txt)
    return code


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("text_string", help="text to format, use quotes if whtiespace")
parser.add_argument("output_file", help="filename to render output file")
parser.add_argument("–scale", help="integer representing scale of image", type=int, default=6)
    args = parser.parse_args()
    code = qr(args.text_string)
    code.png(args.output_file, scale=args.scale)

Despite being quite simple, it worked quite well.