研究了好几天的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了.
第一次写博客 排版可能不太好 望谅解 有不对的地方多谢指出.