Charles Engelke's Blog

August 25, 2009

QR Codes and Perl

Filed under: Uncategorized — Charles Engelke @ 1:28 pm

Two-dimensional barcodes like QRCode are pretty neat, and after I got my Google Ion phone with its built-in barcode program I went around scanning every one I could find for a while.  But I never really did anything with them until yesterday, when it occurred to me that they might be useful for a project I’m doing.  The project would augment an existing system written in Perl, so I went to see what Perl has in this vein.

It has GD::Barcode::QRCode (which I got for Windows using ActiveState‘s PPM tool and installing Catalyst-View-GD-Barcode-QRcode).  It’s dead easy to use.  Given a string (say, $text), you can just do:

use GD::Barcode::QRcode;
binmode STDOUT;
print GD::Barcode::QRcode->new($text)->plot->png;

Well, it’s that easy if the text is very short. If it’s not, you’ll get a message to STDERR saying something like:

Overflow error. version 1
total bits: 468  max bits: 128

You, see, there are different size QRCodes, and the module doesn’t seem to pick the right one for you (even though the documentation seems to say it will). But there are three parameters you can pass to the new method that give you some control over this: Ecc, Version, and ModuleSize. But what do they mean? The documentation isn’t very clear, but I’ve figured a bit of it out. The purpose of this post is for me to document what I’ve learned so I’ll be able to use it again.

The most important parameter (to me, anyway) is Version. Which is a terrible name, because it implies to me sequential enhancements. Actually, it just determines the size of the square barcode. A version 1 barcode is 21 rows by 21 columns, and each successively larger size is four rows taller and four columns wider than the last. So a version 2 barcode is 25 by 25, version 3 is 29 by 29, and so on. (I don’t know why they go up by four. It might just be convention, or it might be something to do with the algorithms involved.) A version n barcode is therefore 4n+17 rows by the same number of columns. The largest legal value of version is apparently 40.

Ecc stands for Error-Correcting Code, and the possible values are ‘M’, ‘L’, ‘H’, or ‘Q’, with ‘M’ being the default. That’s all the module’s documentation says. Huh? How am I supposed to pick? Well, different values result in different levels of error-correcting codes being used. The more robust the error-correction, the less data you fit into a fixed size barcode. And the values used here? Since ‘L’ reduces available data less than ‘M’, which does so less than ‘H’, my guess is that they mean “low”, “medium”, and “high”. ‘Q’ is between ‘M’ and ‘H’; maybe it means “quality”? If you don’t have to worry about the barcode being badly smudged or losing definition in transmission, ‘L’ for low error correction is fine. If you’re going to have it get dirty, scraped up, and badly scanned, go for ‘H’. Or pick something in the middle.

Finally, ModuleSize is just how big the printed blocks are going to be. If you pick 1 for this value, they’ll use a single pixel each in the resulting image file. I found that 8 was a good choice for a PNG on a web page.

The final piece of the puzzle is just how much data you can put into a barcode with specific values of these parameters. This table tells you. So, if I have 256 bytes of binary data, and I have a fairly clean but not pristine printing, scanning, and transmission environment (so I’ll want to at least use M for medium error correction), I’ll need to set the version to at least 12. Here’s the code:

use GD::Barcode::QRcode;
binmode STDOUT;
my $code = GD::Barcode::QRcode->new($binary_data_256_bytes_long,
   {ECC => 'M', Version => 12, ModuleSize => 8}
print $code->plot->png;

1 Comment

  1. One easy way to fix the “bug” with not correctly calculating the size is to change the following line in GD/Barcode/

    $oSelf->{Version} = $rhPrm->{Version} || 1;


    $oSelf->{Version} = $rhPrm->{Version} || 0;

    This will turn auto versioning back on, how or why this bug has been around so long I don’t know.

    Comment by Matt — March 4, 2010 @ 7:57 am

RSS feed for comments on this post.

Blog at

%d bloggers like this: