Hi there 😁,
Thank you for clicking on this article, I hope you enjoy it, despite its very "niche" nature....
But hey, this adventure happened to me in December 2024, so I figured I'd make an article out of it.
Are you ready? Let's get started!
Without realizing it, you use them every day. For example, on your packages ordered online, there are labels.
These self-adhesive labels are created using a label printer. The one I'm most familiar with is from Zebra.
Unlike a conventional printer, label printers can be easily programmed with a relatively simple set of instructions. In fact, you can play around with this instruction set on the "ZPL Viewer".
As far as I'm concerned, the last time I worked with ZPL and this type of printer, before December 2024, was in 2021, when we created the Frères Marchand online cheese shop.
And yes, when you order, the label on your parcel with your address has been printed with a Zebra printer... When I say you use one every day 😁.
In December 2024, I was contacted for several interventions on a C# code that communicates with a Zebra printer.
The first intervention was simple: after changing the hardware (the printer), some images were no longer displayed on the labels.
After a few minutes of searching through the code, I discovered that the ZPL instruction was using a "GFE" with a file that had been loaded into the printer.
Except that the printer had changed in the meantime...
And more importantly, on this type of printer and in this type of environment, it can be replaced at any time. In our case, since it's used to apply labels to parcels, the printer is in high demand every day... and the last thing we want is any downtime.
So it was quite simple: I replaced the "GFE" instruction with a "GFA" instruction with the image encoded. I won't go into too much detail here, as we'll be going into even more detail later on in this article.
Next, I was called in for a second intervention. This time, certain information on the label had to be available in Arabic, when the parcel was destined for an Arabic-speaking country... and that was more work.
For the record, I did this job when I'd just caught the raging flu of late 2024/early 2025... It was fun.
The problem with Arabic is that it's a non-Latin alphabet. To print in this alphabet with a Zebra printer, you'd normally have to add fonts to the printer.
Except, as mentioned above, we don't want to do that.
So we had to find another solution.
Here, we'll go into more detail about the process. Then, below, I'll give you the bonus test code I created to get the job done.
As mentioned, we don't want to add any files to the printer, but we can exploit the standard tools available on all Windows machines.
In fact, there's a C# library for creating images, so we can generate an image containing Arabic text.
This library is called "System.Drawing". You can download it from NuGet in Visual Studio.
With this library, you can create "bitmap" images in C#, and it's child's play.
You'll be able to create an image containing your text, which you can then pass on to other functions.
According to my research, a Zebra printer can only handle black and white, not grayscale.
The problem is that the image generated with the text contains grayscale, particularly in the character "borders".
We therefore need to transform this image into black and white.
To do this, we're going to create a function that scans the image, checks whether each pixel is closer to white or black, and converts it completely to black or white.
Don't worry, you'll find the complete code at the end of this article.
Now that our bitmap is in black and white, we need to transform it into a ZPL instruction.
A GFA instruction in ZPL takes 3 main arguments. In the test code I'll give below, before the GFA, there's a code that indicates where to place the image on the label. But for the moment, let's concentrate on the GFA.
Here are the three arguments:
BitConverter.ToString()
.This part, as you'll have guessed, corresponds to what I did the first time to put the logos back on a printer that contains no files in internal memory.
At this point, as you'll have guessed, we're done. The instruction is ready to be sent to the printer.
Here I give you the complete code for the steps in the previous chapter. You can reuse it in your own C# project.
Some parts can be a little tricky, for example when it comes to scanning the bitmap to determine whether a pixel is black or white.
But on the whole, the code remains quite readable!
As you can see, I've added some lines specific to my use. For example, I use "Segoe UI" when the text is in Arabic, simply because this font works very well with Arabic.
This rather exotic article is coming to an end...
I'm well aware that it differs from what I usually write, but what can I say? Sometimes, we have to write things that are completely out of our usual frame of reference (and I don't mind that!).
Have a great week and see you next time 😁.