热敏打印机编程 ESC/POS指令

ESC/POS指令

ESC/POS©指令体系是由EPSON发明的一套专有POS打印机指令系统
市面上绝大部分打印机兼容esc/pos指令。

说明

本人使用的是USB host模式,如果你用的是蓝牙或者wifi连接,指令的传输就不是UsbDeviceConnection.bulkTransfer方法了。USB host模式的使用可以参看我的android USB通信

常用的打印命令介绍

初始化打印机

指令:

     ASCII码  ESC  @
     十进制码  27   64

说明

这个指令会清楚打印缓冲区中的数据,但是接收缓冲区的数据并不会清除,一般开始打印的时候需要调用

代码

byte [] esc_init=new byte[]{27,64};
mDeviceConnection.bulkTransfer(endpointOut, esc_init, esc_init.length, TIME_OUT);

设置对齐方式

指令:

     ASCII码  ESC  a   n
     十进制码  27   97  n

参数含义:

n 对齐方式
0,48 左对齐
1,49 中间对齐
2,50 右对齐

代码

byte [] esc_gravity=new byte[] {27,97,0}//左对齐
mDeviceConnection.bulkTransfer(endpointOut, esc_gravity, esc_gravity.length, TIME_OUT);

字体加粗

指令:

     ASCII码  ESC   ! n
     十进制码  27   33  n

参数含义:

n 效果
0 取消加粗
8 加粗

代码

byte [] esc_bold=new byte[] {27,33,8}//加粗
mDeviceConnection.bulkTransfer(endpointOut, esc_bold, esc_bold.length, TIME_OUT);

字体倍高倍宽

指令:

     ASCII码  ESC   ! n
     十进制码  27   33  n

参数含义:

n 效果
0 正常
16 倍高
32 倍宽

走纸

指令:

     ASCII码  ESC   d   n
     十进制码  27   100  n

参数含义:

0<=n<=255

说明

打印缓冲区中的数据并向前走纸n行

打印光栅位图

指令:

     ASCII码    GS  v   0    m  xL  xH  yL  yH  d1...dk
     十进制码    29  118  48  m  xL  xH  yL  yH  d1...dk

参数含义
m :指的是打印模式

m值 打印模式
0,48 正常
1,49 倍宽
2,50 倍高
3,51 倍宽倍高

xL:位图宽度以双字节表示的低位数值
XH:位图宽度以双字节表示的高位数值
比如位图宽度是200,宽度占的字节数=200/8=25;
为什么除以8?因为待打印位图的位图是灰度图,一个像素占用一个字节。后面解释什么是灰度图。
25的二进制表示是00000000 00011001。所以xL=0(高8位),xH=25(低8位);
所以水平方向位图点数为 (xL+xH256)8

yL:位图高度以双字节表示的低位数值
yH:位图高度以双字节表示的高位数值
竖直方向位图点数为 yL+yH*256
比如位图高度是200
200的二进制表示是 00000000 11001000。所以yL=200,yH=0;
d1...dk:代表位图数据,每个字节相应位为1表示打印该点,为0不打印该点。

举例:
假设图片尺寸200px200px
那么(xL+xH
256)=25
yL+yH*256=200;

1 2 3 ... 23 24 25
26 27 28 ... 48 49 50
... ... ... ... ... ... ...
4976 4977 4978 ... 4998 4999 5000

其中每个小格由横向的8位组成,相应位为1表示打印该点,为0不打印该点。

规范化位图

用户传入的位图的尺寸是随意的,需要将位图的宽度规范化为8的整数倍。

    private Bitmap resizeImage(Bitmap bitmap, int requestWidth) {
        //将位图宽度规范化为8的整数倍
        int legalWidth=(requestWidth+7)/8*8;
        int height= (int) (legalWidth*bitmap.getHeight()/(float)bitmap.getWidth());
        return Bitmap.createScaledBitmap(bitmap,legalWidth,height,true);
    }

图像的灰度化

首先什么是灰度化?
在RGB模型中,当R=G=B时,则彩色表示一种灰度颜色,其中R=G=B的值叫灰度值。因此,灰度图每个像素只需一个字节存放灰度值,灰度范围为0-255.一般有分量法 、最大值法、平均值法、加权平均法对彩色图像进行灰度化。

说一下加权平均法:
由于人眼对绿色的敏感最高,对蓝色敏感最低,因此,按下式对RGB三分量进行加权平均能得到比较合理的灰度图像。
Gray=0.30R+0.59G+0.11B
程序实现

private int grayPixle(int pixel) {
    int red=(pixel & 0x00ff0000) >> 16;//获取r分量
    int green= (pixel & 0x0000ff00)  >> 8;//获取g分量
    int blue= pixel & 0x000000ff;//获取b分量
    return (int) (red*0.3f+green*0.59f+blue*0.11f);//加权平均法进行灰度化
}

灰度图的二值化

图像的二值化就是将图像上的像素点的灰度值设置为0或或者255,也就是将整个图像呈现出明显的黑白效果的过程。所有灰度大于或等于阈值的像素被判定为属于特定物体,其灰度值为255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。
阈值的选取是至关重要,直接影响着二值化后的图片的质量。对于我们的打印程序选128就行,要求不高。

      //存储位图数据d1...dk
    byte[] data = new byte[width * height];
    int index = 0;
    int temp = 0;
    int part[]=new int[8];
//for循环顺序不要错了,外层遍历高度,内层遍历宽度,因为横向每8个像素点组成一个字节。
    for (int j=0;j<bitmap.getHeight();j++){
        for (int i=0;i<bitmap.getWidth();i+=8){
                //横向每8个像素点组成一个字节。
                for(int k=0;k<8;k++) {
                    int pixel = bitmap.getPixel(i+k, j);
                    int grayPixle = grayPixle(pixel);
                    if (grayPixle >128) {
                        //灰度值大于128位   白色 为第k位0不打印
                        part[k]=0;
                    } else {
                        part[k]=1;
                    }
                }

                //128千万不要写成2^7,^是异或操作符
                temp=part[0]*128+
                        part[1]*64+
                        part[2]*32+
                        part[3]*16+
                        part[4]*8+
                        part[5]*4+
                        part[6]*2+
                        part[7]*1;
                data[index++] = (byte) temp;
            }
        }

以上就获得了d1...dk位图数据

完整的代码

    // 使用光栅位图的打印方式
    public void printBitmap(Bitmap bitmap,int requestWidth) throws Exception {
        // GS v 0 m xL xH yL yH d1...dk
        if (bitmap == null) {
            throw new Exception("bitmap is null");
        }
        //规范化位图宽高
        bitmap=resizeImage(bitmap,requestWidth);

        int width = bitmap.getWidth() / 8;
        int height = bitmap.getHeight();
        byte []cmd= new byte[width * height+4+4];
        cmd[0]=29;
        cmd[1]=118;
        cmd[2]=48;
        cmd[3]=0;
    cmd[4]= (byte) (width % 256);//计算xL
        cmd[5]=(byte) (width / 256);//计算xH
        cmd[6]= (byte) (height % 256);//计算yL
        cmd[7]=(byte) (height / 256);//计算yH 

        int index = 8;
        int temp = 0;
        int part[]=new int[8];
        for (int j=0;j<bitmap.getHeight();j++){
            for (int i=0;i<bitmap.getWidth();i+=8){
                //横向每8个像素点组成一个字节。
                for(int k=0;k<8;k++) {
                    int pixel = bitmap.getPixel(i+k, j);
                    int grayPixle = grayPixle(pixel);
                    if (grayPixle >128) {
                        //灰度值大于128位   白色 为第k位0不打印
                        part[k]=0;
                    } else {
                        part[k]=1;
                    }
                }

                //128千万不要写成2^7,^是异或操作符
                temp=part[0]*128+
                        part[1]*64+
                        part[2]*32+
                        part[3]*16+
                        part[4]*8+
                        part[5]*4+
                        part[6]*2+
                        part[7]*1;
                cmd[index++] = (byte) temp;
            }
        }
        
           mDeviceConnection.bulkTransfer(endpointOut, cmd, esc_bold.length, TIME_OUT);
        
    }

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容