3

I need to generate several thousand qr codes of simple IDs (1234, 1235, 1236, ...) and want to be able to also make them human readable. qrencode is a really cool tool to generate qr-codes, BUT no way to add a subtitle there.

Any ideas?

3 Answers 3

2

Create an image with the text and append that to the image:

#!/bin/bash

txt="$1"
qrencode -o "$txt".png "$txt"

convert  -pointsize 36 "label:$txt" "$txt.gif"
convert -append "$txt".png "$txt.gif" "$txt.total.gif"
2
  • Nice! If I do this with eps output format, I get 2 lines of $txt - do you know that problem? (I know it wasn't in the question...) Commented Jun 18, 2021 at 12:27
  • I encountered some issues with convert and eps before; it kept printing the filename in the image. I had to go via pnm to prevent it from happening; this was the line in my script then. convert "$fromfile" pnm:- | convert -density 300 - out.eps Don't know if that is your issue though. Commented Jun 18, 2021 at 12:54
2

Imagemagics convert to the rescue:

  1. generate QR Code with qrencode (output PNG, SVG doesn't work with convert, I think)
  2. generate png image from string with convert
  3. append the images with convert

Here the script for this:

for i in $(cat ../input.csv); do 
  qrencode $i -t png -l H -s 10 -o $i.q.png;
  convert -size 290x40 xc:white -pointsize 34 -gravity center -font /usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf -draw "text 0,0 '$i'" $i.s.png; 
 convert -append $i.q.png $i.s.png $i.png; rm $i.q.png; rm $i.s.png; 
 echo $i; 
done;

DejaVuSansMono.ttf has dots in the zeros, which makes it well readable, there might be others. 1 and small L and the usual suspects are also well discernible.

2

If you want to keep the svg format, it seems it is not that difficult to edit the xml to add a new <text> element to the end of the file. I don't know svg well enough to do this in some standard way, but looking at how the file looks when you use an svg editor to add a text line, the following awk script might suffice for the example you gave.

i=1234
qrencode "$i" -t svg -l H -s 10 -o "$i.q.svg.orig"
awk <"$i.q.svg.orig" >"$i.q.svg" -v txt="$i" '
/<svg /{ match($0,"height=\"([0-9.]+)",grp)
    ht = grp[1]*1.1
    ht = "height=\"" ht
    sub("height=\"([0-9.]+)",ht,$0)
    match($0,"viewBox=\"0 0 ([0-9]+) ([0-9]+)",grp)
    vb = int(grp[2]*1.1+.5)
    x = int(grp[1]/2+.5)
    y = grp[2]+1
    vb = "viewBox=\"0 0 " grp[1] " " vb
    sub("viewBox=\"0 0 ([0-9]+) ([0-9]+)",vb,$0)
}
/<rect x="0" /{
    match($0,"height=\"([0-9.]+)",grp)
    ht = int(grp[1]*1.1+.5)
    ht = "height=\"" ht
    sub("height=\"([0-9.]+)",ht,$0)
}
/<\/svg>/{
    printf "  <text font-family=\"Helvetica, sans-serif\" font-size=\"6\" stroke-width=\"0\" text-anchor=\"middle\" x=\"%d\" y=\"%d\" xml:space=\"preserve\">%s</text>",x,y,txt
}
{print}
'

This is more complex than really necessary, in order to be a little more generic.

It takes the initial <svg width="10.23cm" height="10.23cm" viewBox="0 0 29 29" ... and scales up the height and 4th viewBox values by 10% so it becomes <svg width="10.23cm" height="11.23cm" viewBox="0 0 29 33" ....

It then takes the background white rectangle and grows the height similarly from <rect ... height="29" to <rect ... height="33".

Finally, it then adds a <text...> line before the end, using as x and y positions the values found from the viewBox. The text-anchor="middle" centers the text on this coordinate.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.