How to print a logo on labels using a Zebra printer and sending ZPL instructions to it
Asked Answered
F

9

12

I would like send ZPL instructions to a Zebra printer (GK420t for now). I'm printing 50mm x 20mm labels. I would like a logo (small ~ 5mm x 5mm image) to be printed on the upper left corner of the label.

I would like to know the steps I should follow to do this.

I have been reading and trying a few things from the ZPL manual but I don't really understand how it works and couldn't find a working example.

It looks like I have to "load" the image into the printer first (in a so-called "storage area"/DRAM?) and then print it.

The .GRF file extension is mentioned many times in the manual. I couldn't find the tool to convert a .PNG or .BMP image into a .GRF file. I read that a .GRF file is an ASCII HEX representation of a graphic image... but it didn't help me do the work.

I could print the logo on the labels using the "Zebra Setup Utilities", by "Downloading Fonts and Graphics", choosing any available .MMF file, adding a .BMP picture, downloading it [to the printer] and printing a test page. But until now, I couldn't do it using ZPL instructions.

I am also wondering what are the best dimensions I should use given the fact that I need a small image ~5mm x 5mm to be printed on the labels. The image I printed is a 40px x 40px image. Also, if I have to make a .GRF file from an original image what should be the type of this file (.BMP, .PNG, .JPG)?

Can you advise me how to proceed?

Falter answered 25/3, 2015 at 10:44 Comment(1)
I think that what I need is an utility that will take the original image and create the byte representation of it (.GRF file?). I can't seem to find this tool.Retrograde
B
27

It sounds like you have some existing ZPL code, and all you want to do is add an image to it.

If that's the case, the easiest solution is probably to go to the Labelary online ZPL viewer, paste your ZPL into the viewer, click "Add image", and upload the image that you want to add to the ZPL.

This should modify your ZPL by adding the image ZPL commands that you need, and you can then tweak the position, etc.

Bersagliere answered 3/4, 2015 at 17:16 Comment(0)
P
6

Here is another option: I created my own image to .GRF converter in python. Feel free to use it.

from PIL import Image, ImageOps
import re
import itertools
import numpy as np

# Use: https://www.geeksforgeeks.org/round-to-next-greater-multiple-of-8/
def RoundUp(x, multiple_of = 8):
    return ((x + 7) & (-1 * multiple_of))

def image2grf(filePath, width = None, height = None, rotate = None):
    image = Image.open(filePath).convert(mode = "1")

    #Resize image to desired size
    if (width != None):
        size = (width, height or width)
        if (isinstance(size[0], float)):
            size = (int(size[0] * image.width), int(size[1] * image.height))

        #Size must be a multiple of 8
        size = (RoundUp(size[0]), RoundUp(size[1]))


        # image.thumbnail(size, Image.ANTIALIAS)
        image = image.resize(size)

    if (rotate != None):
        image = image.rotate(rotate, expand = True)

    image_asArray = np.asarray(np.asarray(image, dtype = 'int'), dtype = 'str').tolist()
    
    bytesPerRow = len(image_asArray[0])
    nibblesPerRow = bytesPerRow // 4
    totalBytes = nibblesPerRow * len(image_asArray)

    #Convert image to hex string
    hexString = "".join(
        format(int("".join(row[i*4:i*4 + 4]), 2) ^ 0xF, "x")
        for row in image_asArray
        for i in range(nibblesPerRow) 
    )

    #Compose data
    data = "~DGimage," + str(totalBytes // 2) + "," + str(nibblesPerRow // 2) + "," + hexString

    #Save image
    fileHandle = open(r"labelPicture.grf", "w")
    fileHandle.write(data)
    fileHandle.close()

if __name__ == '__main__':
    # image2grf(r"warning.bmp")
    image2grf(r"pallet_label_icons.png", rotate = 90)

Edit: I updated the code above to use my new conversion method, which produces better resolution GRF files

Preciosity answered 20/1, 2017 at 13:25 Comment(6)
Bug ?: On line26 NameError: name 'totalBytes' is not defined ... So I replaced totalBytes with previously defined bytesPerRow, only because it seems to make sense. Et voilá, no more errors, the .GRF file is being generated, I can open it with editor, but the .GRF format seems to be corrupted. No viewer / converter can handle it without errors. :-(Buttock
@Buttock Oops! Looks like I am missing a line in the script. Good catch. I have updated the answer.Preciosity
Thanks for your efforts, but still no success. I added ZPL code, image is being printed, but still scrambled. Code snippets of ZPL file: Your code (file name adapted) ~DGR:AVATAR.GRF,3485,20,aed89d2522912245b40e2524a4... followed by this line ^XA^FO20,20^XGR:AVATAR.GRF,1,1^FS^XZ. Can you try this ?Buttock
@Buttock Looks like your code was cut off due to the character length. Could you email it to me? I will post my email in the next comment so I can delete it later. :) I'll help you figure things out- then post any changes that needed to be made to the answer above so others can benefit from it.Preciosity
The above code worked for him when we ran it exactly as written above.Preciosity
thanks for your effort with code correction. Now it's running. 1 up.Buttock
U
3

Just install ZebraDesigner, create a blank label, insert a image object to the template and add the required logo image.

Print to File this label (a *.prn file) and open the recently created file with Notepad++ (MS Notepad will ruin the data if opened and saved with). Find a huge string of seemingly random characters, and there is your image's data. Careful not to lose any of those characters, including the control ones, as the whole string is a textual representation of your image (as it would be if it were base64).

Tip0: Always have your ZPLII Programmer's Guide at hand, you'll need/want to check if ZebraDesigner sent the image to memory or directly to the printer buffer.

Tip1: Before adding the logo to the label and get the text, prepare the image making it greyscale (remember to check the printer's dithering configuration!) or, in my case, plain black and white (best result IMHO). The image can be colored, the ZebraDesigner will make it work for the printer converting the image to greyscale before conversion to commands and text.

Unmade answered 26/4, 2016 at 14:38 Comment(0)
B
1

I created a PHP script to convert PNG images to .GRF similar to Josh Mayberry's image2grf.py: https://gist.github.com/thomascube/9651d6fa916124a9c52cb0d4262f2c3f

It uses PHP's GD image function and therefore can work with all the file formats GD can open. With small modifications, the Imagick extension could be used but performance seems to be better with GD.

Byrnes answered 11/7, 2018 at 8:8 Comment(1)
There is no license specified in the code... May we copy, modify and use it for any purpose?Higginson
H
1

I had to figure this out again today. In the ZPL code, you can output the graphic bytes for every single label (which means a lot of additional data when you're printing a few thousand labels), or you can define the image first and then refer to it.

I used an online ZPL viewer to save on the number of labels printed when testing. I used: http://staging.advanced-technology-group.com/ and here is another that does the same: http://labelary.com/viewer.html

These (currently) have an 'add image' function. This transfers a png to the GRF format that ZPL works with (see the other answers if you need to generate these bytes yourself).

Outputting the bytes for every label

Using the "Add image" function generates a command and the graphic bytes, which looks like:

^FO50,50^GFA,11118,11118,17,,<lots of data>

You can adjust the FO as that tells the printer where to position the graphic. That should be fine for shorter runs / smaller pictures / you're in a hurry.

Downloading the image once and then referring

This is what I had to do, so I needed to rearrange the bytes a bit (nice pun?). THe ^GF command stands for Graphic Field: ^GFa,b,c,d,data where

a: A|B (A, non-binary, B = binary)
b: number of bytes transmitted
c: number of bytes comprising the graphic format
d: number of bytes per row

and what I needed to do is to reformat this as ~DGR:000.GRF,11118,17,, so that I could refer to it with ^XGR:000.GRF,1,1. After the print run, I'd need to delete the graphic from memory again with: ^ID000.GRF

The properties for ~DGd:o.x,t,w,data mean

d: memory destination - R for RAM
o: image name (1-8 alphanumeric chars)
x: filename extension, always GRF
t: number of bytes in the graphic
w: number of bytes per row

So I turned: ^FO50,50^GFA,11118,11118,17,,<data> into: ~DGR:000.GRF,11118,17,,<data>

This definition goes before the label-definition, so:

~DGR:000.GRF,11118,17,,<data>
^XA (start of label)
...
^FT360,700^XGR:000.GRF,1,1^FS <-- this outputs the graphic
...
^XZ (end of label)
^ID000.GRF
Heavenward answered 23/9, 2022 at 9:24 Comment(0)
I
0

Try codeproject's sharpzebra project. The test program that is part of project prints a graphic and I know this works at least it did on a ZM400

Ixion answered 25/3, 2015 at 13:44 Comment(0)
L
0

go to Object ==> Picture and your curser will change to something else.. when it changed go and click on the working area and a dialog box iwll apear... so on there select the image so you can see the image whant you wanna print on the printer i am using GT800 so for me i did like that hope this will helps you

Laroy answered 13/6, 2017 at 14:41 Comment(0)
S
0

Use ZebraNet Bridge Enterprise Software to convert BMP to GRF file format

Stiltner answered 15/9, 2022 at 1:50 Comment(0)
C
0

You can try my lib for more details has working app and libs for images

https://github.com/nssoftengineer/BluetoothPrinter

Carrero answered 24/4 at 7:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.