As you know by now, I'm somewhat biased towards pixel-exact printing on strange printers. This time around, I was tasked with requirement to make Koha print bar-code labels from web interface on Zebra S4M printers which are locally connected to Windows clients over USB.
At first sight, this seems like an easy task. Zebra printers are supported under CUPS on Linux and OSX, so there shouldn't be any problems, right? For a start I found out that CUPS driver doesn't work well, mostly because it's older that Windows version of driver, and doesn't seem to send all ZPL codes required to print label.
To make thing even worse, since printer is connected locally to Windows machine, it presents itself as Windows GDI printer which doesn't want to print ZPL (printer protocol) directly without wrapping ZPL in magic quotes and enabling it in Windows.
On the other side, Koha tries to print labels using normal print dialog in Windows. This won't work well, because we (again) need pixel exact label as opposed to web page randomly scaled to printer label. To make this worse, client Windows machines are behind firewall, so I can't send label to IP address of client because all I can see in request is IP address of our firewall.
To solve all this problem I decided to deploy following setup:
- Label design is done in Inkscape. To rasterize it to bitmap I decided to use rsvg-convert which has nice option to create exact bitmap size from SVG file in which I replace placeholders with variable values (bar-code and call number)
- Printers are installed in Windows using Generic/Text driver which is only one which will just pass data directly to printer
- To share printer to Linux, I decided to install lpd server so I don't have to open local Windows accounts to access printer (and they are behind firewall, so It's safe)
- To get local IP address of client (so I can send ZPL to internal IP address on which lpd is listening) I decided to redirect client to internal web server (behind firewall, same as clients) which knows client IP address, and knows where to send label.
- From user's perspective, Koha redirects clients to internal CGI script, which in turn rasterize label from request parameters, sends it to printer and redirect browser back to Koha page (with additional parameter of IP address of client/printer). This page shows label which was just printerd by pointing directly to internal server's PNG rendering of label. It also inserts data about printed label (including printer IP) in database for audit log.
Since I couldn't use CUPS to produce ZPL for printer, I wrote Printer-Zebra which can convert pbm and pnm formats (easily created from png label using pgntopnm). Even better, it also includes script which can render ZPL printer output back to pbm bitmap which is the only good way to verify that your solution doesn't anti-alias bar-codes or does something similar to reduce print quality on back and white printers. Rasterizer was also very useful when tracking differences between Windows driver output (gathered by printing to File on Windows) and CUPS one.