最近开发java程序调用斑马制卡机的功能,基本思路如下:1.利用java生成一个上岗证图片的正面和反面,2.java调用打印SDK打印彩色上岗证。
本次文章内容只涉及生成图片和打印两块功能,不涉及部署那一块。现在直接贴代码
1.java生成工作证正面和反面
1.1生成正面(包括头像照片和姓名等文字信息)
private static BufferedImage getFront(String path){
BufferedImage bimage = null;
try {
ImageIcon imgIcon = new ImageIcon(path);
Image theImg = imgIcon.getImage();
int width = theImg.getWidth(null) == -1 ? 1023 : theImg.getWidth(null);//3250
int height = theImg.getHeight(null) == -1 ? 639 : theImg.getHeight(null);//2040
bimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bimage.createGraphics();
//消除文字锯齿
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//消除画图锯齿
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//清除画线锯齿
g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_DEFAULT);
g.setColor(Color.white);//背景颜色
g.fillRect(0, 0, 1023, 639);//背景面积及位置,width=x.height=y
g.drawImage(theImg, 0, 0, null);
String fontName="微软雅黑";//微软雅黑
g.setColor(Color.black);
g.setFont(new Font(fontName, Font.PLAIN, 50));
g.drawString("某某建筑工地", 60, 90);
//上岗证
g.setColor(Color.black);
g.setFont(new Font(fontName, Font.PLAIN, 70));
g.drawString("上岗证", 750, 100); //上岗证
//画直线(上)
g.setStroke(new BasicStroke(4.0f));//线条粗细
g.setColor(Color.black);//线条颜色
g.drawLine(0, 120, 1023, 120);//线条起点及终点位置
//绘制头像
//将图片转换为BufferedImage对象
BufferedImage bImage = ImageIO.read(new File("D:\\头像.jpg"));
g.drawImage(bImage, 64, 179, 229, 275, null);
//姓名
g.setColor(Color.black);
g.setFont(new Font(fontName, Font.PLAIN, 45));
g.drawString("姓 名:", 355, 220);
//姓名变量
g.setColor(Color.black);
g.setFont(new Font(fontName, Font.PLAIN, 45));
g.drawString("XXX", 600, 220);
//等级
g.setColor(Color.black);
g.setFont(new Font(fontName, Font.PLAIN, 45));
g.drawString("等 级:", 355, 332);
//等级变量
g.setColor(Color.black);
g.setFont(new Font(fontName, Font.PLAIN, 45));
g.drawString("高 级", 620, 332);
//岗位
g.setColor(Color.black);
g.setFont(new Font(fontName, Font.PLAIN, 45));
g.drawString("岗 位:", 355, 446);
//岗位变量
g.setColor(Color.black);
g.setFont(new Font(fontName, Font.PLAIN, 45));
g.drawString("搬砖工", 570, 446);
//画直线(下)
g.setStroke(new BasicStroke(4.0f));//线条粗细
g.setColor(Color.black);//线条颜色
g.drawLine(0, 516, 1023, 516);//线条起点及终点位置
g.setColor(Color.black);
g.setFont(new Font(fontName, Font.PLAIN, 50));
g.drawString("部 门:水泥混泥土搬砖部", 60, 600);
g.dispose();//处理绘图
//以下是测试代码,将以上生成的图片绘制到电脑磁盘里,看看效果
ImageIO.write(bimage,"bmp",new File("D:\\front123.bmp"));
} catch (Exception e) {
e.printStackTrace();
}
return bimage;
}
说明:如果卡片正面是彩色的,可以先准备好一个彩色背景的图片,然后再在上面画头像、文字和直线
1.2生成反面
private static BufferedImage getBack(String path){
BufferedImage bimage = null;
try {
//首先需要对图片进行预处理,即修改成指定尺寸
ImageIcon imgIcon = new ImageIcon(path);
Image theImg = imgIcon.getImage();
int width = theImg.getWidth(null) == -1 ? 1023 : theImg.getWidth(null);//3250
int height = theImg.getHeight(null) == -1 ? 639 : theImg.getHeight(null);//2040
bimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bimage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//消除画图锯齿
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_DEFAULT);
g.setColor(Color.WHITE);//背景颜色
g.fillRect(0, 0, 1023, 639);//背景面积及位置,width=x.height=y
g.drawImage(theImg, 0, 0, null);
//画印章
BufferedImage bImage = ImageIO.read(new File("D:\\yz.jpg"));
//graphics.drawImage(bufferedImage.getScaledInstance(imageW, imageH, Image.SCALE_DEFAULT),100, 100, null);
g.drawImage(bImage, 450, 50, 420, 420, null);
//员工编号
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.PLAIN, 45));
g.drawString("员工编号:", 60, 93);
//编 号变量,字母编号位置计算方式跟汉字不一样
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.PLAIN, 45));
g.drawString("2020102301", 260, 95);
//兼职岗位
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.PLAIN, 45));
g.drawString("兼职岗位:", 60, 237);
//兼职岗位变量
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.PLAIN, 45));
g.drawString("运砖", 260, 237);
//发证单位
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.PLAIN, 45));
g.drawString("发证单位:", 60, 380);
//发证单位变量
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.PLAIN, 45));
g.drawString("某某建筑工地包工头抽烟办公室", 260, 380);
//有效期限
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.PLAIN, 45));
g.drawString("有效期限:", 60, 537);
//有效期限变量
g.setColor(Color.black);
g.setFont(new Font("微软雅黑", Font.PLAIN, 45));
g.drawString("2020年08月到2020年12月", 260, 539);
g.dispose();//处理绘图
//以下是测试代码,将以上生成的图片绘制到电脑磁盘里
ImageIO.write(bimage,"bmp",new File("D:\\back123.bmp"));
} catch (Exception e) {
e.printStackTrace();
}
return bimage;//返回生成好的图片
}
1.3主程序
import java.awt.*;
import java.io.UnsupportedEncodingException;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
public static void main(String[] args) throws IOException {
//正面头像front.jpg为彩色背景的图片,尺寸大小1023*639(宽*高)
BufferedImage bufferedImage1=getFront("resources/front.jpg");
//反面是白色的,所以不需要额外添加背景色的图片
BufferedImage bufferedImage2=getBack("D:\\");
}
2.调用打印服务
首先请参考斑马制卡机官网API文档熟悉用法,官网地址
https://techdocs.zebra.com/link-os/2-14/pc_card/
另外就是下载需要的SDK和demo支持
下面直接贴代码
import java.awt.Color;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import org.apache.commons.io.IOUtils;
import com.zebra.sdk.comm.*;
import com.zebra.sdk.common.card.containers.GraphicsInfo;
import com.zebra.sdk.common.card.containers.JobStatusInfo;
import com.zebra.sdk.common.card.enumerations.*;
import com.zebra.sdk.common.card.exceptions.ZebraCardException;
import com.zebra.sdk.common.card.graphics.*;
import com.zebra.sdk.common.card.graphics.enumerations.RotationType;
import com.zebra.sdk.common.card.printer.*;
import com.zebra.sdk.common.card.printer.discovery.ZebraCardPrinterFilter;
import com.zebra.sdk.device.ZebraIllegalArgumentException;
import com.zebra.sdk.printer.discovery.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class ZebraTest2 {
/**
* @param args
*/
public static void main(String[] args) {
Connection connection = null;
ZebraCardPrinter zebraCardPrinter = null;
DiscoveredPrinter[] printers = null;
ZebraGraphics graphics = null;
try {
printers = UsbDiscoverer.getZebraUsbPrinters(new ZebraCardPrinterFilter());
if (printers.length > 0) {
connection = printers[0].getConnection();
connection.open();
zebraCardPrinter = ZebraCardPrinterFactory.getInstance(connection);
}
if (zebraCardPrinter == null) {
return;
}
List<GraphicsInfo> graphicsData = new ArrayList<GraphicsInfo>();
//生成画笔
graphics = new ZebraCardGraphics(zebraCardPrinter);
//生成需要打印的图片集合
generatePrintJobImage(graphics, graphicsData);
//打印服务
int jobId = zebraCardPrinter.print(1, graphicsData);
pollJobStatus(zebraCardPrinter, jobId);
JobStatusInfo jStatus = zebraCardPrinter.getJobStatus(jobId);
System.out.println("Job complete: " + jStatus.printStatus);
} catch (ConnectionException e) {
System.out.println("Error discovering local printers: " + e.getMessage());
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
cleanUp(connection, zebraCardPrinter, graphics);
}
}
private static void generatePrintJobImage(ZebraGraphics graphics, List<GraphicsInfo> graphicsData) throws IOException {
BufferedImage img = null;
ByteArrayOutputStream baos = null;
GraphicsInfo grInfo = new GraphicsInfo();
try {
graphics.initialize(0, 0, OrientationType.Landscape, PrintType.Color, Color.WHITE);
// Front Color,打印正面
grInfo.side = CardSide.Front;
grInfo.printType = PrintType.Color;
grInfo.graphicType = GraphicType.BMP;
String filepath = "resources/front123.bmp"; // replace with path to your image
img = ImageIO.read(new File(filepath));
baos = new ByteArrayOutputStream();
ImageIO.write(img, "bmp", baos);
graphics.drawImage(baos.toByteArray(), 0, 0, 0, 0, RotationType.RotateNoneFlipNone);
grInfo.graphicData = graphics.createImage(null);
graphics.clear();
graphicsData.add(grInfo);
// Front Overlay
grInfo = new GraphicsInfo();
grInfo.side = CardSide.Front;
grInfo.printType = PrintType.Overlay;
grInfo.graphicType = GraphicType.NA;
grInfo.graphicData = null;
graphicsData.add(grInfo);
// Back MonoK,打印反面
graphics.initialize(0, 0, OrientationType.Landscape, PrintType.Color, Color.WHITE);
grInfo = new GraphicsInfo();
grInfo.side = CardSide.Back;
grInfo.printType = PrintType.Color;
grInfo.graphicType = GraphicType.BMP;
filepath = "resources/back123.bmp"; // replace with path to your image
img = ImageIO.read(new File(filepath));
baos = new ByteArrayOutputStream();
ImageIO.write(img, "bmp", baos);
graphics.drawImage(baos.toByteArray(), 0, 0, 0, 0, RotationType.RotateNoneFlipNone);
grInfo.graphicData = graphics.createImage(null);
graphics.clear();
graphicsData.add(grInfo);
} finally {
IOUtils.closeQuietly(baos);
}
}
static boolean pollJobStatus(ZebraCardPrinter device, int actionID) throws ConnectionException, ZebraCardException, ZebraIllegalArgumentException {
boolean success = false;
long dropDeadTime = System.currentTimeMillis() + 40000;
long pollInterval = 500;
// Poll job status
JobStatusInfo jStatus = null;
do {
jStatus = device.getJobStatus(actionID);
System.out.println(String.format("Job %d, Status:%s, Card Position:%s, " + "ReadyForNextJob:%s, Mag Status:%s, Contact Status:%s, Contactless Status:%s, " + "Error Code:%d, Alarm Code:%d", actionID, jStatus.printStatus, jStatus.cardPosition, jStatus.readyForNextJob,
jStatus.magneticEncoding, jStatus.contactSmartCard, jStatus.contactlessSmartCard, jStatus.errorInfo.value, jStatus.alarmInfo.value));
if (jStatus.contactSmartCard.contains("station")) {
success = true;
break;
} else if (jStatus.contactlessSmartCard.contains("station")) {
success = true;
break;
} else if (jStatus.printStatus.contains("done_ok")) {
success = true;
break;
} else if (jStatus.printStatus.contains("alarm_handling")) {
System.out.println("Error Dectected: " + jStatus.alarmInfo.description);
} else if (jStatus.printStatus.contains("error") || jStatus.printStatus.contains("cancelled")) {
success = false;
break;
}
if (System.currentTimeMillis() > dropDeadTime) {
success = false;
}
try {
Thread.sleep(pollInterval);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (true);
return success;
}
private static void cleanUp(Connection connection, ZebraCardPrinter genericPrinter, ZebraGraphics graphics) {
try {
if (genericPrinter != null) {
genericPrinter.destroy();
genericPrinter = null;
}
} catch (ZebraCardException e) {
e.printStackTrace();
}
if (graphics != null) {
graphics.close();
graphics = null;
}
if (connection != null) {
try {
connection.close();
connection = null;
} catch (ConnectionException e) {
e.printStackTrace();
}
}
}
}
说明:将之前生成好的图片,bmp格式的放到程序可以找到的位置,包括正面和反面。本实例采用的2-14版本的jdk
相关需要下载的资源
a.斑马SDK以及demo
https://download.csdn.net/download/qq_34309663/13023613
b.我自己写的demo
https://download.csdn.net/download/qq_34309663/13025187