Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

Pre-rendering graphics in ZPL label printers

by cavac (Curate)
on Oct 02, 2018 at 13:31 UTC ( #1223401=CUFP: print w/replies, xml ) Need Help??

I've been working quite a lot with ZPL compatible label printers (Zebra, TSC) the last few years. When working with complex forms or large graphics, printing can be quite slow, because the printer has to - basically - calculate everything pixel-by-pixel for every single label. Not to mention the fact that the standard ZPL image format is not... well "nice" to work with with standard open source tools.

ZPL has a way to store a rendered label, which it can reuse later quite a bit faster (in most cases). Basically, you load in the saved, pre-rendered label and then add you dynamic content.

Here is the Perl script to convert a PNG file to ZPL, including the "save" command. E.g. this generates the ZPL file to pre-render the image and save it to the printers flash memory.

#!/usr/bin/env perl use strict; use warnings; use GD; use Data::Dumper; my $xoffs = 20; my $yoffs = 20; my $minwhite = 200; my $verbose = 0; my $image = GD::Image->new('examplelogo.png'); my $w = $image->width(); my $h = $image->height(); print "Image size: $w x $h\n"; open(my $ofh, '>', 'savelogo.zpl') or die($!); # Start of form; print $ofh "^XA\n"; for(my $x = 0; $x < $w; $x++) { for(my $y = 0; $y < $h; $y++) { my $index = $image->getPixel($x,$y); my ($r,$g,$b) = $image->rgb($index); if($r < $minwhite) { print "#" if $verbose; print $ofh '^FO' , ($x*1) + $xoffs, ',' , ($y*1) + $yoffs, + '^GB1,1,1,B,0^FS', "\n"; } else { print " " if $verbose; } } print "\n" if $verbose; } # Save graphic to flash mem print $ofh "^ISR:LOGO.GRF,Y\n"; # End of form print $ofh "^XZ\n"; close $ofh;

$xoffs and $yoffs change the upper left starting point where the image is drawn and $minwhite sets the threshold of what is considered a white vs. black pixel. This generates ZPL code like this (abbreviated), setting one pixel black per line:

^XA ^FO55,74^GB1,1,1,B,0^FS ^FO55,75^GB1,1,1,B,0^FS ^FO55,76^GB1,1,1,B,0^FS ^FO55,77^GB1,1,1,B,0^FS ^FO55,78^GB1,1,1,B,0^FS ... ^FO561,126^GB1,1,1,B,0^FS ^FO561,127^GB1,1,1,B,0^FS ^FO561,128^GB1,1,1,B,0^FS ^ISR:LOGO.GRF,Y ^XZ

To actually save the image to the printer, on Linux you would run something like this if you run CUPS:

lpr -P yourprintername -o raw savelogo.zpl

Now you can use the saved image in a normal label print by loading it at the start:


and then printing it:

lpr -P yourprintername -o raw label.zpl

Of course, this can trivially be used for dynamic content. But i leave it to the reader to figure out how to load label.zpl, replace XXCAPTIONXX with an increasing number, saving it to tmp.zpl and calling lpr...

You also can get the whole example (including a badly made example png) with Mercurial SCM:

hg clone

Have fun!

"For me, programming in Perl is like my cooking. The result may not always taste nice, but it's quick, painless and it get's food on the table."

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://1223401]
Approved by marto
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (5)
As of 2021-03-01 16:45 GMT
Find Nodes?
    Voting Booth?
    My favorite kind of desktop background is:

    Results (13 votes). Check out past polls.