The previous post demonstrated different ways of printing QR-code from a .NET application. This blog post will demonstrate how to achieve the same goal from a web application. The complete sample is available here. The corresponding JavaScript is here.
Prerequisites
First, make sure the latest DYMO Label software is installed. It is always available on DYMO web-site, at the time of writing it is version 8.3.1.
Use Barcode Object
The easiest way to print QR-code is to use built-in support for QR-code in DYMO Label Framework. First, design your label using DYMO Label software. Unfortunately, DYMO Label itself does not have ability to specify QR-code barcode type in the UI yet. So, add the Barcode object to the label and put it into desired position. Don’t specify the barcode symbology, use the default Code39. Save the label in to a file, open the file in any XML editor and change thetag to “QRCode”.
<BarcodeObject>
<Name>Barcode</Name>
<ForeColor Alpha="255" Red="0" Green="0" Blue="0" />
<BackColor Alpha="0" Red="255" Green="255" Blue="255" />
<LinkedObjectName></LinkedObjectName>
<Rotation>Rotation0</Rotation>
<IsMirrored>False</IsMirrored>
<IsVariable>False</IsVariable>
<Text></Text>
<Type>QRCode</Type>
<Size>Large</Size>
<TextPosition>None</TextPosition>
<TextFont Family="Arial" Size="8" Bold="False" Italic="False" Underline="False" Strikeout="False" />
<CheckSumFont Family="Arial" Size="8" Bold="False" Italic="False" Underline="False" Strikeout="False" />
<TextEmbedding>None</TextEmbedding>
<ECLevel>0</ECLevel>
<HorizontalAlignment>Left</HorizontalAlignment>
<QuietZonesPadding Left="0" Top="0" Right="0" Bottom="0" />
</BarcodeObject>
See Barcode.label from the sample. After the label is ready, the actual steps to print it is quite easy: open the label, set desired data, print. Here is a snippet from the sample:
printButton.onclick = function()
{
try
{
if (!barcodeLabel)
throw "Load label before printing";
if (!printersSelect.value)
throw "Select printer.";
barcodeLabel.setObjectText('Barcode', 'http://developers.dymo.com');
barcodeLabel.print(printersSelect.value);
}
catch(e)
{
alert(e.message || e);
}
}
First, we check that the label is loaded and the printer is selected. Next, the barcode data is set to be the blog’s URL. And finally, the label is printed.
Use Image Object
Printing QR-code by using Barcode object is easy. The only drawback, it is hard to control the actual barcode size. tag can be used for that but it support only three predefined sizes Small/Medium/Large, but still the overall size will depend on the actual barcode data. The longer the data string, the larger is the barcode. So, the idea is to use some library to generate QR-code image of desired size, and then print it using the Image object. As before, design a label using DYMO Label software. Put an Image object on the label where the barcode should be printed. Set the Image objet size to the desired barcode size. When specifying the barcode image size in pixels calculate it based on the printer resolution, that is 300 dpi for LabelWriter printers and 180 dpi for Tape printers. For example, if you want the barcode to be 1” in size, specify the barcode image size as 300×300 pixels. See BarcodeAsImage.label from the sample project.
Image object accepts image data as a string that contains base64-encoded png stream. The question is, how to get/generate this string. Again, there are several ways of doing that.
Generate and base64-encode QR-code image on the server-side
One way is to generate QR-code image on the server using some library. Then encode the image using base64 and return it to the client as a string. Finally, on the client side, call setObjectText on the Image object and print.
printAsImageButton.onclick = function()
{
try
{
if (!barcodeAsImageLabel)
throw "Load label before printing";
if (!printersSelect.value)
throw "Select printer";
$.get("qr.base64", function(qr)
{
try
{
barcodeAsImageLabel.setObjectText('Image', qr);
barcodeAsImageLabel.print(printersSelect.value);
}
catch(e)
{
alert(e.message || e);
}
}, "text");
}
catch(e)
{
alert(e.message || e);
}
}
In the sample, we just request “qr.base64” resource that contains precalculated QR-code image for “http://developers.dymo.com”. In real application, you will probably pass the data to be encoded as a resource parameter.
Generate QR-code image on the server-side and base64-encode it on the client-side.
Base64-encoded strings are larger then binary png data. So, to reduce network traffic, we can return original png data from the server and base64-encode it on the client. To encode the data we will create , render our image on it, and then get encoded data using canvas.toDataURL() method.
printAsImageCanvasButton.onclick = function()
{
try
{
if (!barcodeAsImageLabel)
throw "Load label before printing";
if (!printersSelect.value)
throw "Select printer.";
var img = new Image();
img.onload = function()
{
try
{
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
var dataUrl = canvas.toDataURL('image/png');
var pngBase64 = dataUrl.substr('data:image/png;base64,'.length);
barcodeAsImageLabel.setObjectText('Image', pngBase64);
barcodeAsImageLabel.print(printersSelect.value);
}
catch(e)
{
alert(e.message || e);
}
};
img.onerror = function()
{
alert('Unable to load "qr.png"');
};
img.src = 'qr.png';
}
catch(e)
{
alert(e.message || e);
}
}
Note: image loading is asynchronous process. So, we can’t just assign img.src property and immediately draw it on a canvas; we have to wait until the image is loaded completely from the server. To handle that, we do main work in onload handler. also, toDataURL returns data url, to get the data itself, we have to remove the url prefix.
Again, as in the previous case, qr.png resource contains recalculated QR-code image for “http://developers.dymo.com”. In real application, you will probably pass the data to be encoded as a resource parameter.
A drawback of this method is that it requires support in the browser. All major browsers already support it, but be aware that in Internet Explorer it is supported starting from version 9 only.
Use third-party service
Instead of generating QR-code image on your own server, is it possible to use one of the many free online QR-code generator/service? The answer is yes, but it is even more trickier than the previous way. The problem, as usual in web development, is the security. But default is it not possible to grab canvas pixels if an image from a different domain has been drawn on the canvas. It is possible to overcome it, but it requires three parties to participate properly. First, your JavaScript has to set img.crossOrigin property to ‘anonymous’. This will tell the browser that you are trying to access a cross-domain resource, so the browser can send appropriate request headers, e.g. the browser will not send cookies. Next, the server itself should allow its resources to be accessible from other domains. Only few of many QR-code online generators do allow it. And the last, the browser itself should support CORS for . It is very recent addition to the standards, so at the time of writing only Chrome does support it. In any other browsers you will still get “security exception” error. Here are some links regarding and cross-domain limitations:
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#security-with-canvas-elements
http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html
http://code.google.com/p/chromium/issues/detail?id=82042
Update (2011-12-20): works in Firefox 9 as well.
printAsImageCanvas2Button.onclick = function()
{
try
{
if (!barcodeAsImageLabel)
throw "Load label before printing";
if (!printersSelect.value)
throw "Select printer.";
var img = new Image();
img.crossOrigin = 'anonymous';
img.onload = function()
{
try
{
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
var dataUrl = canvas.toDataURL('image/png');
var pngBase64 = dataUrl.substr('data:image/png;base64,'.length);
barcodeAsImageLabel.setObjectText('Image', pngBase64);
barcodeAsImageLabel.print(printersSelect.value);
}
catch(e)
{
alert(e.message || e);
}
};
img.onerror = function()
{
alert('Unable to load qr-code image');
};
img.src = 'https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl=http%3A//developers.dymo.com&choe=UTF-8';
}
catch(e)
{
alert(e.message || e);
}
}
The code is very similar to the previous example. The only difference is that we set img.crossOrigin property and we use Google’s Infographics API to generate the qr-code image. Notice that in this example the image is generated dynamically, and barcode data is passed as the part of the url.
Pure client-side JavaScript
At the time of writing, it seems there is no self-contained pure JavaScript solutions to create QR-code images using <canvas> completely on the client-side. In the future it might be one more way of doing QR-code printing.
Conclusion
It is quite simple to print QR-code barcode even if built-in support is somewhat limited.