Generating QR codes - the Easy, the Comfy and the Smarty
Using QR codes to assist people to find the right information quickly is a good choice nowadays. A QR code can be scanned easily with any mobile camera application and get your visitors straight into the action where you want them to be.
The Easy
One of the fastest and easiest ways to get a QR code is to sign up to one of the many online sites offering it as a Software-as-a-Service (SaaS) model and hoping the best. I used to do that in the past but recently noticed that the available conditions of a free tier had been reduced massively, meaning I lost a good number of QR codes.
Maybe more interestingly might be to check out the Google Charts API and to use their URL pattern to create your own QR codes quickly. You'll find that API under the section of Infographics. However, at the time of writing there is a small drawback.
Using the API is based on an HTTP GET request with a few query string parameters.
The result is ad hoc ready and usable.
Feel free to scan it with your mobile camera app and visit the URL presented.
One possible use case would be to integrate that URL template with a spreadsheet application like Sheets and have a column holding the hyperlink to the QR codes. Kindly read the description above for the chl
parameter to keep an eye on the format of the payload data.
This approach has been used twice for the annual MSCC Developers Conference in Mauritius and generated over 4,000 QR codes across two years. The individual QR codes were sent out as embedded image in emails to registrants and used to check in attendees during the event.
The Comfy
Now with Google's API deprecation warning in mind, it might be better to look for a more future-safe variation to generate QR codes. Interestingly, I was inspired by a post on LinkedIn for the initial solution: Write a small Python snippet to generate the QR code.
Using Python
Save that snippet as generateqrcode.py
file and run it using the Python 3 interpreter, like so.
This small program is going to create the QR code and save it as a PNG file in the same directory where you run it. In the most likely case that you are going to be greeted by an error regarding missing module you have to install it.
However a little bit of comfort and flexibility would be most appreciated though. After a few iterations the Python snippet might be transformed to the following.
The program reads the URL and the filename of the QR code to generate from the command line and has a bit of usage information. With this implementation it is possible to generate QR codes in a more versatile approach using the following command line statement.
This approach allows you to generate any QR code offline on your local machine.
Using a little bit of bash-Fu, aka shell scripting, one can write a small loop reading single lines from another file and feed them into this Python script to quickly produce any number of QR code images. One approach could be using the while read -r line; do COMMAND; done < input.file
syntax. Probably combined with the xargs
command to specify the URL for the QR data and the file name of the generated QR code image per line in the given input file.
Avid readers of my blog might be wondering: But why did you use Python?
As mentioned earlier, I got the initial idea from a post on LI and simply took the Python snippet as-is. This way it took me less than 15 minutes from reading to finished implementation. OK, I had minor help from my P-AI-R programming buddy Duet AI giving me the code fragments to read the command line arguments, to do the argument sanity checks and to deal with default values. Although I know Python in general I'm not familiar with it on a daily base.
It is also possible to "translate" the implementation above to C#.
Using C#
Let's create a similar console application using .NET instead. Additionally, we use a NuGet package called QRCoder
to generate the QR codes based on our payload. It's an open source library and hosted on GitHub.
Open the newly created file Program.cs
with your favourite text editor and replace the existing code with the following.
using QRCoder;
using (QRCodeGenerator qrGenerator = new QRCodeGenerator())
using (QRCodeData qrCodeData = qrGenerator.CreateQrCode("https://jochen.kirstaetter.name", QRCodeGenerator.ECCLevel.Q))
{
PngByteQRCode qrCode = new PngByteQRCode(qrCodeData);
byte[] qrCodeAsPngByteArr = qrCode.GetGraphic(20);
File.WriteAllBytes("qrcode.png", qrCodeAsPngByteArr);
}
Console.WriteLine("QR code saved.");
Save the file and launch the console application. We are using the new minimal approach of .NET 6.
$ dotnet run
QR code saved.
If there are no typos and the project compiled without any errors you should see the generated QR code in the same directory. Here's the PNG image I created on my Chromebook using .NET 6.
I leave the implementation to deal with command line arguments, default values and parameter checks to you. Or better said, the complete source code is available in my GitHub repository.
The Smarty
With the easy approach we saw that we are able to create QR codes online and integrate them into any kind of other resources online; however we are dependent on the circumstances that those resources continue to be available to our liking (which didn't happen to be the case for me previously). The comfortable approach was to have a command line tool that is capable to produce the images we would need; however it is limited to the local machine and lacks the previous level of integration.
How about combining both ways in a smart fashion?
Let's embrace cloud computing and more precisely serverless cloud computing. With minimal to no changes to the previous code snippet it is possible to create a Google Cloud Function (or Azure Function) and bring back the online integration with other applications. But how does this work?
Google Cloud Function in Python
First, create a new directory on your machine and create a file called main.py
in which we copy the Python code from the previous command line script. Using that file name is by convention for Google Cloud Functions.
The implementation of the Cloud Function in Python is according to the console application. Main difference here is that we do not handle command-line arguments but read the payload from a query string parameter called url
and we return the generated PNG image in the HTTP response using the correct mime-type.
To import additional Python modules into the Cloud function it is necessary to create a file called requirements.txt
in the same folder where the main.py
file resides. Enter the following content and save it.
Before deployment to Google Cloud Functions it is recommended to run, test and debug your code locally. Use the Functions Framework to run your function without deploying. If not already installed, run the following command to install.
Then you can launch it using this command.
Next, open a browser tab or window and navigate to the URL http://localhost:8080/
. In case that you prefer staying in the terminal you can use curl
to call same URL. You see the following HTTP 400 response: Missing URL parameter. Which is expected given our implementation of the function checking for the required query string parameter url
.
To generate an actual QR code image you have to provide information in the required query string parameter: http://localhost:8080/?url=https://jochen.kirstaetter.name/
You can use Cltr+C to stop the local function execution.
Alternatively, you might give the Functions Emulator a try. At the time of writing is was tagged as Preview feature. Due to the lack of Docker environment on my machine I didn't try this. The command-line to deploy the Python function locally using the Functions Emulator would be like this.
Note: Use the Functions Emulator at your own risk!
Finally, it is time to deploy the function to Google Cloud Functions. There are multiple options available. You could log into the Cloud Console and navigate to the Cloud Functions area and create a new function in the browser, or you have the gcloud SDK already installed and use the following command.
See deploying the function in the official documentation for more details. Using a 2nd gen Cloud Function is recommended. Those are built on Cloud Run and EventArc to provide an enhanced feature set. See Cloud Function version comparison for more information and explanation.
You can optionally use the --allow-unauthenticated
flag to reach the function without authentication. This is useful for testing, but we don't recommend using this setting in production unless you are creating a public API or website.
After successful deployment you should have a working instance of your Cloud Function in the Console. It will also show you its URL to use the function.
You can also query the so-called description of your deployed Cloud Function using the gcloud command. This will give you the uri
address to reach the function.
$ gcloud functions describe generate_code
Alternatively, there is also the Google Cloud extension for Visual Studio Code that provides you access to your Cloud Functions to access and deploy them.
Again, you can test your deployed Cloud Function at the given URL. Given identical payload in the url
query string parameter the generated PNG image is showing the same QR code as your locally run function earlier.
Google Cloud Function in C#
The steps are similar to the previous ones however we are going to use the project template for Google Cloud Functions to start a new project using the dotnet
CLI tool.
In case you don't have the project template you need to install it. See here for more information: The .NET Runtime
Replace the content of the newly created Program.cs
with the following implementation.
To test your function launch the project.
Either navigate your browser or use curl
to access the URL http://localhost:8080/?url=https://jochen.kirstaetter.name/
to get the generated QR code as PNG image.
Finally, deploy the .NET project to Google Cloud Functions via the gcloud
CLI tool using the following command.
The value of the entry-point
flag is based on the used namespace and type (class) you defined in your project. See also the output of dotnet run
regarding the EntryPoint information. At the time of writing, the two possible values for the runtime
flag were dotnet3
and dotnet6
only. I hope that with the launch of .NET 8 mid of November that a new runtime dotnet8
for Cloud Functions will be available.
Same recommendations as described in the paragraph on Python-based deployment apply. See above for details.
Conclusion
There is no excuse of not generating and using QR codes after you reached this far. As mentioned, we use them to provide unique images for our event registrations which we send out by email. Any registrant coming simply shows us her/his QR code and we are able to check them in quickly. It's a real time-saver.
Please take into consideration that the code snippets in Python and C# above are merely a proof of concept although a powerful and production-ready one. Both libraries qrcode
and QRCoder
offer a ton of features to create more sophisticated QR codes. You can customise your codes with a branded centre image, use different error correction levels, dimensions and colours. I sincerely encourage you to explore those options in the official documentation of each package.
Furthermore, having your own QR code generator online provides independence from any service provider or risk of deprecation. Actually with the described functionality you could start your own QR code Software-as-a-Service product and offer valuable features to others. Combining this blue print with a URL shortener with redirect feature to gather statistics on usage, a user authentication to isolate customers' instances of the Cloud Function from each other, and providing an appealing UX/UI website offering a management of QR code payloads.
Spice it up with a landing page and affordable pricing structure which could potentially kick off a new business.
Hmm, maybe more on that in the future...
Image generated using Bing Image Creator: "A fleet of QR codes in the clouds"