当前位置:   article > 正文

java实现ZEBRA斑马打印机 FNTHEX32.dll 打印图片和文字_fnthex32.dll 支持多种字符打印

fnthex32.dll 支持多种字符打印

斑马打印中文的原理是使用FNTHEX32将中文转换成图片,再转换成斑马能识别的字符串代码

但是java调用DLL是无法跨平台的,所以按照斑马的图片编码原理我写了一个java版的图片编码类,供掉坑的各苦逼程序猿参考


  1. public class Fnthex {
  2. public static BufferedImage source = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
  3. public static Graphics2D gs = source.createGraphics();
  4. // public static String getFontZpl(String content, int x, int y, int size, String fontName) {
  5. // return String.format("^FO%d,%d^A1N,%d,%d^FD%s^FS", x, y, size, size, content);
  6. // }
  7. public static String getFontHexWithWidth(String content, int x, int y, int width,
  8. int maxHeight, String fontName) {
  9. if (content == null || "".equals(content))
  10. return "";
  11. Font f = null;
  12. width = (width + 7) / 8 * 8;
  13. int size = width / content.length();
  14. int retryFlag = 1;
  15. if (size > maxHeight) {
  16. size = maxHeight;
  17. if ("宋体".equals(fontName)) {
  18. f = new Font("simsun", Font.PLAIN, size);
  19. } else if ("黑体".equals(fontName)) {
  20. f = new Font("simhei", Font.BOLD, size);
  21. } else {
  22. f = new Font("simsun", Font.PLAIN, size);
  23. }
  24. } else {
  25. while (true) {
  26. if ("宋体".equals(fontName)) {
  27. f = new Font("simsun", Font.PLAIN, size);
  28. } else if ("黑体".equals(fontName)) {
  29. f = new Font("simhei", Font.BOLD, size);
  30. } else {
  31. f = new Font("simsun", Font.PLAIN, size);
  32. }
  33. gs.setFont(f);
  34. FontMetrics fontMetrics = gs.getFontMetrics();
  35. Rectangle2D stringBounds = fontMetrics.getStringBounds(content, gs);
  36. int nw = (int) stringBounds.getWidth();
  37. if (nw > width) {
  38. size--;
  39. if (retryFlag == 1) {
  40. break;
  41. }
  42. retryFlag = 0;
  43. } else {
  44. if (size >= maxHeight)
  45. break;
  46. size++;
  47. retryFlag = 1;
  48. }
  49. }
  50. }
  51. int height = size;
  52. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
  53. Graphics2D g2 = image.createGraphics();
  54. g2.setFont(f);
  55. g2.setColor(Color.BLACK);
  56. g2.drawString(content, 1, (int) (height * 0.88));
  57. g2.dispose();
  58. StringBuilder zpl = new StringBuilder("^FO").append(x).append(",").append(y)
  59. .append(getImage(image)).append("^FS");
  60. return zpl.toString();
  61. }
  62. public static String getFontHex(String content, int x, int y, int size, String fontName) {
  63. if (content == null || "".equals(content))
  64. return "";
  65. Font f = null;
  66. if ("宋体".equals(fontName)) {
  67. f = new Font("simsun", Font.PLAIN, size);
  68. } else if ("黑体".equals(fontName)) {
  69. f = new Font("simhei", Font.BOLD, size);
  70. } else {
  71. f = new Font("simsun", Font.PLAIN, size);
  72. }
  73. gs.setFont(f);
  74. FontMetrics fontMetrics = gs.getFontMetrics();
  75. Rectangle2D stringBounds = fontMetrics.getStringBounds(content, gs);
  76. int width = (int) stringBounds.getWidth();
  77. int height = size;
  78. width = (width + 7) / 8 * 8;
  79. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
  80. Graphics2D g2 = image.createGraphics();
  81. g2.setFont(f);
  82. g2.setColor(Color.BLACK);
  83. g2.drawString(content, 1, (int) (height * 0.88));
  84. g2.dispose();
  85. StringBuilder zpl = new StringBuilder("^FO").append(x).append(",").append(y)
  86. .append(getImage(image)).append("^FS");
  87. return zpl.toString();
  88. }
  89. private static final char[] HEX = "0123456789ABCDEF".toCharArray();
  90. public static String printImage(BufferedImage image, int x, int y) {
  91. if (image.getWidth() % 8 != 0) {
  92. BufferedImage i = new BufferedImage(((image.getWidth() + 7) / 8) * 8,
  93. image.getHeight(), BufferedImage.TYPE_INT_ARGB);
  94. Graphics2D g2 = i.createGraphics();
  95. g2.drawImage(image, null, 0, 0);
  96. g2.dispose();
  97. image = i;
  98. }
  99. StringBuilder zpl = new StringBuilder("^FO").append(x).append(",").append(y)
  100. .append(getImage(image)).append("^FS");
  101. return zpl.toString();
  102. }
  103. private static String getImage(BufferedImage i) {
  104. int w = i.getWidth();
  105. int h = i.getHeight();
  106. boolean black[] = getBlackPixels(i, w, h);
  107. int hex[] = getHexValues(black);
  108. String data = ints2Hex(hex);
  109. int bytes = data.length() / 2;
  110. int perRow = bytes / h;
  111. return "^GFA," + bytes + "," + bytes + "," + perRow + "," + data;
  112. }
  113. private static String flipRows(String hex, int height) {
  114. String flipped = "";
  115. int width = hex.length() / height;
  116. for (int i = 0; i < height; i++) {
  117. flipped += new StringBuilder(hex.substring(i * width, (i + 1) * width)).reverse()
  118. .toString();
  119. }
  120. return flipped;
  121. }
  122. /**
  123. * Returns an array of ones or zeros. boolean is used instead of int for memory considerations.
  124. *
  125. * @param o
  126. * @return
  127. */
  128. private static boolean[] getBlackPixels(BufferedImage bi, int w, int h) {
  129. int[] rgbPixels = ((DataBufferInt) bi.getRaster().getDataBuffer()).getData();
  130. int i = 0;
  131. boolean[] pixels = new boolean[rgbPixels.length];
  132. for (int rgbpixel : rgbPixels) {
  133. pixels[i++] = isBlack(rgbpixel);
  134. }
  135. return pixels;
  136. }
  137. private static boolean isBlack(int rgbPixel) {
  138. int a = (rgbPixel & 0xFF000000) >>> 24;
  139. if (a < 127) {
  140. return false; // assume pixels that are less opaque than the luma threshold should be considered to be white
  141. }
  142. int r = (rgbPixel & 0xFF0000) >>> 16;
  143. int g = (rgbPixel & 0xFF00) >>> 8;
  144. int b = rgbPixel & 0xFF;
  145. int luma = ((r * 299) + (g * 587) + (b * 114)) / 1000; //luma formula
  146. return luma < 127;
  147. }
  148. private static int[] getHexValues(boolean[] black) {
  149. int[] hex = new int[(int) (black.length / 8)];
  150. // Convert every eight zero's to a full byte, in decimal
  151. for (int i = 0; i < hex.length; i++) {
  152. for (int k = 0; k < 8; k++) {
  153. hex[i] += (black[8 * i + k] ? 1 : 0) << 7 - k;
  154. }
  155. }
  156. return hex;
  157. }
  158. public static String getHexString(byte[] b) throws Exception {
  159. String result = "";
  160. for (int i = 0; i < b.length; i++) {
  161. result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
  162. }
  163. return result;
  164. }
  165. private static String ints2Hex(int[] ints) {
  166. char[] hexChars = new char[ints.length * 2];
  167. for (int i = 0; i < ints.length; ++i) {
  168. hexChars[i * 2] = HEX[(ints[i] & 0xF0) >> 4];
  169. hexChars[i * 2 + 1] = HEX[ints[i] & 0x0F];
  170. }
  171. return new String(hexChars);
  172. }
  173. public static void main(String[] args) {
  174. System.out.println(getFontHex("你好", 10, 50, 80, "黑体"));
  175. }
  176. }

getFontHexWithWidth
方法支持定宽文字自动缩小

getFontHex
将图片编码成ZPL格式


printImage
直接打印图片


命令中已包含^FO和^FS 是完整的一条ZPL指令


这是掉了无数坑过后提炼出来的代码,生成速度经过测试已达到工业级标准,在0.7主频的树莓派上生成一张热敏电子面单只需要0.4-0.8秒

希望对研究斑马打印机的人有所帮助。


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/179597
推荐阅读
相关标签
  

闽ICP备14008679号