【问题标题】:How to convert image to zpl code for printing using zebra printer?如何将图像转换为 zpl 代码以使用斑马打印机进行打印?
【发布时间】:2018-08-04 14:17:34
【问题描述】:

我想通过 Android 应用程序中的斑马打印机打印图像以及其他一些文本。我能够为文本数据创建 zpl 代码,但我不得不为图像创建 zpl 代码。 zpl 不支持 base64 代码。图像需要转换为十六进制 ascii 并使用 ^GF 命令打印。

带有文本和图像的原始数据在thisPastebin link上可用,并且可以在labelary viewer中查看。

有没有图片转换过程?

【问题讨论】:

    标签: android image zebra-printers zpl-ii


    【解决方案1】:

    我解决了问题并发布了答案,以便其他人可以从解决方案中受益。位图图像可以使用以下转换器类转换为 zpl 代码。

    public class ZPLConverter {
        private int blackLimit = 380;
        private int total;
        private int widthBytes;
        private boolean compressHex = false;
        private static Map<Integer, String> mapCode = new HashMap<Integer, String>();
    
        {
            mapCode.put(1, "G");
            mapCode.put(2, "H");
            mapCode.put(3, "I");
            mapCode.put(4, "J");
            mapCode.put(5, "K");
            mapCode.put(6, "L");
            mapCode.put(7, "M");
            mapCode.put(8, "N");
            mapCode.put(9, "O");
            mapCode.put(10, "P");
            mapCode.put(11, "Q");
            mapCode.put(12, "R");
            mapCode.put(13, "S");
            mapCode.put(14, "T");
            mapCode.put(15, "U");
            mapCode.put(16, "V");
            mapCode.put(17, "W");
            mapCode.put(18, "X");
            mapCode.put(19, "Y");
            mapCode.put(20, "g");
            mapCode.put(40, "h");
            mapCode.put(60, "i");
            mapCode.put(80, "j");
            mapCode.put(100, "k");
            mapCode.put(120, "l");
            mapCode.put(140, "m");
            mapCode.put(160, "n");
            mapCode.put(180, "o");
            mapCode.put(200, "p");
            mapCode.put(220, "q");
            mapCode.put(240, "r");
            mapCode.put(260, "s");
            mapCode.put(280, "t");
            mapCode.put(300, "u");
            mapCode.put(320, "v");
            mapCode.put(340, "w");
            mapCode.put(360, "x");
            mapCode.put(380, "y");
            mapCode.put(400, "z");
        }
    
        public String convertFromImage(Bitmap image, Boolean addHeaderFooter) {
            String hexAscii = createBody(image);
            if (compressHex) {
                hexAscii = encodeHexAscii(hexAscii);
            }
    
            String zplCode = "^GFA," + total + "," + total + "," + widthBytes + ", " + hexAscii;
    
            if (addHeaderFooter) {
                String header = "^XA " + "^FO0,0^GFA," + total + "," + total + "," + widthBytes + ", ";
                String footer = "^FS" + "^XZ";
                zplCode = header + zplCode + footer;
            }
            return zplCode;
        }
    
        private String createBody(Bitmap bitmapImage) {
            StringBuilder sb = new StringBuilder();
            int height = bitmapImage.getHeight();
            int width = bitmapImage.getWidth();
            int rgb, red, green, blue, index = 0;
            char auxBinaryChar[] = {'0', '0', '0', '0', '0', '0', '0', '0'};
            widthBytes = width / 8;
            if (width % 8 > 0) {
                widthBytes = (((int) (width / 8)) + 1);
            } else {
                widthBytes = width / 8;
            }
            this.total = widthBytes * height;
            for (int h = 0; h < height; h++) {
                for (int w = 0; w < width; w++) {
                    rgb = bitmapImage.getPixel(w, h);
                    red = (rgb >> 16) & 0x000000FF;
                    green = (rgb >> 8) & 0x000000FF;
                    blue = (rgb) & 0x000000FF;
                    char auxChar = '1';
                    int totalColor = red + green + blue;
                    if (totalColor > blackLimit) {
                        auxChar = '0';
                    }
                    auxBinaryChar[index] = auxChar;
                    index++;
                    if (index == 8 || w == (width - 1)) {
                        sb.append(fourByteBinary(new String(auxBinaryChar)));
                        auxBinaryChar = new char[]{'0', '0', '0', '0', '0', '0', '0', '0'};
                        index = 0;
                    }
                }
                sb.append("\n");
            }
            return sb.toString();
        }
    
        private String fourByteBinary(String binaryStr) {
            int decimal = Integer.parseInt(binaryStr, 2);
            if (decimal > 15) {
                return Integer.toString(decimal, 16).toUpperCase();
            } else {
                return "0" + Integer.toString(decimal, 16).toUpperCase();
            }
        }
    
        private String encodeHexAscii(String code) {
            int maxlinea = widthBytes * 2;
            StringBuilder sbCode = new StringBuilder();
            StringBuilder sbLinea = new StringBuilder();
            String previousLine = null;
            int counter = 1;
            char aux = code.charAt(0);
            boolean firstChar = false;
            for (int i = 1; i < code.length(); i++) {
                if (firstChar) {
                    aux = code.charAt(i);
                    firstChar = false;
                    continue;
                }
                if (code.charAt(i) == '\n') {
                    if (counter >= maxlinea && aux == '0') {
                        sbLinea.append(",");
                    } else if (counter >= maxlinea && aux == 'F') {
                        sbLinea.append("!");
                    } else if (counter > 20) {
                        int multi20 = (counter / 20) * 20;
                        int resto20 = (counter % 20);
                        sbLinea.append(mapCode.get(multi20));
                        if (resto20 != 0) {
                            sbLinea.append(mapCode.get(resto20)).append(aux);
                        } else {
                            sbLinea.append(aux);
                        }
                    } else {
                        sbLinea.append(mapCode.get(counter)).append(aux);
                    }
                    counter = 1;
                    firstChar = true;
                    if (sbLinea.toString().equals(previousLine)) {
                        sbCode.append(":");
                    } else {
                        sbCode.append(sbLinea.toString());
                    }
                    previousLine = sbLinea.toString();
                    sbLinea.setLength(0);
                    continue;
                }
                if (aux == code.charAt(i)) {
                    counter++;
                } else {
                    if (counter > 20) {
                        int multi20 = (counter / 20) * 20;
                        int resto20 = (counter % 20);
                        sbLinea.append(mapCode.get(multi20));
                        if (resto20 != 0) {
                            sbLinea.append(mapCode.get(resto20)).append(aux);
                        } else {
                            sbLinea.append(aux);
                        }
                    } else {
                        sbLinea.append(mapCode.get(counter)).append(aux);
                    }
                    counter = 1;
                    aux = code.charAt(i);
                }
            }
            return sbCode.toString();
        }
    
        public void setCompressHex(boolean compressHex) {
            this.compressHex = compressHex;
        }
    
        public void setBlacknessLimitPercentage(int percentage) {
            blackLimit = (percentage * 768 / 100);
        }
    
       }
    

    使用示例: 您需要将图像转换为位图,转换为单色图像并进行 hex acii 转换。生成的zpl代码可以在labelary viewer查看。

    public class Utils {
    
        public static String getZplCode(Bitmap bitmap, Boolean addHeaderFooter) {
            ZPLConverter zp = new ZPLConverter();
            zp.setCompressHex(true);
            zp.setBlacknessLimitPercentage(50);
            Bitmap grayBitmap = toGrayScale(bitmap);
            return zp.convertFromImage(grayBitmap, addHeaderFooter);
        }
    
        public static Bitmap toGrayScale(Bitmap bmpOriginal) {
            int width, height;
            height = bmpOriginal.getHeight();
            width = bmpOriginal.getWidth();
    
            Bitmap grayScale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            Canvas c = new Canvas(grayScale);
            Paint paint = new Paint();
            ColorMatrix cm = new ColorMatrix();
            cm.setSaturation(0);
            ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
            paint.setColorFilter(f);
            c.drawBitmap(bmpOriginal, 0, 0, paint);
            return grayScale;
        }
    }
    

    转换器代码已引用自here,并添加了对android使用的支持。

    【讨论】:

    • 这不适用于低像素图像。我在labelary.com 上转换了一个图像,它工作得很好,但是当我在这个类中转换相同的图像时它不能正常工作
    【解决方案2】:

    我知道这是一种完成的交易,但我仍然对当前的答案感到很困惑。我想将我的经验分享给可能需要的人。

    首先,^GFA 代表像素的十六进制表示,但它必须转换为可读文本 (ASCII)。这是一个例子: 像素白色 = 1,黑色 = 1

    1011 0100 翻译成 0xB4

    在^GFA的数据部分,你需要有B4作为数据。

    如果我们一起去

    像素线 1:1011 0100 1001 1100 = 0xBA 0x9C 像素线2:0011 0110 0001 1111 = 0x36 0x1F

    生成的 ZPL 代码将是:

    ^XA(需要启动 ZPL 文件)

    ^F10,0(水平偏移 10 像素,垂直偏移 0 像素)

    ^GFA,4,4,2,BA9C361F(4为总字节数,2为每行字节数)

    ^F0^XZ(文件结束)

    现在,有趣的一点。如何获取代码:

    您需要一个灰度位图。您需要按像素访问位图。换句话说,一个包含整数的数组,其值在 0 到 255 之间变化。

    使用该数组,您可以获取每组 8 个像素,将其转换为十六进制值,然后转换为这些十六进制的文本表示。这是用 Borland 制作的 c++ 代码:

    Graphics::TBitmap *imageFax = new Graphics::TBitmap();
    
    unsigned char r;
    unsigned char b;
    ofstream outFile;
    char listeHex[16];
    int lineByteWidth;
    int j;
    int bytesCount = 0;
    int widthHeight;
    AnsiString testOut;
    
    listeHex[0] = '0';
    listeHex[1] = '1';
    listeHex[2] = '2';
    listeHex[3] = '3';
    listeHex[4] = '4';
    listeHex[5] = '5';
    listeHex[6] = '6';
    listeHex[7] = '7';
    listeHex[8] = '8';
    listeHex[9] = '9';
    listeHex[10] = 'A';
    listeHex[11] = 'B';
    listeHex[12] = 'C';
    listeHex[13] = 'D';
    listeHex[14] = 'E';
    listeHex[15] = 'F';
    
    imageFax->Monochrome = true;
    imageFax->PixelFormat = pf8bit;
    
    imageFax->LoadFromFile("c:/testEtiquette/test.bmp"); //1200x300pixels bitmap test image
    
    testOut = "c:/testEtiquette/outputfile.txt";
    
    outFile.open(testOut.c_str());
    
    imageFax->PixelFormat = pf8bit;
    
    
    lineByteWidth = imageFax->Width/8;//Number of byte per line
    widthHeight = lineByteWidth*imageFax->Height;//number of total byte to be written into the output file
    
    
    testOut = "^XA^FO10,0^GFA,";
    outFile << testOut.c_str() << widthHeight << ',' << widthHeight << ',' << lineByteWidth << ',' ;
    for(int i = 0; i < imageFax->Height; i++)
    {
         unsigned char * pixel = (unsigned char *)imageFax->ScanLine[i];
         bytesCount = 0;
         b=0x00;
         for(j = 0; j < imageFax->Width; j++)
         {
            //Here is the "switch" : what is not white (255) bit = 0, is black bit = 1.
            //You can set your switch at whatever value you think is best. 0, 255 or anything between.
            //I think 255 (white) is a good for my application
            if(pixel[j] != 255)
            {
                b = b<<1;
                //It is not white (hence black), we force value 1 into current position
                b = b|0x01;
            }
            else
            {
                //Since it white, we move 1 bit to the left, pushing 0 into current position
                b = b<<1;
                b = b&0xFE;//Forcing a 0 in the current position
            }
    
            //If we've got a full byte (8-bits), we write it into the file
            //This will lead into cutting off part of images that width is not a multiple of 8
            if(j%8 == 7)
            {
                bytesCount++;
    
                r = b;
                r = r&0xF0; //Cleaning last digits
                r=r>>4; //Moving the bits to the left 0xF0 => 0x0F
                outFile << listeHex[r%16]; //Reaching into the conversion array listeHex, ASCII representation of hex value
                r = listeHex[r%16]; //For debug only
    
                r = b;
                r = r&0x0F;//Cleaning first digits
                outFile << listeHex[r%16];//Reaching into the conversion array listeHex, ASCII representation of hex value
                r = listeHex[r%16]; //For debug only
    
                b = 0x00; //Reseting for next Byte
            }
         }
    }
    testOut = "^F0^XZ";
    outFile << testOut.c_str();
    outFile.close();
    delete imageFax;
    

    一些链接: ZPL PDF doc(图形转换参见第 191 页)https://www.zebra.com/content/dam/zebra/manuals/printers/common/programming/zpl-zbi2-pm-en.pdf (如果链接不起作用,请在 google 上尝试“zpl-zbi2-pm-en.pdf”)

    https://www.rapidtables.com/convert/number/binary-to-hex.html

    【讨论】:

      【解决方案3】:

      这是IP打印机的完整工作代码(型号GK420t ZPL,您可以访问任何IP打印机)。只需替换三件事 1)添加您的IP地址2)添加您的端口号3) 加你 PNG 文件路径

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Management;
      using System.Net.Http;
      using System.ServiceModel.Channels;
      using System.Web;
      using System.Web.Http;
      using System.Net.Sockets;
      using System.Net;
      using System.Text;
      using System.IO;
      using System.ComponentModel;
      using System.Data;
      using System.Drawing;
      using System.Text;
      using System.Printing;
      using System.Net.NetworkInformation;
      using System.Drawing.Imaging;
      using System.Text.RegularExpressions;
      using System.Drawing.Drawing2D;
      using System.Runtime.InteropServices;
      using System.Windows.Forms;
      using System.Runtime.InteropServices;
      using System.Drawing.Printing;
      
      
      
      
      
      namespace ConsoleApplication2
      {
          class Program
          {
              static void Main(string[] args)
              {     
                  string ipAddress = "Your IP address";
                  int port = Your port number;
      
                  string zplImageData = string.Empty;
                  string filePath = @"your png file path";
                  byte[] binaryData = System.IO.File.ReadAllBytes(filePath);
                  foreach (Byte b in binaryData)
                  {
                      string hexRep = String.Format("{0:X}", b);
                      if (hexRep.Length == 1)
                          hexRep = "0" + hexRep;
                      zplImageData += hexRep;
                  }
                  string zplToSend = "^XA" + "^FO50" + "50^GFA,120000,120000,100" + binaryData.Length + ",," + zplImageData + "^XZ";
                  string printImage = "^XA^FO115,50^IME:LOGO.PNG^FS^XZ";
      
                  try
                  {
                      // Open connection
                      System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient();
                      client.Connect(ipAddress, port);
      
                      // Write ZPL String to connection
                      System.IO.StreamWriter writer = new System.IO.StreamWriter(client.GetStream(), Encoding.UTF8);
                      writer.Write(zplToSend);
                      writer.Flush();
                      writer.Write(printImage);
                      writer.Flush();
                      // Close Connection
                      writer.Close();
                      client.Close();
                  }
                  catch (Exception ex)
                  {
                      // Catch Exception
                  }
      
      
          }
              }
      
          }
      

      【讨论】:

        猜你喜欢
        • 2016-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-03
        相关资源
        最近更新 更多