研究了好几天的pos机打印,终于搞好了,在此做个笔记。第一次写博客 ,如有不对,望提出。
由于pos机可打印多种类型图片,我打印的是光栅位图,另外pos机也可打印其他多种类型图片,在此只说明光栅位图的打印。
给pos机传的都是16进制,所以以下指令都是16进制的字符串。
先贴出我用到的打印机指令:
String MIDDLE="1B 61 01"; //居中
String LEFT="1B 61 00"; //靠左
String LINE="0A"; //换行
居中、靠左、换行这几个指令对于文本和图片都是可用的
下面是打印光栅位图的指令:
String i1 = "1D";
String i2 = "76";
String i3 ="30";
String i4 ="00" ;
String xL;
String xH;
String yL;
String yH;
以上指令中:i4值可 根据需求制定:0普通模式,1倍宽模式,2倍高模式,3四倍大小
xL+xH*256=图片的宽/8
yL+yH*256=图片的高
为什么这里宽要除8呢?
一个像素点需要把自己的信息传递给pos机,信息中1代表打印 0代表不打印,而1byte=8bit;一个像素点是一个byte; 需要用8位二进制传递信息,传给打印机的时候8位二进制会转成高位和低位的十六进制.
对于这个的理解我也不是很透彻,还不太理解的自行百度.
有了以上指令就可以pos机打印啦 直接贴代码
打印文本:
StringBuffer sb=new StringBuffer();
sb.append(MIDDLE).append(title).append(LINE)
.append(LEFT).append(name).append(LINE)
.append(time).append(LINE)
.append(money).append(LINE);
以上代码居中命令在需要居中的文本之前调用,靠左只需调用一次,pos机默认靠左, title,name,time,money是需要打印的信息 这些信息也是需要转成十六进制滴
文本信息转十六进制代码:
/**
* 字符串转换为16进制字符
*/
public static String str2HexStr(String str){
char[] chars = "0123456789ABCDEF".toCharArray();
StringBuilder sb = new StringBuilder("");
byte[] bs = new byte[0];
try {
bs = str.getBytes("GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
int bit;
for (int i = 0; i < bs.length; i++)
{
bit = (bs[i] & 0x0f0) >> 4;
sb.append(chars[bit]);
bit = bs[i] & 0x0f;
sb.append(chars[bit]);
sb.append(' ');
}
return sb.toString().trim();
}
通过以上就拿到文本的16进制字符串,当然打印机需要的是16进制字节, 16进制字符串转16进制byte数组代码在文章最后
打印图片:
//打印机打印图片指令 xl+xh*256=宽 yl+yh*256=高
int width= bitmap.getWidth()/8;
int height=bitmap.getHeight();
int xl=width%256; //低位取余 高位取商
int xh=width/256;
int yl=height%256;
int yh=height/256;
xl,xh,yl,yh在这里还是十进制的 需要转成十六进制, 十进制转十六进制代码:
//10进制转16进制
public static String IntToHex(int n){
char[] ch = new char[20];
int nIndex = 0;
while ( true ){
int m = n/16;
int k = n%16;
if ( k == 15 )
ch[nIndex] = 'F';
else if ( k == 14 )
ch[nIndex] = 'E';
else if ( k == 13 )
ch[nIndex] = 'D';
else if ( k == 12 )
ch[nIndex] = 'C';
else if ( k == 11 )
ch[nIndex] = 'B';
else if ( k == 10 )
ch[nIndex] = 'A';
else
ch[nIndex] = (char)('0' + k);
nIndex++;
if ( m == 0 )
break;
n = m;
}
StringBuffer sb = new StringBuffer();
sb.append(ch, 0, nIndex);
sb.reverse();
String result=sb.toString();
if(result.length()==1){
result="0"+result;
}
return result;
}
现在打印图片的头指令有了,后面再加上图片的数据就可以了 图片转byte :
public static byte[] sendBWImage(Bitmap img, Context ctx) {
int width = img.getWidth(); //获取位图的宽
int height = img.getHeight(); //获取位图的高
int[] pixels = new int[width * height]; //通过位图的大小创建像素点数组
img.getPixels(pixels, 0, width, 0, 0, width, height);
int[] gray=new int[height*width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int grey = pixels[width * i + j];
int red = ((grey & 0x00FF0000 ) >> 16);
gray[width*i+j]=red;
}
}
//551
int e=0;
int byteLen = width/8;
byte[] result=new byte[byteLen*height];
int k=0;
for (int i = 0; i < height; i++) {
byte[] bt = new byte[byteLen];
for (int j = 0; j < width; j++) {
int g=gray[width*i+j];
int byteIndex = j/8;
int bitIndex = j%8;
if (g>=128) {
pixels[width*i+j]=0xffffffff;
e=g-255;
}else {
pixels[width*i+j]=0xff000000;
if(j < byteLen*8){
bt[byteIndex] += 1<<(7-bitIndex);
}
e=g-0;
}
if (j<width-1&&i<height-1) {//右边像素处理
gray[width*i+j+1]+=3*e/8; //下
gray[width*(i+1)+j]+=3*e/8;//右下
gray[width*(i+1)+j+1]+=e/4;
}else if (j==width-1&&i<height-1) {//靠右或靠下边s的像素的情况
//下方像素处理
gray[width*(i+1)+j]+=3*e/8;
}else if (j<width-1&&i==height-1) {
//右边像素处理
gray[width*(i)+j+1]+=e/4;
}
}
for(int m=0;m<bt.length;m++){
result[k++]=bt[m];
}
}
Bitmap mBitmap=Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
mBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
// ImageUtils.saveMyBitmap("0001", mBitmap);
return result;
}
现在头指令和图片数据都有了 怎么把String类型的16进制和byte类型的结合在一起呢?
16进制字符串转byte数组代码:
/**
* 将指定字符串src,以每两个字符分割转换为16进制形式 如:"2B44EFD9" –> byte[]{0x2B, 0×44, 0xEF,
* 0xD9}
*
* @param src
* String
* @return byte[]
*/
public static byte[] HexString2Bytes(String src) {
if (null == src || 0 == src.length()) {
return null;
}
byte[] ret = new byte[src.length() / 2];
byte[] tmp = src.getBytes();
for (int i = 0; i < (tmp.length / 2); i++) {
ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
}
return ret;
}
/**
* 将两个ASCII字符合成一个字节; 如:"EF"–> 0xEF
*
* @param src0
* byte
* @param src1
* byte
* @return byte
*/
public static byte uniteBytes(byte src0, byte src1) {
byte _b0 = Byte.decode("0x" + new String(new byte[] {src0})).byteValue();
_b0 = (byte) (_b0 << 4);
byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 })).byteValue();
byte ret = (byte) (_b0 ^ _b1);
return ret;
}
把16进制字节发给打印机就ok了.
第一次写博客 排版可能不太好 望谅解 有不对的地方多谢指出.