ZPL命令 实现打印中文

最近用C#结合ZPL指令实现了打印中文的功能,在这里对其中的代码以及一些资源,分享一下.

一.直接使用ZPL打印

对于直接使用ZPL命令打印中文,首先需要明确几个概念:

1.码表文件: 字符编码文件,打印中文需要制定的码表,常用中文码表为 GB.DAT,GB8BIT.DAT,GB2312.DAT,GB18030.DAT, 其中 GB.DAT,GB8BIT.DAT为较早的机型使用编码表文件,码表可以自行下载,使用ANSI编码时必须配置编码表.

命令:SE,例子:SEE:GB18030.DAT^FS,其中E:为默认存储位置,大多数机器都默认存储在E盘,

值得注意的是,下面这些盘符都是软盘,需要通过软件点此查看将字体烧录到打印机硬件中,才能实现中文打印,比较麻烦,所以还是推荐最后的终极解决方案

存储盘符包括:

R: DRAM
B: PCMCIA Card
E: Flash Memory

2.字库文件: 我们常说的字体,打印中文需要中文字库文件,字库文件后缀为FNT或TTF,字库文件需要相应工具来转换。机器默认的字库文件可以到打印机官网查询,字库文件也可以自行下载,需要注意的是,由于字库文件需要一定的存储空间,最好选择合适的字库文件.

命令:CW/A,例子:CW1,E:SIMSUN.FNTA1,20,20FS,其中CW为定义字体,^A为调用SIMSUN.FNT为字体名称,1为定义的字体标识名称.

3.字符集,打印中文需要选取中文字符集,常用的有

14 = 双字节亚洲编码 a

26 = 包含 ASCII Transparency a 和 c 的多字节亚洲编码

28 = Unicode (UTF-8 编码) - Unicode 字符集

很多文章里提到了CI17,官方文档上标注CI17 命令已弃用,同时弃用的还有 ^CI17 命令正常工作所需的 ^F8 和 ^F16 命令。建议您改用 ^CI28-30 命令。我的建议是找跟自己打印机固件匹配的指令,打印机的固件版本可以到官网上获取.

官网:https://www.zebra.com/us/en/support-downloads/printers/industrial/zm400.html

中文SimSun字体在斑马打印机的应用-敏用数码|专注于条码数据处理 (chongshang.com.cn)

命令:CI,例子:CI28

友情提示:

Encoding编码为ANSI时,需要码表文件和字库文件,而Unicode编码时,只需要字库文件即可.

可以使用 WD*😗.*命令进行查询打印机的码表,WD为打印目录标签命令,你也可以使用^WDE:*.DAT,直接查询E:盘下后缀为DAT的有哪些.

代码例子:

1.使用 ANSI Encoding编码模式输出时,需要中文码表支持,ZPL命令如下:

^XA
^SEE:GB18030.DAT^FS
^CWJ,E:MSUNG.FNT^FS
^FO10,10^AJ,24,24^CI26^FD中文打印测试ANSI^FS
^PQ1
^XZ

2.Encoding编码为UTF-8时,只要字库文件,此时改变国际字符集指令使用CI17加F8,或^CI28,如:

^XA
^CWJ,E:MSUNG.FNT^FS
^FO10,10^AJN,24,24^CI17^F8^FD中文打印测试UTF^FS
^PQ1
^XZ
或:
^XA
^CWJ,E:MSUNG.FNT^FS
^FO10,10^AJN,24,24^CI28^FD中文打印测试UTF^FS
^PQ1
^XZ

要注意编码表,字库文件和字符集三者都正确才能打印出中文,负责可能出现乱码的情况.

二.使用第三方库文件Fnthex32.dll转换为图像后打印,Fnthex32.dll 并没有找到官网下载地址,各位看官网上自己搜吧...该库文件分为8参和9参两个版本,此处以9参为例进行介绍,直接上代码

 public class ZebraPrintHelper
    {
        [DllImport("Fnthex32.dll")]
        public static extern int GETFONTHEX(
        string BarcodeText,//转换的文本
        string FontName,//打印字体
        string FileName,//存储的变量名称
        int Orient,//方向
        int Height,//字体高度,点阵高度
        int Width,//点阵宽度
        int IsBold,//是否加粗0,1
        int IsItalic,//是否斜体0,1
        StringBuilder ReturnBarcodeCMD);//存储的内容
 
        /// <summary>
        /// 转换中文
        /// </summary>
        /// <param name="chStr">转换的字符</param>
        /// <param name="tempName">存储的变量名称</param>
        /// <param name="font">使用的字体</param>
        /// <returns></returns>
        public static string ConvertChineseToHex(string chStr, string tempName, string font = "Microsoft YaHei")
        {
            StringBuilder cBuf = new StringBuilder(chStr.Length * 1024);
            int nCount = GETFONTHEX(chStr, font, tempName, 0, 25, 15, 1, 0, cBuf);
            string temp = " " + cBuf.ToString();
            temp = temp.Substring(0, nCount);
            return temp;
        }
    }

调用类库方法ConvertChineseToHex获取ZPL指令

string zplCode=ZebraPrintHelper.ConvertChineseToHex("打印测试ASD", "tempName", "Microsoft YaHei")

指令获取结果:

 ~DGtempName,00200,008,j03FC1FE0HF07F8I07FE3HF1HF8HFCI041F20F907C83EK0FH07803C01
EK0FH07803C01EJ03E01FH0F807CJ07C03E01FH0F8J0FH07803C01EJ01EH0FH07803CJ01EH0FH078
03CJ01EH0FH07803Cg01FH0F807C03EJ01FH0F807C03Ek0

这里~DG指令只是创建了一个名称为tempName的图像,我们还需要附加一条指令来调用它,如下

^FO15,5^XGtempName,1,1^FS

完整的ZPL命令应该是:

^XA
 ~DGtempName,00200,008,j03FC1FE0HF07F8I07FE3HF1HF8HFCI041F20F907C83EK0FH07803C01
EK0FH07803C01EJ03E01FH0F807CJ07C03E01FH0F8J0FH07803C01EJ01EH0FH07803CJ01EH0FH078
03CJ01EH0FH07803Cg01FH0F807C03EJ01FH0F807C03Ek0
^FO15,5^XGtempName,1,1^FS
^PQ1
^XZ

最后将ZPL命令以RAW模式发送至给印机即可.

最后在这里分享几个不错的网站:

1.在线调试网址,对于ZPL指令执行的结果可以进行调试.

http://labelary.com/viewer.html

2.资料网站,前查资料的时候发现的网站,有很多ZPL中文打印相关的问题和解答

http://www.winfuture.net/bbs/index.asp

[Fnt字体制作_weixin_43932081的博客-程序员宝宝_fnt字体制作 - 程序员宝宝 (cxybb.com)

[Fnt字体制作_weixin_43932081的博客-CSDN博客_fnt字体制作](https://www.cxybb.com/article/weixin_43932081/101716387)

生成fnt字体工具BMFontTool工具_MOMO实验室的博客-CSDN博客_ttf转fnt

碰到斑马打印机下载字体问题

最近手里有一台斑马打印机(Zebra GT800 EPL),要求打印出Arial 7号字体,然后就开始各种摸索,从网上查资料,

然后就找到了这个http://www.chongshang.com.cn/manual/ZPL_font.shtml,写的够详细,但是我按照这个步骤来怎么也找不到我字体下载到哪去啦!!

终于,发现不是步骤的问题,是驱动的问题,其实seagull和斑马自带的驱动都能实现字体下载的功能,只是好像有一个差别。

因为一开始打印机标明是EPL语言打印机,我就直接装了个EPL驱动,两个驱动都试过!!然后下载进去各种找不到。

后来就想了下换成ZPL的试试,没想到还真的下载进去啦。。

斑马自带驱动下载进去后,如果不改字体名字的话,默认是ARI000.FNT,然后直接调用就可以!原文链接:https://blog.csdn.net/u013366966/article/details/46011323

终极解决方案:图片转ZPL实现打印

Java How to Convert Image to ZPL Zebra printer format Example (jcgonzalez.com)

源码部分

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
public class ZPLConveter {
    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 convertfromImg(BufferedImage image) throws IOException {
        String cuerpo = createBody(image);
        if(compressHex)
           cuerpo = encodeHexAscii(cuerpo);
        return headDoc() + cuerpo + footDoc();        
    }
    private String createBody(BufferedImage orginalImage) throws IOException {
        StringBuffer sb = new StringBuffer();
        Graphics2D graphics = orginalImage.createGraphics();
        graphics.drawImage(orginalImage, 0, 0, null);
        int height = orginalImage.getHeight();
        int width = orginalImage.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 = orginalImage.getRGB(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;        
        StringBuffer sbCode = new StringBuffer();
        StringBuffer sbLinea = new StringBuffer();
        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) + aux);    
                    } else {
                        sbLinea.append(aux);    
                    }
                } else {
                    sbLinea.append(mapCode.get(counter) + aux);
                    if(mapCode.get(counter)==null){
                    }
                }
                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) + aux);    
                    } else {
                        sbLinea.append(aux);    
                    }
                } else {
                    sbLinea.append(mapCode.get(counter) + aux);
                }
                counter = 1;
                aux = code.charAt(i);
            }            
        }
        return sbCode.toString();
    }
    private String headDoc(){
        String str = "^XA " +
                        "^FO0,0^GFA,"+ total + ","+ total + "," + widthBytes +", ";
        return str;
    }
    private String footDoc(){
        String str = "^FS"+
                        "^XZ";        
        return str;
    }
    public void setCompressHex(boolean compressHex) {
        this.compressHex = compressHex;
    }
    public void setBlacknessLimitPercentage(int percentage){
        blackLimit = (percentage * 768 / 100);
    }
    public static void main(String[] args) throws Exception {
        BufferedImage orginalImage = ImageIO.read(new File("/tmp/logo.jpg"));
        ZPLConveter zp = new ZPLConveter();
        zp.setCompressHex(true);
        zp.setBlacknessLimitPercentage(50);        
        System.out.println(zp.convertfromImg(orginalImage));        
    }
}

标签打印机图片转ZPL指令 - 佳博云打印 (poscom.cn)

Java绘图: 使用 Graphics 类绘制线段、矩形、椭圆/圆弧/扇形、图片、文本_xietansheng的博客-CSDN博客_graphics画矩形

源码部分

测试通过——zebra-api: java编写图片转ZPL指令,斑马打印机打印中文标签纸

未测试

本文作者:Journey&Flower

本文链接:https://www.cnblogs.com/JourneyOfFlower/p/16768697.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Journey&Flower  阅读(6182)  评论(3编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 404 Not Found REOL
404 Not Found - REOL
00:00 / 00:00
An audio error has occurred.

Fade away

Do over again

Fade away

Utai hajime no hitomojime

Itsumo mayotteru

Douse toritome no nai koto dakedo

Tsutawaranakya motto imi ga nai (Ooh-ooh, oh-oh-oh)

Doushitatte konna ni fukuzatsu nano ni

Kamikudaite yaranakya tsutawaranai

Hora kekkyoku kashi nanka dou datte ii

Boku no ongaku nanka kono yo ni nakutatte ii nda yo

Ii ndarou

Nee sou darou

Everybody don't know why

Everybody don't know much

Boku wa ki ni shinai, kimi wa kidzukanai

Doko ni mo mou inai inai

Everybody don't know why

Everybody don't know much

Wasureteiku, wasurerareteiku

We don't know, we don't know, no, no

Me no mae, hirogaru genjitsu sekai ga mata yuganda

Nando risetto shite mo

Boku wa boku igai no dareka ni wa umare kawarenai

Sonna no shitteru yo

Ki ni naru ano ko no uwasabanashi mo

Shinikaru hyouteki wa tsugi no sokuhou

Mahi shichatteru (Tteru) kokkara esukeepu (Keepu)

Tooku tooku made ikeru yo

Antei nante nai (Na-na-na-na)

Fuanteina sekai (Na-na-na-na)

Antei nante nai (Na-na-na-na)

Kitto ashita ni wa wasureru yo

Fade away

Do over again

Fade away

Souda sekai wa dokoka ga itsumo uso kusai

Kireigoto dake ja daijina hitotachi sura mamorenai

Kudaranai, bokura minna dokoka kurutteru mitai

Hontou no koto nanka zenbu kamisama mo shiranai

Kamisama mo shiranai (Woah, woah, woah, no, woah)

Kamisama mo shiranai (Woah, woah, woah, no, woah)

Kamisama mo shiranai, but

Kamisama mo shiranai (Woah, no, woah, no, woah)

Everybody don't know why

Everybody don't know much

Boku wa ki ni shinai, kimi wa kidzukanai

Doko ni mo mou inai inai

Everybody don't know why

Everybody don't know much

Wasureteiku, wasurerareteiku

We don't know, we don't know, oh, oh-oh-oh

Ahh, oh-oh-oh-oh

Woah, oh-oh-oh

Ooh, ooh, ooh, ooh-ooh-ooh-ooh