近来开发一个配送单打印服务,买了一台芯烨打印机来打印配送小票。网口版打印机型号XP-N160II。官网上没找到电脑端Java版的开发demo,找了开发文档也没有直接支持二维码打印的指令。一番折腾,然后找芯烨售后技术支持:
好吧,退货换一款打印机! 想想退货来回浪费时间...
于是认真研究了下开发文档,看到如下一条打印光栅图片的指令,决定自己搞试试
说开始就开始,不多说直接上核心代码
/**
* 使用光栅图方式打印二维码
* @param m
* @param content 二维码内容
* @param alignType 打印位置
* @param pagewidth 纸张宽度
* @param qrcode_size 二维码大小
* @return
* @throws WriterException
*/
public static byte[] strToSendData(int m, String content, AlignType alignType, int pagewidth, int qrcode_size) throws WriterException {
// 使用二维码工具包生成二维码
// <dependency>
// <groupId>com.google.zxing</groupId>
// <artifactId>core</artifactId>
// <version>3.4.0</version>
// </dependency>
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, qrcode_size, qrcode_size, hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
int[] pixels = new int[width * height];
// 下面这里按照二维码的算法,逐个生成二维码的图片, 两个for循环是图片横列扫描的结果
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (bitMatrix.get(x, y)) {
pixels[y * width + x] = 0xff000000;
} else {
pixels[y * width + x] = 0xffffffff;
}
}
}
//将像素转化成字节数据
byte[] data = getbmpdata(pixels, width, height);
int n = (width + 7) / 8;
byte xL = (byte) (n % 256);
byte xH = (byte) (n / 256);
List list = new ArrayList();
byte[] head = { 29, 118, 48, (byte) m, xL, xH, (byte) height };
int mL = 0;
int mH = 0;
if (width >= pagewidth) {
alignType = AlignType.Left;
}
switch (alignType) {
case Left:
mL = (pagewidth - width) / 2 % 256;
mH = (pagewidth - width) / 2 / 256;
break;
case Center:
mL = 0;
mH = 0;
break;
case Right:
mL = (pagewidth - width) % 256;
mH = (pagewidth - width) / 256;
break;
}
byte[] aligndata = DataForSendToPrinterPos80.setAbsolutePrintPosition(mL, mH);
byte[] newdata = new byte[n * height];
System.arraycopy(data, 0, newdata, 0, height * n);
if (alignType != AlignType.Left) {
for (byte b : aligndata) {
list.add(Byte.valueOf(b));
}
}
for (byte b : head) {
list.add(Byte.valueOf(b));
}
for (byte b : newdata) {
list.add(Byte.valueOf(b));
}
byte[] byteData = new byte[list.size()];
for (int i = 0; i < byteData.length; i++) {
byteData[i] = ((Byte) list.get(i)).byteValue();
}
return byteData;
}
/**
* 像素转化成字节数据
* @param b
* @param w
* @param h
* @return
*/
private static byte[] getbmpdata(int[] b, int w, int h) {
int n = (w + 7) / 8;
byte[] data = new byte[n * h];
byte mask = 1;
for (int y = 0; y < h; y++) {
for (int x = 0; x < n * 8; x++) {
if (x < w) {
if ((b[(y * w + x)] & 0xFF0000) >> 16 == 0)
continue;
int tmp66_65 = (y * n + x / 8);
byte[] tmp66_54 = data;
tmp66_54[tmp66_65] = (byte) (tmp66_54[tmp66_65] | (byte) (mask << 7 - x % 8));
} else if (x >= w) {
int tmp104_103 = (y * n + x / 8);
byte[] tmp104_92 = data;
tmp104_92[tmp104_103] = (byte) (tmp104_92[tmp104_103] | (byte) (mask << 7 - x % 8));
}
}
}
for (int i = 0; i < data.length; i++) {
data[i] = (byte) (data[i] ^ 0xFFFFFFFF);
}
return data;
}
}
到这便结束了,我们测试下
/**
*
* @author chencg
* @Date 2019年10月24日
*/
public class PrintTest {
private static final String CHARSET = "utf-8";
// 二维码尺寸
private static final int QRCODE_SIZE = 200;
public static void main(String[] args) {
String PRINT_IP = "192.168.3.100";
int PRINT_PORT = 9100;
// 建立打印机连接
Socket socket = null;
OutputStream socketOut = null;
OutputStreamWriter writer = null;
try {
socket = new Socket(PRINT_IP, PRINT_PORT);
socketOut = socket.getOutputStream();
writer = new OutputStreamWriter(socketOut, "utf-8");
// 初始化打印机,清除缓存
socketOut.write(DataForSendToPrinterPos80.initializePrinter());
// 选择对齐方式
//socketOut.write(DataForSendToPrinterPos80.selectAlignment(1));
byte[] data = strToSendData(3, "二维码", AlignType.Center, 576);
socketOut.write(data);
socketOut.write(DataForSendToPrinterPos80.printAndFeedLine());
//选择切纸模式并切纸
socketOut.write(DataForSendToPrinterPos80.selectCutPagerModerAndCutPager(66, 3));
// 打印指令
socketOut.write(DataForSendToPrinterPos80.printAndFeedLine());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
socketOut.flush();
writer.close();
socketOut.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
打印出来效果满意,不需要退货了。
转载自原文链接, 如需删除请联系管理员。
原文链接:如何让芯烨打印机支持打印二维码,转载请注明来源!