ESC/POS©指令体系是由EPSON发明的一套专有POS打印机指令系统
市面上绝大部分打印机兼容esc/pos指令。
常用的打印命令介绍
初始化打印机
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+xH_256)_8
yL:位图高度以双字节表示的低位数值
yH:位图高度以双字节表示的高位数值
竖直方向位图点数为 yL+yH256
比如位图高度是200
200的二进制表示是 00000000 11001000。所以yL=200,yH=0;
d1…dk:代表位图数据,每个字节相应位为1表示打印该点,为0不打印该点。
举例:
假设图片尺寸200px_200px
那么(xL+xH_256)=25
yL+yH256=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.30_R+0.59_G+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...dkbyte[] 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...dkif (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);//计算xLcmd[5]=(byte) (width / 256);//计算xHcmd[6]= (byte) (height % 256);//计算yLcmd[7]=(byte) (height / 256);//计算yHint 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);}
