当前位置: 首页 > news >正文

java调用斑马GK888t打印机(ZPL指令)

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

在项目中使用斑马打印机遇到了如下问题:

在实际打印信息前,需要修改打印机驱动设置,主要是设置打印颜色深度,默认值一般会打印的比较浅。通常情况下,在设置的颜色深度后,打印机能够很好的工作。但是如果我将程序注册为windows系统服务,以自启动的方式运行程序后,对于打印机驱动的设置将不会生效。而直接使用控制台启动程序,却是正常的。经过分析之后,怀疑可能是由于,系统服务的启动方式和直接控制台启动的方式是有区别的,两种方式程序的登录用户是不同的,系统服务的登录用户是SYSTEM(非administration)用户,控制台启动方式就是普通的USER用户。而打印机的驱动设置,貌似每个用户之间是相互独立的,所以修改了USER用户的设置,SYSTEM用户的设置仍然是默认值,所以打印机驱动就不会生效。

这个问题的一个解决方案,就是使用ZPL指令,直接控制打印机。ZPL是打印机专用的一种编程语言,具体可以参考《ZPL语言中文手册》。通过使用ZPL指令,可以打印问题,条码,图片,也可以修改各种打印参数,包括修改打印浓度参数。所以通过ZPL的方式可以忽略系统打印机的驱动设置,也就能够随意修改颜色深度设置了。

但是如何调用ZPL呢?

一种方式可以通过cmd命令行的方式向打印机发送ZPL指令文件,具体可参考连接:http://www.chongshang.com.cn/news/view.asp?id=334。

另一种是通过JAVA调用打印机,在发送ZPL指令。这里我参考了github上的代码,详见:https://github.com/w3blogfr/zebra-zpl。从这个代码中就知道如何通过JAVA向打印机发送ZPL指令了。

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();
	}
}

 

转载于:https://my.oschina.net/u/2450094/blog/800030

相关文章:

  • 允许chrome 浏览器运行 flash player
  • 注解的使用
  • hadoop各个组件功能
  • 命令行创建虚拟机,无桌面运行virtualbox
  • 一次arp防护配置错误导致的故障
  • 框架替换主页
  • HandlerSocket安装
  • phpstorm10.0安装xdebug插件
  • 网络编程(socket,套接字)
  • selinux
  • Bzoj2756 [SCOI2012]奇怪的游戏
  • 汇新云智慧城市解决方案——以区块链加速智慧城市建设
  • Spring MVC RequestParam
  • Docker容器管理
  • 组件之间数据交互
  • php的引用
  • [译]Python中的类属性与实例属性的区别
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • CEF与代理
  • docker容器内的网络抓包
  • Git学习与使用心得(1)—— 初始化
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • tensorflow学习笔记3——MNIST应用篇
  • Xmanager 远程桌面 CentOS 7
  • 程序员该如何有效的找工作?
  • 基于遗传算法的优化问题求解
  • 将回调地狱按在地上摩擦的Promise
  • 区块链共识机制优缺点对比都是什么
  • 手写一个CommonJS打包工具(一)
  • 算法-插入排序
  • 我是如何设计 Upload 上传组件的
  • 小而合理的前端理论:rscss和rsjs
  • 与 ConTeXt MkIV 官方文档的接驳
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 自制字幕遮挡器
  • kubernetes资源对象--ingress
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • ​io --- 处理流的核心工具​
  • ###C语言程序设计-----C语言学习(6)#
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #QT(智能家居界面-界面切换)
  • ${ }的特别功能
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (六)软件测试分工
  • (一)Neo4j下载安装以及初次使用
  • (转)Sublime Text3配置Lua运行环境
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .Net 4.0并行库实用性演练
  • .NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(二)...
  • .NET设计模式(2):单件模式(Singleton Pattern)
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • :O)修改linux硬件时间