研究了好几天的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了.


第一次写博客 排版可能不太好  望谅解 有不对的地方多谢指出.