java調用斑馬GK888t打印機(ZPL指令)

在項目中使用斑馬打印機遇到了以下問題:java

在實際打印信息前,須要修改打印機驅動設置,主要是設置打印顏色深度,默認值通常會打印的比較淺。一般狀況下,在設置的顏色深度後,打印機可以很好的工做。可是若是我將程序註冊爲windows系統服務,以自啓動的方式運行程序後,對於打印機驅動的設置將不會生效。而直接使用控制檯啓動程序,倒是正常的。通過分析以後,懷疑多是因爲,系統服務的啓動方式和直接控制檯啓動的方式是有區別的,兩種方式程序的登陸用戶是不一樣的,系統服務的登陸用戶是SYSTEM(非administration)用戶,控制檯啓動方式就是普通的USER用戶。而打印機的驅動設置,貌似每一個用戶之間是相互獨立的,因此修改了USER用戶的設置,SYSTEM用戶的設置仍然是默認值,因此打印機驅動就不會生效。git

這個問題的一個解決方案,就是使用ZPL指令,直接控制打印機。ZPL是打印機專用的一種編程語言,具體能夠參考《ZPL語言中文手冊》。經過使用ZPL指令,能夠打印問題,條碼,圖片,也能夠修改各類打印參數,包括修改打印濃度參數。因此經過ZPL的方式能夠忽略系統打印機的驅動設置,也就可以隨意修改顏色深度設置了。github

可是如何調用ZPL呢?編程

一種方式能夠經過cmd命令行的方式向打印機發送ZPL指令文件,具體可參考鏈接:http://www.chongshang.com.cn/news/view.asp?id=334。json

另外一種是經過JAVA調用打印機,在發送ZPL指令。這裏我參考了github上的代碼,詳見:https://github.com/w3blogfr/zebra-zpl。從這個代碼中就知道如何經過JAVA向打印機發送ZPL指令了。windows

github上的這個demo程序,用於打印通常的文字,條碼是挺不錯的,可是個人項目中須要打印一張位圖圖片,這個demo中並無相關的示例。因此我查了下ZPL語言的手冊,發現其中的~DG命令可以知足個人需求,通過研究以後,終於可以使用ZPL打印圖片了。如下是打印部分的參考代碼:數組

import java.awt.image.BufferedImage;
import java.awt.print.PrinterException;
import java.io.File;

import javax.imageio.ImageIO;
import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintService;
import javax.print.SimpleDoc;

import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



/**
 * @detail GK888t斑馬打印機ZPL指令打印
 * 相比以前的打印方式,這種方式可以經過程序設置打印機參數
 * 而且解決了使用服務啓動時,不能調整打印機參數的問題
 *
 */
public class PrinterZPL {

	private Logger logger = LoggerFactory.getLogger(getClass());


	/**
	 * @param parcelDetailBo
	 * @return 0成功,-1打印機不存在
	 * @throws PrinterException
	 */
	public JSONObject startPrint() {
		try {

			// 根據打印機名獲取打印服務
			PrintService service = PrinterUtil.getPrintService(printerName);

			// 判斷打印機是否找到
			if (service == null) {
				printJson.put("fullName", "未找到打印機,多是驅動未安裝");
				return printJson;
			} else {
				printJson.put("fullName", service.toString());
			}

			// 判斷打印機是否鏈接
			if (Devcon.DeviceCheck(printerName).isEmpty()) {
				printJson.put("connect", "打印機未鏈接,或電源未打開");
				return printJson;
			} else {
				printJson.put("connect", "打印數據已發送至打印機");
			}

			// 顏色濃度值
			String darkness = SystemProperties.readString("gk888t_darkness", "20");
			
			// 從文件讀取圖像數據,並完成轉換
			ZPLVo zplVo = getImagePixel(imgPath);

			// 組裝ZPL打印指令,指令詳情請參考ZPL的相關手冊
			String zplCode = "~DGR:SAMPLE.GRF," + 
					zplVo.getData().length + "," + // 圖形中的總字節數
					zplVo.getWidth() + ","			// 每行的字節數
					+ bytesToHexString(zplVo.getData())	// 該數據字符串用於定義圖像,也表示圖像的 ASCII 十六進制。每一個字符表示橫向的 8 個點。
					+ "~SD" + darkness + "^XA" + "^FO50,20^XGR:SAMPLE.GRF,2,2^FS"	// FO後面的爲起始座標,^SF前的兩個參數分別爲橫向、縱向擴展比例
					+ "^XZ";// 指令結束

			// 調用打印機,發送ZPL指令
			Doc doc = new SimpleDoc(zplCode.getBytes(), DocFlavor.BYTE_ARRAY.AUTOSENSE, null);
			service.createPrintJob().print(doc, null);

		} catch (Exception e) {
			logger.error("打印異常", e);
			printJson.put("error", e.getMessage());
		}
		return printJson;
	}
	
	/**
	 * 根據座標獲取圖像的顏色值
	 * @param bi
	 * @param x
	 * @param y
	 * @return
	 */
	public int getRgb(BufferedImage bi, int x, int y) {
		try {
			return bi.getRGB(x + 0, y) & 0xffffff;
		} catch (Exception e) {
			return 1;
		}
	}

	/**
	 * 讀取一張圖片的RGB值
	 * 
	 * @throws Exception
	 */
	public ZPLVo getImagePixel(String image) throws Exception {
		try {
			ZPLVo zplVo = new ZPLVo();
			// 讀取圖像
			BufferedImage bi = ImageIO.read(new File(image));
			
			// 設置寬度,不能整除時向上取整
			zplVo.setWidth((int)Math.ceil(bi.getWidth() / 8.0));
			zplVo.setData(new byte[zplVo.getWidth() * bi.getHeight()]);

			int zplIndex = 0;
			
			// 循環讀取圖像像素
			for (int j = 0; j < bi.getHeight(); j++) {
				for (int i = 0; i < bi.getWidth(); i += 8) {
				
					// 當前像素值
					int rgb0 = getRgb(bi, i + 0, j);
					int rgb1 = getRgb(bi, i + 1, j);
					int rgb2 = getRgb(bi, i + 2, j);
					int rgb3 = getRgb(bi, i + 3, j);
					int rgb4 = getRgb(bi, i + 4, j);
					int rgb5 = getRgb(bi, i + 5, j);
					int rgb6 = getRgb(bi, i + 6, j);
					int rgb7 = getRgb(bi, i + 7, j);
					
					byte value = 0;
					
					// 實際每一個像素點在ZPL的圖像數據中只佔1位
					value |= (rgb0 == 0 ? 0x00 : 0x80);
					value |= (rgb1 == 0 ? 0x00 : 0x40);
					value |= (rgb2 == 0 ? 0x00 : 0x20);
					value |= (rgb3 == 0 ? 0x00 : 0x10);
					value |= (rgb4 == 0 ? 0x00 : 0x08);
					value |= (rgb5 == 0 ? 0x00 : 0x04);
					value |= (rgb6 == 0 ? 0x00 : 0x02);
					value |= (rgb7 == 0 ? 0x00 : 0x01);
					
					// ZPL顯示的圖像顏色須要取反
					value = (byte) ~value;
					
					// 保存
					zplVo.getData()[zplIndex++] = value;
				}
			}
			
			return zplVo;
			
		} catch (Exception e) {
			logger.error("", e);
			return null;
		}
	}

	/**
	 * 把字節數組轉換成16進制字符串
	 * 
	 * @param bArray
	 * @return
	 */
	public static final String bytesToHexString(byte[] bArray) {
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;
		for (int i = 0; i < bArray.length; i++) {
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2)
				sb.append(0);
			sb.append(sTemp.toUpperCase());
		}
		return sb.toString();
	}
}
相關文章
相關標籤/搜索