6

I need to print a PNG image onto a label with a ZPL printer. The idea is to convert the PNG image to a monochrome one and then generate the necessary ZPL code with the image data to print the image.

After some googling and coding, I have a piece of code that does just that. The generated ZPL code seems fine on labelary (http://labelary.com).

The code for generating the ZPL code was mostly taken from here --> How to optimize ASCII HEX for BMP to ZPL as using in Labelary

Unfortunately, when trying to print a label with the generated ZPL code, it comes out like this: Not supposed to look like this

Image should look like this: ImageToConvert

The code that i use is this:

static void Main(string[] args)
    {

        // 1. Convert Image to monochrome bmp
        string bitmapFilePath = @"somepath.bmp";
        Bitmap imageToConvert = new Bitmap(bitmapFilePath);
        var rectangle = new Rectangle(0, 0, imageToConvert.Width, imageToConvert.Height);
        Bitmap monochromeImage = imageToConvert.Clone(rectangle, PixelFormat.Format1bppIndexed);

        // Mirror image
        monochromeImage.RotateFlip(RotateFlipType.Rotate180FlipX);

        // Save mono image            
        monochromeImage.Save("somePathMono.bmp", ImageFormat.Bmp);

        // 2. Convert to ZPL
        ConvertImage();   

    }

    public static void ConvertImage()
    {
        string bitmapFilePath = "somePathMono.bmp";
        int w, h;
        Bitmap b = new Bitmap(bitmapFilePath);
        w = b.Width; h = b.Height;
        byte[] bitmapFileData = System.IO.File.ReadAllBytes(bitmapFilePath);
        int fileSize = bitmapFileData.Length;

        int bitmapDataOffset = int.Parse(bitmapFileData[10].ToString()); ;
        int width = w; // int.Parse(bitmapFileData[18].ToString()); ;
        int height = h; // int.Parse(bitmapFileData[22].ToString()); ;
        int bitsPerPixel = int.Parse(bitmapFileData[28].ToString()); 
        int bitmapDataLength = bitmapFileData.Length - bitmapDataOffset;
        double widthInBytes = Math.Ceiling(width / 8.0);

        while (widthInBytes % 4 != 0)
        {
            widthInBytes++;
        }

        // Copy over the actual bitmap data without header data            
        byte[] bitmap = new byte[bitmapDataLength];

        Buffer.BlockCopy(bitmapFileData, bitmapDataOffset, bitmap, 0, bitmapDataLength);           

        // Invert bitmap colors
        for (int i = 0; i < bitmapDataLength; i++)
        {
            bitmap[i] ^= 0xFF;
        }             

        // Create ASCII ZPL string of hexadecimal bitmap data
        string ZPLImageDataString = BitConverter.ToString(bitmap);            
        ZPLImageDataString = ZPLImageDataString.Replace("-", string.Empty);

        // Add new line every 1023 chars characters
        string ZPLImageDataStringWithNewLine = SpliceText(ZPLImageDataString, 1023);            

        // Create ZPL command to print image
        string ZPLCommand = string.Empty;

        ZPLCommand += "^XA";
        ZPLCommand += "^FO20,20";
        ZPLCommand +=
        "^GFA," +
        bitmapDataLength.ToString() + "," +
        bitmapDataLength.ToString() + "," +
        widthInBytes.ToString() + "," +
        System.Environment.NewLine +
        ZPLImageDataStringWithNewLine;

        ZPLCommand += "^XZ";

        System.IO.StreamWriter sr = new System.IO.StreamWriter("zplCodePath", false, System.Text.Encoding.Default);

        sr.Write(ZPLCommand);
        sr.Close();       
    }

    public static string SpliceText(string text, int lineLength)
    {
        return Regex.Replace(text, "(.{" + lineLength + "})", "$1" + Environment.NewLine);
    }

We use the Zebra ZT 410 printer

Can someone help me figure out what the problem could be? I'm out of ideas at this point.

Thanks!

UPDATE: Seems like the problem is the newline that I put after every x characters in the image data. I don't understand why. My code works perfectly for smaller image (where I don't have to put new lines), but for big images with long imagedata strings it does not print if I don't put the new lines.

Any help would be appreciated!

Lenquist
  • 61
  • 1
  • 1
  • 3
  • Im confused, it looks like your image is an R with a barcode underneath it? Why not just draw and R with text and correctly base the barcode code in the zpl? – Sam Marion Apr 12 '18 at 14:22
  • Is that an example image, or the image you want on all labels? It would likely be easier to generate a large R and the barcode directly in ZPL. – Shane Ray Apr 12 '18 at 14:22
  • Also, I'm pretty sure if you just want to go the image route why not just base64 encode the image and use that? That's what we do with all of our images and it works great. – Sam Marion Apr 12 '18 at 14:26
  • The image provided is just a sample image, the real one is rather complicated and also changes everytime, so recreating it is impossible – Lenquist Apr 12 '18 at 14:35
  • @samMarion do You mean to just encode the byte Array of the image as Base64? Maybe you have an example? – Lenquist Apr 12 '18 at 14:37
  • @Lenquist yeah exactly like so... Convert.ToBase64String(File.ReadAllBytes(imageFilepath)); – Sam Marion Apr 12 '18 at 14:38
  • Then in the ZPL its just ^GFA,###,###,##,:Z64:{base64StringHere} – Sam Marion Apr 12 '18 at 14:43
  • I can pastebin a sample template if you want to see it. – Sam Marion Apr 12 '18 at 15:06
  • That would be helpful, since it does not seem to work for me. Also, the ZPL programming guide does not mention a parameter like :Z64: in GFA or maybe I'm missing something – Lenquist Apr 12 '18 at 15:10
  • Check it out in labelary online viewer 300 dpi https://pastebin.com/y5a1s5qF – Sam Marion Apr 12 '18 at 15:20
  • seems like something is not right with my Base64 conversion. this is the string I get when converting the image I attached above to Base64: https://pastebin.com/bYBktc9d Looks very different than Your image data – Lenquist Apr 12 '18 at 15:27
  • Unfortunately this does not work for me. The Base64 code seems fine, but it wont render the image neither on lablery nor my printer. – Lenquist Apr 13 '18 at 07:45
  • [check this answere](https://stackoverflow.com/a/48892728/7782179), i use that class for prin my labels, i developed an ZPL editor – henoc salinas Apr 18 '18 at 21:34
  • @Lenquist A note on `Z64` and `B64` can be found in the ZPL guide, page 1366. "Introduction to B64 and Z64". – Anthony Feb 04 '19 at 15:42

2 Answers2

3

Because I had such issue with the ZPL guide and various references providing different solutions (that never seemed to fully work with my use-case) I created a simple .net core application which takes a label image and converts it to ZPL, either to a file (if output is provided) or directly to the console so it's pipeable in bash scripts.

nelsontruran
  • 514
  • 4
  • 18
  • 2
    Thanks for your great library. In my case, I had 'index outside bounds array' error, I edit ConvertBitmapToHex method, using List instead of byte[] fixed problem. – Hamidreza Shokouhi Jun 30 '20 at 11:07
  • @HamidrezaShokouhi cheers for letting me know, i'll look into the issue and create a bugfix for that. – nelsontruran Jul 03 '20 at 20:47
0

I was facing same issue, use online tool to convert your png/jpeg to ZPL monochrome format for print and verify your ZPL code on viewer

Sumit
  • 1,022
  • 13
  • 19