How to generate a dynamic GRF image to ZPL ZEBRA print

21,869

Solution 1

Try the following code. Not tested!

public static string CreateGRF(string filename, string imagename)
{
    Bitmap bmp = null;
    BitmapData imgData = null;
    byte[] pixels;
    int x, y, width;
    StringBuilder sb;
    IntPtr ptr;

    try
    {
        bmp = new Bitmap(filename);
        imgData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);
        width = (bmp.Width + 7) / 8;
        pixels = new byte[width];
        sb = new StringBuilder(width * bmp.Height * 2);
        ptr = imgData.Scan0;
        for (y = 0; y < bmp.Height; y++)
        {
            Marshal.Copy(ptr, pixels, 0, width);
            for (x = 0; x < width; x++)
                sb.AppendFormat("{0:X2}", (byte)~pixels[x]);
            ptr = (IntPtr)(ptr.ToInt64() + imgData.Stride);
        }
    }
    finally
    {
        if (bmp != null)
        {
            if (imgData != null) bmp.UnlockBits(imgData);
            bmp.Dispose();
        }
    }
    return String.Format("~DG{0}.GRF,{1},{2},", imagename, width * y, width) + sb.ToString();
}

Solution 2

One thing to point out is that the bitmap being converted must be monochrome (that is, 1 bit per pixel). There is an example on Zebra's knowledgebase that demonstrates printing a simple monochrome image in ZPL: https://km.zebra.com/kb/index?page=answeropen&type=open&searchid=1356730396931&answerid=16777216&iqaction=5&url=https%3A%2F%2Fkm.zebra.com%2Fkb%2Findex%3Fpage%3Dcontent%26id%3DSA304%26actp%3Dsearch%26viewlocale%3Den_US&highlightinfo=4194550,131,153#. If you can convert your images into monochrome bitmaps, then you should be able to follow that example.

// Given a monochrome bitmap file, one can read
// information about that bitmap from the header
// information in the file.  This information includes
// bitmap height, width, bitsPerPixel, etc.  It is required
// that a developer understands the basic bitmap format and
// how to extract the following data in order to proceed.
// A simple search online for 'bitmap format' should yield
// all the needed information.  Here, for our example, we simply
// declare what the bitmap information is, since we are working
// with a known sample file.

string bitmapFilePath = @"test.bmp";  // file is attached to this support article
byte[] bitmapFileData = System.IO.File.ReadAllBytes(bitmapFilePath);
int fileSize = bitmapFileData.Length;

// The following is known about test.bmp.  It is up to the developer
// to determine this information for bitmaps besides the given test.bmp.
int bitmapDataOffset = 62;
int width = 255;
int height = 255;
int bitsPerPixel = 1; // Monochrome image required!
int bitmapDataLength = 8160;
double widthInBytes = Math.Ceiling(width / 8.0);

// Copy over the actual bitmap data from the bitmap file.
// This represents the bitmap data without the header information.
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);

// Create ZPL command to print image
string[] ZPLCommand = new string[4];

ZPLCommand[0] = "^XA";
ZPLCommand[1] = "^FO20,20";
ZPLCommand[2] =
    "^GFA, " +
    bitmapDataLength.ToString() + "," +
    bitmapDataLength.ToString() + "," +
    widthInBytes.ToString() + "," +
    ZPLImageDataString;

ZPLCommand[3] = "^XZ";

// Connect to printer
string ipAddress = "10.3.14.42";
int port = 9100;
System.Net.Sockets.TcpClient client =
    new System.Net.Sockets.TcpClient();
client.Connect(ipAddress, port);
System.Net.Sockets.NetworkStream stream = client.GetStream();

// Send command strings to printer
foreach (string commandLine in ZPLCommand)
{
    stream.Write(ASCIIEncoding.ASCII.GetBytes(commandLine), 0, commandLine.Length);
    stream.Flush();
}

// Close connections
stream.Close();
client.Close();
Share:
21,869
lucasrhuan
Author by

lucasrhuan

Updated on October 13, 2020

Comments

  • lucasrhuan
    lucasrhuan over 3 years

    I have a problem.

    I´m generating a dynamic BMP image and trying to send this to a ZEBRA printer by ZPL commands. I need to convert my BMP to a GRF image. I think that my Hexadecimal extracted by the BMP image isn´t correct.

    The printed image is blurred and incorrect.

    This is my code:

    string bitmapFilePath = @oldArquivo;  // file is attached to this support article
    byte[] bitmapFileData = System.IO.File.ReadAllBytes(bitmapFilePath);
    int fileSize = bitmapFileData.Length;
    
    Bitmap ImgTemp = new Bitmap(bitmapFilePath);
    Size ImgSize = ImgTemp.Size;
    ImgTemp.Dispose();
    
    // The following is known about test.bmp.  It is up to the developer
    // to determine this information for bitmaps besides the given test.bmp.            
    int width = ImgSize.Width;
    int height = ImgSize.Height;
    int bitmapDataOffset = 62; // 62 = header of the image
    int bitmapDataLength = fileSize - 62;// 8160;    
    
    double widthInBytes = Math.Ceiling(width / 8.0);    
    
    // Copy over the actual bitmap data from the bitmap file.
    // This represents the bitmap data without the header information.
    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).Replace("-", string.Empty);
    
    string comandoCompleto = "~DG" + nomeImagem + ".GRF,0" + bitmapDataLength.ToString() + ",0" + widthInBytes.ToString() + "," + ZPLImageDataString;
    
    • vincent
      vincent over 7 years
      what is the bitmapDataOffset header of the image means here? how to get the value of 62?
  • lucasrhuan
    lucasrhuan over 11 years
    Hi! Thank you for reply. It´s very important to me. Have an error on this line: "sb.AppendFormat("{0:X2}", (byte)~pixels[x]);" This is the error: "Arithmetic operation resulted in an overflow." Can you help me? Thanks!
  • lucasrhuan
    lucasrhuan over 11 years
    Hello! Thank you for reply. My code is based on this example that you post. But I need to have dinamic image with dinamic width and height. I´m generating the image on another function that will bring to this function the image created. Then, I need a function with dinamic parameters that generate a GRF by a bitmap parameter. Can you help me? thank you again!
  • lucasrhuan
    lucasrhuan over 11 years
    Hey! I think that with your function and a some bits mining I finished my problem, hehe. Thanks for the Answer Jigsore
  • Admin
    Admin over 9 years
    @lucasrhuan did you got the answer for this. I am doing the same application now.. I need to make a C# app which should convert my .bmp file to .GRF file. For instance i am using .net paint to create the pcx file and then Ztools to create the .GRF file. But i really need to make single C# application that could convert my .bmp file to grf and send to the print. Sending to the printer is already doing.. I just need this .bmp to .grf conversion.. i mean programatically i need to convert any ideas!!!.. If you got the answer please let me thanks a lot..
  • Admin
    Admin over 9 years
    @Jigsore Please can you e me about your answer.. i applied the same answer.. but its showing error in imagename please let me know
  • André Kool
    André Kool over 7 years
    Can you please add some explenation to your answer? Only showing code can be confusing.
  • zzczzc004
    zzczzc004 over 7 years
    Your code is excellent, but it has a small mistake for me. In my convert, it always have a black edge on the right side. I don't know why, I solved it by set last pixel in every row to 0.
  • vincent
    vincent over 7 years
    help why am I getting FFFFFFFFFFF on all rows for my image, based on png file path. Does image size matter? i have a 14kb png file 728x529 dimension monochrome.
  • BlueFuzzyThing
    BlueFuzzyThing over 7 years
    @zzczzc004 I ran into the black edge as well. To avoid it, make sure your image width is divisible by 8.
  • zzczzc004
    zzczzc004 over 7 years
    @user2748023 Do you mean that (bmp.Width + 7) should divisible by 8? In my case, they are not divisible, because the width is depends on the content which user input .
  • BlueFuzzyThing
    BlueFuzzyThing over 7 years
    @zzczzc004 No, bmp.Width should be divisible by 8. I had an image that was 50x50 and I got the black edge. I resized the image to be 48x48 and the black edge disappeared.
  • Ali Mst
    Ali Mst over 5 years
    @jason.zissman - Thank you for posting the code (Zebra killed the link!)