任务
由于得力打印机(DL888D型号)不提供Linux版本驱动,其驱动开发商 seagull 只为Windows服务。故需要在Linux下提供能够对接打印机的软件。
打印机描述:该型号打印机是用来打印条形码、二维码等黑白图片的打印机(貌似叫热感打印机)。该打印机支持tspl指令。
输入:1、输入图像在纸上打印的长、宽(单位 mm),2、要打印的图像
输出:将输入的图片居中打印在打印纸上。
所需Lib
1、libusb:http://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-1.0.9/libusb-1.0.9.tar.bz2
该lib为c++包。
知识补充
1、TSPL指令:该指令是用于打印条形码打印机的统一指令,大多条形码打印机都支持该指令。
https://max.book118.com/html/2016/0226/35995692.shtm
2、libusb安装与使用方式:https://blog.csdn.net/psy6653/article/details/56678276
3、.prn 文件为打印文件,构建该文件,将该文件转换为字节码通过usb端口发送给打印机,打印机会自动读取字节码,并做出相关的工作。
4、DL888D 打印机会将接受到的指令存储在打印机的指令存储器中,如果指令有错,打印机会卡死,这时需要将打印机断电,指令存储器中存储的错误指令才会自动清除。
5、jni调用:
总体思想
java构建UI界面,接受输入的长、宽 ,图片。然后构建指令,将指令转为字节码,构建prn文件,通过JNI调用,调用so库。
C语言构建so库,主要功能为使用usblib 向 usb发送字节码。(将prn文件提取为字节码发送给usb端口,打印机会自动识别字节码)
关键命令与解析
关键指令在源码的 Config.java 文件中的TSPL变量:
public static final String TSPL = "SIZE 60 mm,40 mm\n" + "CLS\n" + "BITMAP ##WALTY_BYTES##\n" + "PRINT 1,1\n";
其中 ##WALTY_BYTES## 为占位符,之后替换为对应的BITMAP指令。
指令的具体解析请参考 :TSPL指令
关键代码
1)java 图片二值化
public static void imgFilter(int width,int height,String path,ByteArrayOutputStream baos) throws IOException { File file = new File(path); BufferedImage image = ImageIO.read(file); String str = (Config.PAPER_WIDTH - width*8)/2 + "," + (Config.PAPER_HEIGHT - height*8)/2 + "," + width+","+ (height*8) +","+Config.BITMAT_MODE+","; System.out.println(str); baos.write(str.getBytes()); byte b = 0x00; BitSet bs = new BitSet(8); BufferedImage grayImage = zoomInImage(image,width*8,height*8); int cols = grayImage.getWidth(); int rows = grayImage.getHeight(); for(int row = 0 ; row < rows ; row++){ for(int col = 0 ; col < cols; col++){ if(grayImage.getRGB(col, row) == -1) { b = (byte)(b | 0x80 >> (col%8)); } if((col%8 == 7 && col != 0) || col == cols-1) { baos.write(b); b = 0x00; } } b = 0x00; } }
该代码主要为将输入的图片二值化、拉伸为输入的长、宽,然后按照BITMAP指令要求,构建对应的格式。
2)向USB端口发送字节码
void send_msg(int len){ int ret = 1; int i = 0; int transferred = 0; //printf("fc = %s,len = %d\n",file_content,len); first_send(); ret = libusb_bulk_transfer(dev_handle, EP2ADDR, file_content, len, &transferred, USB_TIMEOUT); //printf("ret = %d,trans = %d\n",ret,transferred); if(ret==0 && transferred==len){ printf("write Successful!\n"); }else{ printf("write error!\n"); } }