热敏打印机图片打印ESC/POS指令
28 Apr 2021
这几天研究热敏打印机的打印指令,
通过蓝牙或接口,发送给打印机进行打印。
使用的是位图打印命令。
本问主要说明怎样将图片转换成指令。
适用于Android系统平台的代码。
用360*360大小的Bitmap转成byte[]指令
指令说明
ESC * 设定位图命令格式:
ASCII: ESC * m n1 n2 d1..dk
DEC: 27 42 m n1 n2 d1..dk
HEX: 1B 2A m n1 n2 d1..dk
注释:
设定位图方式(用 m)、点数(用 n1 n2)以及位图内容(d1..dk)
m=0,1,32,33,n1=0~ 255。n2=0~3。d=0~255。
k=n1+256×n2 (m=0,1)
k=(n1+256×n2)×3 (m=32,33)
水平方向点数为 n1+256×n2
m 用于选择位图方式。
m Mode 横向最多点数
0 8点单密度 n1+n2×256[不超过 288 点]
1 8点双密度 n1+n2×256[不超过 576 点]
32 24点单密度 (n1+n2×256)×3[不超过 288点]
33 24点双密度 (n1+n2×256)×3[不超过 576点]
注:
1、 如果 m 值超出上面指定的范围,
n1以后的数据会被当作普通打印字符来打印。
2、 横向点数为 n1+256×n2。
3、 如果点数超过一行,超过其最大点数
(与选择的位图方式有关,详见上表)的部分被忽略。
4、 d 代表图形数据。其中每个字节的某位为 1 的
时候打印出一点,为 0 的时候,为空白。
5、 打印数据超过 GS L 和 GS W 规定的打印区域的
时候,超出数据会被忽略。
6、 打印完图形模式后,打印机会回到字符打印模式。
但图形下打印速度较慢,所以一般要求
在打印字符前加 ESC @指令恢复速度设置。
7、 字符修饰指令,如强调、下划线、反转以及尺寸变化
等指令在图形模式下无效。对齐指令有效。
转换代码
1.将图片地址转Bitmap对象
将图片缩放到360*360尺寸/** * 通过图片地址获取图片对象 * @param path 图片地址 * @return Bitmap */ public static Bitmap getBitmap(String path) { Bitmap bitmapTemp = BitmapFactory.decodeFile(path); Bitmap bitmap = Bitmap.createScaledBitmap( bitmapTemp, 360, 360, false); // 如果没有缩放,那么不回收 if (bitmapTemp != bitmap) { // 释放Bitmap的native像素数组 bitmapTemp.recycle(); } return bitmap; }
2.获取指令数组
包含三个方法:2.1 图片生成指令组
/** * 用于打印360*360大小的图片 * 360 = 24 * 15 * 换行 10 * 0x68 = 104 * 360 = 0x68 + 0x01 * 256 * 16290 = ( 5 + 3 * 360 + 1 ) * 15 * * @param bit 图片 * @return 打印指令 */ public static byte[] draw2PxPoint360(Bitmap bit) { byte[] data = new byte[16290]; int k = 0; for (int j = 0; j < 15; j++) { data[k++] = 0x1B; data[k++] = 0x2A; data[k++] = 33; //24点双密度打印,分辨率200DPI。 data[k++] = 0x68; data[k++] = 0x01; for (int i = 0; i < 360; i++) { for (int m = 0; m < 3; m++) { for (int n = 0; n < 8; n++) { //获取图片的灰度值 byte b = px2Byte(i, j * 24 + m * 8 + n, bit); data[k] += data[k] + b; } k++; } } //换行 data[k++] = 10; } return data; }2.2 像素转指令
/** * 图片二值化,黑色是1,白色是0 * * @param x 横坐标 * @param y 纵坐标 * @param bit 位图 * @return 像素对应点数据 */ public static byte px2Byte(int x, int y, Bitmap bit) { byte b = 0; int pixel = bit.getPixel(x, y); int red = (pixel & 0x00ff0000) >> 16; // 取高两位 int green = (pixel & 0x0000ff00) >> 8; // 取中两位 int blue = pixel & 0x000000ff; // 取低两位 int gray = RGB2Gray(red, green, blue); if (gray < 128) { b = 1; } else { b = 0; } return b; }2.3 图片灰度的转化
/** * 图片灰度的转化 * * @param r 红 * @param g 绿 * @param b 蓝 * @return 灰度值 */ private static int RGB2Gray(int r, int g, int b) { return (int) (0.29900 * r + 0.58700 * g + 0.11400 * b); }
3.完整打印指令
有些冗余指令,可根据效果调整。3.1 复位打印机
new byte[]{0x1B, 0x40};3.2 开始打印图片
1B,40 初始化打印机
1B,33 设定 n/180 英寸行间距
new byte[]{0x00, 0x1B, 0x40, 0x1B, 0x33, 0x00};3.3 设置居中
new byte[]{0x1b, 0x61, 0x31};3.4 打印图片指令
byte[] command = draw2PxPoint360(bitmap);3.5 结束打印图片
设置左边距
new byte[]{0x1d, 0x4c, 0x1f, 0x00};3.6 换行
new byte[]{10};
4.并排打印图片
因为小票纸宽的问题把图片缩放到192*192
80mm宽纸最多可以打印3张
58mm宽纸可以打印2张
public static byte[] draw2PxPoint( Bitmap bit1, Bitmap bit2) { byte[] data = new byte[9264]; int k = 0; for (int j = 0; j < 8; j++) { data[k++] = 0x1B; data[k++] = 0x2A; data[k++] = 33; //24点双密度打印 data[k++] = (byte) (128 & 0xFF); data[k++] = 0x01; for (int i = 0; i < 192; i++) { for (int m = 0; m < 3; m++) { for (int n = 0; n < 8; n++) { byte b = px2Byte(i, j * 24 + m * 8 + n, bit1); data[k] += data[k] + b; } k++; } } for (int i = 0; i < 192; i++) { for (int m = 0; m < 3; m++) { for (int n = 0; n < 8; n++) { byte b = px2Byte(i, j * 24 + m * 8 + n, bit2); data[k] += data[k] + b; } k++; } } data[k++] = 10; } return data; }
5.图片转换说明
图片的颜色标准为RGB,例如:#00ff00即红绿蓝,根据算法转换成一个灰度值
判断灰度值大于128,
就是打印机上的一个黑点,用1标识
否则就是空白,用0标识
用24点双密度的模式去打印图片
一个byte有8位,3个8位就是24点
打印机横向滑行一次,一列上可以打印24个点
宽360px,高360px的图片
图片上有360行像素点
第一列的8行像素点可以放一个byte
第一列的9到16行可以放第二个byte
第一列的17到24行可以放第三个byte
3个byte在打印机上可以打印一次
然后在像右移动一列,打印3个byte
就是第二列的前24行
所以将图片分成360列15行组,
一行组有24个像素点数据(3个byte)
对于byte数组,就有360*3列15行
例如:
360*360图片
行是15,列是360
像素点 360 * 360 =( 3 * 8 * 15 )* 360
byte 360 * 360 / 8 = 15 * 360 * 3
192*192图片
行是8,列是192
像素点 192 * 192 =( 3 * 8 * 8 )* 192
byte 192 * 192 / 8 = 8 * 360 * 3
6.常用打印指令
6.1 复位new byte[]{0x1B, 0x40};6.2 居中
new byte[]{0x1b, 0x61, 0x01};6.3 居左
new byte[]{0x1b, 0x61, 0x00};6.4 普通大小
new byte[]{0x1d, 0x21, 0x00};6.5 加高
new byte[]{0x1d, 0x21, 0x01};6.6 字体加粗
new byte[]{0x1b, 0x45, 0x01};6.7 取消字体加粗
new byte[]{0x1b, 0x45, 0x00};6.8 换行
new byte[]{10};参考文献:
MCP-58系列用户手册.pdf
打印机编程手册ESC指令.pdf
https://blog.csdn.net/bzdwdmzjsmff/article/details/51325718
https://blog.csdn.net/qq_34942689/article/details/72820226?locationNum=3&fps=1