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