热敏打印机图片打印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