QR codes are everywhere. Easy to scan with a phone. But what if you want to decode a QR on your laptop instead of your phone, without a camera?
I was working on an app with generated QR codes containing login links. But my local development environment is not reachable from my phone, so the links from the QR code didn't work. Not very practical. So I needed a way to scan the QR directly on my laptop. I succeeded but it was slightly less easy than I hoped.
zbarimg
Using the command line tool zbarimg you can decode a QR-code in an image file.
If you're using Debian or derivitive like Ubuntu you can install the tool using:
sudo apt install zbar-tools
Now you can easily decode files with QR codes:
zbarimg screenshot.png
Works fine, but I had to test a lot of QR codes during development and testing. Making a screenshot, run the tool, and copy the result got old soon. So I set out to automate things further, of course.
flameshot
For screenshots I've been using the great tool flameshot for a while. Check it out, if you haven't already. It has a GUI but like a good Linux application also a command line interface so you can use it in scripts.
Installing flameshot
:
sudo apt install flameshot
Then create a new file named qr-scan
with the following contents:
#!/bin/bash
flameshot gui -r \
| zbarimg - \
| sed "s/^QR-Code://g" \
| xclip -selection clipboard
Make it executable using chmod +x qr-scan
and execute it with ./qr-scan
. Put it in a directory that's in your PATH
and you can run it from everywhere.
The script works like this:
- Execute
flameshot
with thegui
parameter to show the gui to make the screen selection. The-r
parameter (forraw
) will send the selection as raw png data tostdout
- The output is piped through
zbarimg
which decodes the QR code - The output of
zbarimg
is cleaned up bysed
- The final result is copied to the clipboard using
xclip
That's all?
Well, I hoped so, but I bumped into issues. Quite a few QR codes turned out to be unreadable by zbarimg
. It seemed to be related to the payload size. But my phone could decode them with no problems. The error output was extensive but rather useless for finding a solution.
scanned 0 barcode symbols from 1 images in 0 seconds
WARNING: barcode data was not detected in some image(s)
Things to check:
- is the barcode type supported? Currently supported symbologies are:
. EAN/UPC (EAN-13, EAN-8, EAN-2, EAN-5, UPC-A, UPC-E, ISBN-10, ISBN-13)
. DataBar, DataBar Expanded
. Code 128
. Code 93
. Code 39
. Codabar
. Interleaved 2 of 5
. QR code
. SQ code
- is the barcode large enough in the image?
- is the barcode mostly in focus?
- is there sufficient contrast/illumination?
- If the symbol is split in several barcodes, are they combined in one image?
- Did you enable the barcode type?
some EAN/UPC codes are disabled by default. To enable all, use:
$ zbarimg -S*.enable <files>
Please also notice that some variants take precedence over others.
Due to that, if you want, for example, ISBN-10, you should do:
$ zbarimg -Sisbn10.enable <files>
A short duckduckgo search showed me I was not the only one with this problem. And thankfully I found a good solution on a Stackoverflow page.
Imagemagick
Imagemagick provides the super cool convert
command which enables you to convert almost anything into almost anything with all kinds of advanced magic. Apparently you can also use it to make QR codes better readable for zbarimg
.
Install imagemagick
with:
sudo apt install imagemagick
The following code is copied from the SO page above:
convert input.png +repage -threshold 50% -morphology open square:1 output.png
zbarimg output.png
I did not have time nor motivation to find out what this does in detail. As long as it works for zbarimg
right?
Wrapping up...
If we implement this step into the qr-scan
script we get:
#!/bin/bash
flameshot gui -r \
| convert - +repage -threshold 50% -morphology open square:1 - \
| zbarimg - \
| sed "s/^QR-Code://g" \
| xclip -selection clipboard