How to Print Images with your Zebra Label Printer

A stream of adhesive labels coming out of a barcode label printer
A stream of adhesive labels coming out of a barcode label printer

Zebra printers are the industry standard for rugged, industrial barcode label printing. Many of them utilize a technology known as direct thermal to “burn” images onto the label. This results in a durable image that can withstand the harsh environments in which these labels typically find themselves: warehouses, distribution centers, manufacturing facilities, airports, delivery vehicles, and even your front doorstep (this may be the harshest environment of all, depending on how mischievous your neighbor’s kids are).

Male courier showing damaged box, cheap parcel delivery, poor shipment quality
Mail courier showing damaged box, cheap parcel delivery, poor shipment quality

Despite the many advantages of these rugged labels, there are also some drawbacks. First, you typically have only two color choices: black (a shaded pixel) or white (the absence of a shaded pixel). Second, there are not many intuitive software solutions that support these printers.

When sending a print job to a Zebra printer, one must first convert the document to ZPL, which is a proprietary programming language developed by Zebra. Contrary to modern programming languages, ZPL is not intuitive, nor is it easy to read, write, or maintain. This is why many companies choose to store their label templates in an alternate format, such as the XML-based format used by LabelZoom Studio.

But what if your label format is not known before you need to print it? What if someone sends you a traditional image–such as PNG–and expects you to be able to print it on the fly? Does one of your mission-critical software applications communicate with a 3rd-party service that only transmits images in conventional formats?

If you answered “yes” to any of the questions above, read on to learn how you can use LabelZoom’s online label conversion service to convert images to ZPL in the blink of an eye.

Option 1: Manual Conversion

LabelZoom recently launched an online conversion tool that allows you to convert images to ZPL directly from your web browser. The tool is very simple to use. We were able to convert a PNG logo to ZPL and print it in just 4 steps:

  1. Choose the image file
  2. Press the “Convert” button
  3. Press the “Print” button
  4. Enter the hostname or IP address of the printer (e.g. 192.168.0.44) (not shown)

Option 2: Automated Conversion via Scripting

While the web-based conversion tool is convenient for some, it might not necessarily be the best option for all use cases. For example, if you continually receive a stream of images in a predictable manner, it may be worth your while to automate the conversion process. This is particularly true when connecting two software systems together to allow them to exchange information freely, without human intervention.

Fortunately, LabelZoom has published their API specification which enables us to build our own integrations with the service.

For this example, we’ll be converting from PNG to ZPL, so we need to construct a POST request to https://www.labelzoom.net/api/v2/convert/png/to/zpl (we found this endpoint in the “conversion-controller” section of the API documentation).

With Groovy

The following script will retrieve a file called LabelZoom_Logo_f_400px.png from the current directory of our filesystem, submit it to the web service, and return the result to a variable called zpl:

def post = new URL('https://www.labelzoom.net/api/v2/convert/png/to/zpl').openConnection();
def file = new File('LabelZoom_Logo_f_400px.png')
post.setRequestMethod('POST')
post.setDoOutput(true)
post.setRequestProperty('Content-Type', 'image/png')
post.setRequestProperty('Accept', 'text/plain')
post.getOutputStream().write(file.bytes)
def postRC = post.getResponseCode()
if (!postRC.equals(200)) {
    throw new RuntimeException("API returned status $postRC")
}
def zpl = post.getInputStream().getText()
println(zpl)

If you’re feeling ambitious and also want to print the ZPL, just open a TCP socket to the printer on port 9100 and send the text (NOTE: This will bypass the OS print queue). Replace 1.2.3.4 below with your printer’s IP address or hostname:

try(def socket = new Socket('1.2.3.4', 9100); def p = new PrintWriter(socket.getOutputStream())) {
    p.write(zpl)
}

With Python

This script has the same behavior as the Groovy script above, but it is written in Python:

import requests

with open('LabelZoom_Logo_f_400px.png', 'rb') as f:
    image_data = f.read() 
url = 'https://www.labelzoom.net/api/v2/convert/png/to/zpl'
headers = { 'Content-Type': 'image/png', 'Accept': 'text/plain' }
response = requests.post(url, data=image_data, headers=headers)
try:
    zpl = response.text
    print(zpl)
except requests.exceptions.RequestException:
    print(response.text)

And, same as with Groovy, bonus points for sending the ZPL to the printer:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('1.2.3.4', 9100))
s.sendall(str.encode(zpl))
s.close()

With C# .NET

This was written in .NET Core 6.0, but should be compatible with earlier versions of .NET Framework.

To convert the image to ZPL:

using (var client = new HttpClient())
{
    using (var request = new HttpRequestMessage(HttpMethod.Post, "https://www.labelzoom.net/api/v2/convert/png/to/zpl"))
    {
        var bytes = File.ReadAllBytes("C:\\Users\\Rob\\Desktop\\page-0.png");
        using (var content = new ByteArrayContent(bytes))
        {
            content.Headers.Add("Content-Type", "image/png");
            request.Content = content;
            using (var response = await client.SendAsync(request))
            {
                response.EnsureSuccessStatusCode();
                var zpl = await response.Content.ReadAsStringAsync();
                Console.WriteLine(zpl);
            }
        }
    }
}

To send the ZPL to the printer:

using (var client = new TcpClient("1.2.3.4", 9100))
using (var stream = client.GetStream())
{
    byte[] data = Encoding.ASCII.GetBytes(zpl);
    stream.Write(data, 0, data.Length);
}

With PowerShell

Perhaps the simplest of all, the following PowerShell one-liner will POST an image called LabelZoom_Logo_f_400px.png from the current directory and return the ZPL to the console:

Invoke-RestMethod -Method POST -Uri https://www.labelzoom.net/api/v2/convert/png/to/zpl -ContentType image/png -InFile LabelZoom_Logo_f_400px.png

Unfortunately, we were having some difficulty sending the ZPL to the printer using the Out-Printer command, but if we figure it out, we’ll be sure to update this post.

Other languages

Want to see code snippets in other languages? Let us know in the comments section below! 👇

Also, feel free to follow us on GitHub; we frequently post new code snippets as our engineers learn new tricks out in the field.