最近一期做WiFi打印机打印小票功能,其中有一个功能点是把Logo打印在小票上面。
实现思路就是对网上的思路进行一下调整修改,方便Android端调用,很简单;
测试的打印机型号:Zebra GK888T
Bitmap to ZPL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
/**
* 把Bitmap –> ZPL, 拼接成一个ZPL命令
*/
public class ZPLImageConverter {
private Context context;
public ZPLImageConverter(Context context) {
this.context = context;
}
private int blackLimit = 380;
private int total;
private int widthBytes;
private boolean compressHex = false;
private static Map<Integer, String> mapCode = new HashMap<Integer, String>();
{
mapCode.put(1, “G”);
mapCode.put(2, “H”);
mapCode.put(3, “I”);
mapCode.put(4, “J”);
mapCode.put(5, “K”);
mapCode.put(6, “L”);
mapCode.put(7, “M”);
mapCode.put(8, “N”);
mapCode.put(9, “O”);
mapCode.put(10, “P”);
mapCode.put(11, “Q”);
mapCode.put(12, “R”);
mapCode.put(13, “S”);
mapCode.put(14, “T”);
mapCode.put(15, “U”);
mapCode.put(16, “V”);
mapCode.put(17, “W”);
mapCode.put(18, “X”);
mapCode.put(19, “Y”);
mapCode.put(20, “g”);
mapCode.put(40, “h”);
mapCode.put(60, “i”);
mapCode.put(80, “j”);
mapCode.put(100, “k”);
mapCode.put(120, “l”);
mapCode.put(140, “m”);
mapCode.put(160, “n”);
mapCode.put(180, “o”);
mapCode.put(200, “p”);
mapCode.put(220, “q”);
mapCode.put(240, “r”);
mapCode.put(260, “s”);
mapCode.put(280, “t”);
mapCode.put(300, “u”);
mapCode.put(320, “v”);
mapCode.put(340, “w”);
mapCode.put(360, “x”);
mapCode.put(380, “y”);
mapCode.put(400, “z”);
}
public String convertFromImg(Bitmap image) throws IOException {
String cuerpo = createBody(image);
if(compressHex)
cuerpo = encodeHexAscii(cuerpo);
return headDoc() + cuerpo + footDoc();
}
private String createBody(Bitmap originalImage) throws IOException {
StringBuffer sb = new StringBuffer();
// Graphics2D graphics = originalImage.createGraphics();
// graphics.drawImage(originalImage, 0, 0, null);
int height = originalImage.getHeight();
int width = originalImage.getWidth();
int rgb, red, green, blue, index=0;
char auxBinaryChar[] = {‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’};
widthBytes = width/8;
if(width%8 > 0){
widthBytes= (((int)(width / 8)) + 1);
} else {
widthBytes= width/8;
}
this.total = widthBytes*height;
for (int h = 0; h<height; h++)
{
for (int w = 0; w<width; w++)
{
// rgb = originalImage.getRGB(w, h);
rgb = originalImage.getPixel(w, h);
red = (rgb >> 16 ) & 0x000000FF;
green = (rgb >> 8 ) & 0x000000FF;
blue = (rgb) & 0x000000FF;
char auxChar = ‘1’;
int totalColor = red + green + blue;
if(totalColor>blackLimit){
auxChar = ‘0’;
}
auxBinaryChar[index] = auxChar;
index++;
if(index==8 || w==(width-1)){
sb.append(fourByteBinary(new String(auxBinaryChar)));
auxBinaryChar = new char[]{‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’, ‘0’};
index=0;
}
}
sb.append(“\n”);
}
return sb.toString();
}
private String fourByteBinary(String binaryStr){
int decimal = Integer.parseInt(binaryStr,2);
if (decimal>15){
return Integer.toString(decimal,16).toUpperCase();
} else {
return “0” + Integer.toString(decimal,16).toUpperCase();
}
}
private String encodeHexAscii(String code){
int maxlinea = widthBytes * 2;
StringBuffer sbCode = new StringBuffer();
StringBuffer sbLinea = new StringBuffer();
String previousLine = null;
int counter = 1;
char aux = code.charAt(0);
boolean firstChar = false;
for(int i = 1; i< code.length(); i++ ){
if(firstChar){
aux = code.charAt(i);
firstChar = false;
continue;
}
if(code.charAt(i)==‘\n’){
if(counter>=maxlinea && aux==‘0’){
sbLinea.append(“,”);
} else if(counter>=maxlinea && aux==‘F’){
sbLinea.append(“!”);
} else if (counter>20){
int multi20 = (counter/20)*20;
int resto20 = (counter%20);
sbLinea.append(mapCode.get(multi20));
if(resto20!=0){
sbLinea.append(mapCode.get(resto20) + aux);
} else {
sbLinea.append(aux);
}
} else {
sbLinea.append(mapCode.get(counter) + aux);
if(mapCode.get(counter)==null){
}
}
counter = 1;
firstChar = true;
if(sbLinea.toString().equals(previousLine)){
sbCode.append(“:”);
} else {
sbCode.append(sbLinea.toString());
}
previousLine = sbLinea.toString();
sbLinea.setLength(0);
continue;
}
if(aux == code.charAt(i)){
counter++;
} else {
if(counter>20){
int multi20 = (counter/20)*20;
int resto20 = (counter%20);
sbLinea.append(mapCode.get(multi20));
if(resto20!=0){
sbLinea.append(mapCode.get(resto20) + aux);
} else {
sbLinea.append(aux);
}
} else {
sbLinea.append(mapCode.get(counter) + aux);
}
counter = 1;
aux = code.charAt(i);
}
}
return sbCode.toString();
}
private String headDoc() {
String str = /*”^XA ” +*/
“^FO10,50^GFA,”+ total + “,”+ total + “,” + widthBytes +“, “;
return str;
}
private String footDoc(){
String str = “^FS”/*+ “^XZ”*/;
return str;
}
public void setCompressHex(boolean compressHex) {
this.compressHex = compressHex;
}
public void setBlacknessLimitPercentage(int percentage){
blackLimit = (percentage * 768 / 100);
}
}
|
调用方式
就是把Bitmap对象转化为ZPL编码格式,并把转化后的内容塞到ZPL命令中,和打印机通过Wifi 连接,把组装后的命令发给打印机就可以了。
1
2
3
4
5
6
7
|
ZPLImageConverter zp = new ZPLImageConverter(context);
zp.setCompressHex(true);
zp.setBlacknessLimitPercentage(50);
String str = zp.convertFromImg(myBitmap);
zplStr += str;
//…
|
其它命令的时候可以参考zebra打印机官方文档。
refs
- http://labelary.com/viewer.html (在线调整打印小票样式细节)
- http://www.jcgonzalez.com/java-image-to-zpl-example
- https://jinfengli.github.io/2017/11/17/zebra_printer_logo/