package com.sunmi.innerprinter; import java.io.UnsupportedEncodingException; import java.util.List; import java.util.ArrayList; import java.util.Map; import android.graphics.Bitmap; import android.graphics.BitmapFactory; public class ESCUtil { public static final byte ESC = 27;// 换码 public static final byte FS = 28;// 文本分隔符 public static final byte GS = 29;// 组分隔符 public static final byte DLE = 16;// 数据连接换码 public static final byte EOT = 4;// 传输结束 public static final byte ENQ = 5;// 询问字符 public static final byte SP = 32;// 空格 public static final byte HT = 9;// 横向列表 public static final byte LF = 10;// 打印并换行(水平定位) public static final byte CR = 13;// 归位键 public static final byte FF = 12;// 走纸控制(打印并回到标准模式(在页模式下) ) public static final byte CAN = 24;// 作废(页模式下取消打印数据 ) // ------------------------打印机初始化----------------------------- private static String hexStr = "0123456789ABCDEF"; private static String[] binaryArray = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" }; private static byte uniteBytes(byte src0, byte src1) { byte _b0 = Byte.decode(new String(new byte[] { src0 })).byteValue(); _b0 = (byte) (_b0 << 4); byte _b1 = Byte.decode(new String(new byte[] { src1 })).byteValue(); byte ret = (byte) (_b0 | _b1); byte aret = Byte.decode("0x" + ret).byteValue(); return aret; } public static String binaryStrToHexString(String binaryStr) { String hex = ""; String f4 = binaryStr.substring(0, 4); String b4 = binaryStr.substring(4, 8); for (int i = 0; i < binaryArray.length; i++) { if (f4.equals(binaryArray[i])) hex += hexStr.substring(i, i + 1); } for (int i = 0; i < binaryArray.length; i++) { if (b4.equals(binaryArray[i])) hex += hexStr.substring(i, i + 1); } return hex; } public static byte[] HexStringToBinary(String hexString) { int len = hexString.length() / 2; byte[] bytes = new byte[len]; byte high = 0; byte low = 0; for (int i = 0; i < len; i++) { high = (byte) ((hexStr.indexOf(hexString.charAt(2 * i))) << 4); low = (byte) hexStr.indexOf(hexString.charAt(2 * i + 1)); bytes[i] = (byte) (high & 0xF0 | low & 0x0F); } return bytes; } public static List<String> binaryListToHexStringList(List<String> list) { List<String> hexList = new ArrayList<String>(); for (String binaryStr : list) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < binaryStr.length(); i += 8) { String str = binaryStr.substring(i, i + 8); String hexString = binaryStrToHexString(str); sb.append(hexString); } hexList.add(sb.toString()); } return hexList; } public static byte[] sysCopy(List<byte[]> srcArrays) { int len = 0; for (byte[] srcArray : srcArrays) { len += srcArray.length; } byte[] destArray = new byte[len]; int destLen = 0; for (byte[] srcArray : srcArrays) { System.arraycopy(srcArray, 0, destArray, destLen, srcArray.length); destLen += srcArray.length; } return destArray; } public static byte[] hexList2Byte(List<String> list) { List<byte[]> commandList = new ArrayList<byte[]>(); for (String hexStr : list) { commandList.add(HexStringToBinary(hexStr)); } byte[] bytes = sysCopy(commandList); return bytes; } /** * 打印机初始化 * * @return */ public static byte[] init_printer() { byte[] result = new byte[2]; result[0] = ESC; result[1] = 64; return result; } // ------------------------换行----------------------------- /** * 换行 * * @param lineNum要换几行 * @return */ public static byte[] nextLine(int lineNum) { byte[] result = new byte[lineNum]; for (int i = 0; i < lineNum; i++) { result[i] = LF; } return result; } // ------------------------下划线----------------------------- /** * 绘制下划线(1点宽) * * @return */ public static byte[] underlineWithOneDotWidthOn() { byte[] result = new byte[3]; result[0] = ESC; result[1] = 45; result[2] = 1; return result; } /** * 绘制下划线(2点宽) * * @return */ public static byte[] underlineWithTwoDotWidthOn() { byte[] result = new byte[3]; result[0] = ESC; result[1] = 45; result[2] = 2; return result; } /** * 取消绘制下划线 * * @return */ public static byte[] underlineOff() { byte[] result = new byte[3]; result[0] = ESC; result[1] = 45; result[2] = 0; return result; } // ------------------------加粗----------------------------- /** * 选择加粗模式 * * @return */ public static byte[] boldOn() { byte[] result = new byte[3]; result[0] = ESC; result[1] = 69; result[2] = 0xF; return result; } /** * 取消加粗模式 * * @return */ public static byte[] boldOff() { byte[] result = new byte[3]; result[0] = ESC; result[1] = 69; result[2] = 0; return result; } // ------------------------对齐----------------------------- /** * 左对齐 * * @return */ public static byte[] alignLeft() { byte[] result = new byte[3]; result[0] = ESC; result[1] = 97; result[2] = 0; return result; } /** * 居中对齐 * * @return */ public static byte[] alignCenter() { byte[] result = new byte[3]; result[0] = ESC; result[1] = 97; result[2] = 1; return result; } /** * 右对齐 * * @return */ public static byte[] alignRight() { byte[] result = new byte[3]; result[0] = ESC; result[1] = 97; result[2] = 2; return result; } /** * 水平方向向右移动col列 * * @param col * @return */ public static byte[] set_HT_position(byte col) { byte[] result = new byte[4]; result[0] = ESC; result[1] = 68; result[2] = col; result[3] = 0; return result; } // ------------------------字体变大----------------------------- /** * 字体变大为标准的n倍 * * @param num * @return */ public static byte[] fontSizeSetBig(int num) { byte realSize = 0; switch (num) { case 1: realSize = 0; break; case 2: realSize = 17; break; case 3: realSize = 34; break; case 4: realSize = 51; break; case 5: realSize = 68; break; case 6: realSize = 85; break; case 7: realSize = 102; break; case 8: realSize = 119; break; } byte[] result = new byte[3]; result[0] = 29; result[1] = 33; result[2] = realSize; return result; } // ------------------------字体变小----------------------------- /** * 字体取消倍宽倍高 * * @param num * @return */ public static byte[] fontSizeSetSmall(int num) { byte[] result = new byte[3]; result[0] = ESC; result[1] = 33; return result; } // ------------------------切纸----------------------------- /** * 进纸并全部切割 * * @return */ public static byte[] feedPaperCutAll() { byte[] result = new byte[4]; result[0] = GS; result[1] = 86; result[2] = 65; result[3] = 0; return result; } /** * 进纸并切割(左边留一点不切) * * @return */ public static byte[] feedPaperCutPartial() { byte[] result = new byte[4]; result[0] = GS; result[1] = 86; result[2] = 66; result[3] = 0; return result; } // ------------------------切纸----------------------------- public static byte[] byteMerger(byte[] byte_1, byte[] byte_2) { byte[] byte_3 = new byte[byte_1.length + byte_2.length]; System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length); System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length); return byte_3; } public static byte[] byteMerger(byte[][] byteList) { int length = 0; for (int i = 0; i < byteList.length; i++) { length += byteList[i].length; } byte[] result = new byte[length]; int index = 0; for (int i = 0; i < byteList.length; i++) { byte[] nowByte = byteList[i]; for (int k = 0; k < byteList[i].length; k++) { result[index] = nowByte[k]; index++; } } for (int i = 0; i < index; i++) { // CommonUtils.LogWuwei("", "result[" + i + "] is " + result[i]); } return result; } // -------------------- public static byte[] generateMockData() { try { byte[] next2Line = ESCUtil.nextLine(2); byte[] title = "出餐单(午餐)**万通中心店".getBytes("gb2312"); byte[] boldOn = ESCUtil.boldOn(); byte[] fontSize2Big = ESCUtil.fontSizeSetBig(3); byte[] center = ESCUtil.alignCenter(); byte[] Focus = "网 507".getBytes("gb2312"); byte[] boldOff = ESCUtil.boldOff(); byte[] fontSize2Small = ESCUtil.fontSizeSetSmall(3); byte[] left = ESCUtil.alignLeft(); byte[] orderSerinum = "订单编号:11234".getBytes("gb2312"); boldOn = ESCUtil.boldOn(); byte[] fontSize1Big = ESCUtil.fontSizeSetBig(2); byte[] FocusOrderContent = "韭菜鸡蛋饺子-小份(单)".getBytes("gb2312"); boldOff = ESCUtil.boldOff(); byte[] fontSize1Small = ESCUtil.fontSizeSetSmall(2); next2Line = ESCUtil.nextLine(2); byte[] priceInfo = "应收:22元 优惠:2.5元 ".getBytes("gb2312"); byte[] nextLine = ESCUtil.nextLine(1); byte[] priceShouldPay = "实收:19.5元".getBytes("gb2312"); nextLine = ESCUtil.nextLine(1); byte[] takeTime = "取餐时间:2015-02-13 12:51:59".getBytes("gb2312"); nextLine = ESCUtil.nextLine(1); byte[] setOrderTime = "下单时间:2015-02-13 12:35:15".getBytes("gb2312"); byte[] tips_1 = "微信关注\"**\"自助下单每天免1元".getBytes("gb2312"); nextLine = ESCUtil.nextLine(1); byte[] tips_2 = "饭后点评再奖5毛".getBytes("gb2312"); byte[] next4Line = ESCUtil.nextLine(4); byte[] breakPartial = ESCUtil.feedPaperCutPartial(); byte[][] cmdBytes = { title, nextLine, center, boldOn, fontSize2Big, Focus, boldOff, fontSize2Small, next2Line, left, orderSerinum, nextLine, center, boldOn, fontSize1Big, FocusOrderContent, boldOff, fontSize1Small, nextLine, left, next2Line, priceInfo, nextLine, priceShouldPay, next2Line, takeTime, nextLine, setOrderTime, next2Line, center, tips_1, nextLine, center, tips_2, next4Line, breakPartial }; return ESCUtil.byteMerger(cmdBytes); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } public static byte[] decodeBitmap(byte[] bitmapBytes) { Bitmap bmp = BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length); int zeroCount = bmp.getWidth() % 8; String zeroStr = ""; if (zeroCount > 0) { for (int i = 0; i < (8 - zeroCount); i++) { zeroStr = zeroStr + "0"; } } List<String> list = new ArrayList<>(); for (int i = 0; i < bmp.getHeight(); i++) { StringBuilder sb = new StringBuilder(); for (int j = 0; j < bmp.getWidth(); j++) { int color = bmp.getPixel(j, i); int r = (color >> 16) & 0xff; int g = (color >> 8) & 0xff; int b = color & 0xff; // if color close to white,bit='0', else bit='1' if (r > 160 && g > 160 && b > 160) sb.append("0"); else sb.append("1"); } if (zeroCount > 0) { sb.append(zeroStr); } list.add(sb.toString()); } List<String> bmpHexList = binaryListToHexStringList(list); List<String> commandList = new ArrayList<>(); commandList.addAll(bmpHexList); return hexList2Byte(commandList); } public static byte[] decodeBitmap2(byte[] bitmapBytes) { Bitmap bmp = BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length); return draw2PxPoint(bmp); } public static byte[] draw2PxPoint(Bitmap bmp) { //用来存储转换后的 bitmap 数据。为什么要再加1000,这是为了应对当图片高度无法 //整除24时的情况。比如bitmap 分辨率为 240 * 250,占用 7500 byte, //但是实际上要存储11行数据,每一行需要 24 * 240 / 8 =720byte 的空间。再加上一些指令存储的开销, //所以多申请 1000byte 的空间是稳妥的,不然运行时会抛出数组访问越界的异常。 int size = bmp.getWidth() * bmp.getHeight() / 8 + 1000; byte[] data = new byte[size]; int k = 0; //设置行距为0的指令 data[k++] = 0x1B; data[k++] = 0x33; data[k++] = 0x00; // 逐行打印 for (int j = 0; j < bmp.getHeight() / 24f; j++) { //打印图片的指令 data[k++] = 0x1B; data[k++] = 0x2A; data[k++] = 33; data[k++] = (byte) (bmp.getWidth() % 256); //nL data[k++] = (byte) (bmp.getWidth() / 256); //nH //对于每一行,逐列打印 for (int i = 0; i < bmp.getWidth(); i++) { //每一列24个像素点,分为3个字节存储 for (int m = 0; m < 3; m++) { //每个字节表示8个像素点,0表示白色,1表示黑色 for (int n = 0; n < 8; n++) { byte b = px2Byte(i, j * 24 + m * 8 + n, bmp); data[k] += data[k] + b; } k++; } } data[k++] = 10;//换行 } return data; } /** * 灰度图片黑白化,黑色是1,白色是0 * * @param x 横坐标 * @param y 纵坐标 * @param bit 位图 * @return */ public static byte px2Byte(int x, int y, Bitmap bit) { if (x < bit.getWidth() && y < bit.getHeight()) { byte b; 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; } return 0; } /** * 图片灰度的转化 */ private static int RGB2Gray(int r, int g, int b) { int gray = (int) (0.29900 * r + 0.58700 * g + 0.11400 * b); //灰度转化公式 return gray; } }