Dec 162011
 

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.

  18 Responses to “Printing QR-code: Part 2”

  1. When can we expect the QR codes to be supported in the designer?

  2. is there a way to specify how many copies of the label you want printed?

  3. Is it possible to change size (width and height) of label objects (like barcodeobject or textobject) and location (left, top) on the fly on C#?

    • The OpenStream(Buffer: Variant) API reads a label file from a buffer (vs. from a file or URL). This API allows you to manage the binary data yourself. You’ll find more information in the SDK manual on page 14.

  4. I get the following error when i try to print a image: getObjectByNameElement(): no object with name ‘Image’ was found on the line barcodeAsImageLabel.setObjectText(‘Image’, pngBase64);
    I put Image in the label-xml but it didn’t help. What could be the problem?

    • First make sure that your *.label file is correct. Please load your *.label file with the latest DLS 8.4.1 version and verify that your *.label file is right. More information about the *.label layout can be found here http://dymodevelopers.wordpress.com/tag/xml/

      • Hi pi

        Thanks for the tip, I did that with v8.4.1 and it had mistake but I am still getting the same error.

        Landscape
        Shipping
        30323 Shipping

        Image

        Rotation0
        False
        False

        Uniform
        0

        Left
        Top

        • <?xml version="1.0" encoding="utf-8"?>
          <DieCutLabel Version="8.0" Units="twips">
          <PaperOrientation>Landscape</PaperOrientation>
          <Id>Shipping</Id>
          <PaperName>30323 Shipping</PaperName>
          <DrawCommands>
          <RoundRectangle X="0" Y="0" Width="2025" Height="5020" Rx="270" Ry="270"/>
          </DrawCommands>
          <ObjectInfo>
          <ImageObject>
          <Name>Image</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>
          <Image></Image>
          <ScaleMode>Uniform</ScaleMode>
          <BorderWidth>0</BorderWidth>
          <BorderColor Alpha="255" Red="0" Green="0" Blue="0"/>
          <HorizontalAlignment>Left</HorizontalAlignment>
          <VerticalAlignment>Top</VerticalAlignment>
          </ImageObject>
          <Bounds X="321" Y="58.00006" Width="4612" Height="1884"/>
          </ObjectInfo>
          </DieCutLabel>

  5. QR Code only picks up first line of text in object. How can I change this to pick up all lines (7 lines) of text in object?
    Thanks

    • It is best to create the template in DLS. Lay out all of the objects that are required for your label. Simply put a barcode object on your label, make sure it is named appropriately and set the data in code.

      • Is it possible to print a label from Excel 2007, I’ve tried several examples using VBA but the code only seems to print the last label that was printed using DLS and not the cell value, ideally I need an example of printing a label with two text objects text1 & text2, cell A1 to populate text1 and cell b1 to populate text2.

        Thank you

  6. Can the library support formatting the label using table with border? If no, any ways that similar effect can be made?

    • Hi Stephen,

      Formatting label using DYMO SDK or in DLS ? Can you pls describe more about your issue with some example.

      Thanks

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>