由于公司一个地方需要用到图片转换ZPL格式去打印;这里的ZPL格式是打印斑马打印机,这里面有一些小的地方是需要注意的.
由于斑马打印机的型号不一样,设置不一样,外加自身的图片格式(.jpg,.png的不一样),图片的高度和宽度也不一样,就会直接导致打印出来的东西和你理想中的效果不一样,所以这里就需要设置图片的参数和斑马打印机自身的参数等设置。
然后下面贴出来图片转换为ZPL格式的代码,也可以当一个工具类来进行使用。
public class ZPLConveterUtils {
private int blackLimit = 380;
private int total;
private int widthBytes;
private boolean compressHex = false;
private static Map<Integer, String> mapCode = new HashMap<Integer, String>();
mapCode.put(1, "G");
mapCode.put(2, "H");
mapCode.put(3, "I");
mapCode.put(4, "J");
mapCode.put(5, "K");
mapCode.put(6, "L");
mapCode.put(7, "M");
mapCode.put(8, "N");
mapCode.put(9, "O");
mapCode.put(10, "P");
mapCode.put(11, "Q");
mapCode.put(12, "R");
mapCode.put(13, "S");
mapCode.put(14, "T");
mapCode.put(15, "U");
mapCode.put(16, "V");
mapCode.put(17, "W");
mapCode.put(18, "X");
mapCode.put(19, "Y");
mapCode.put(20, "g");
mapCode.put(40, "h");
mapCode.put(60, "i");
mapCode.put(80, "j");
mapCode.put(100, "k");
mapCode.put(120, "l");
mapCode.put(140, "m");
mapCode.put(160, "n");
mapCode.put(180, "o");
mapCode.put(200, "p");
mapCode.put(220, "q");
mapCode.put(240, "r");
mapCode.put(260, "s");
mapCode.put(280, "t");
mapCode.put(300, "u");
mapCode.put(320, "v");
mapCode.put(340, "w");
mapCode.put(360, "x");
mapCode.put(380, "y");
mapCode.put(400, "z");
public void setCompressHex(boolean compressHex) {
this.compressHex = compressHex;
public void setBlacknessLimitPercentage(int percentage) {
this.blackLimit = (percentage * 768 / 100);
private String headDoc() {
String str = "^XA " + "^FO0,0^GFA," + total + "," + total + "," + widthBytes + ", ";
return str;
private String footDoc() {
String str = "^FS" + "^XZ";
return str;
* Image to zpi string data.
* @param image
* @return
* @throws IOException
public String convertfromImg(BufferedImage image) throws IOException {
String cuerpo = createBody(image);
if (compressHex) {
cuerpo = encodeHexAscii(cuerpo,20);
return headDoc() + cuerpo + footDoc();
/* public static void main(String[] args) throws Exception {
resizeImage("image/gavin2019GY-HCK-21099224.jpg","image/cc.png",810,1220);
File file = new File("image/cc.png");
BufferedImage orginalImage = ImageIO.read(file);
ZPLConveterUtils zpl = new ZPLConveterUtils();
zpl.setCompressHex(true);
zpl.setBlacknessLimitPercentage(50);
String content = zpl.convertfromImg(orginalImage);
JSONObject jsonObject = new JSONObject();
jsonObject.put("str", content);
System.out.println(jsonObject);
public static void resizeImage(String srcImgPath, String distImgPath,
int width, int height) throws IOException {
File srcFile = new File(srcImgPath);
Image srcImg = ImageIO.read(srcFile);
BufferedImage buffImg = null;
buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
buffImg.getGraphics().drawImage(
srcImg.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0,
0, null);
ImageIO.write(buffImg, "JPG", new File(distImgPath));
* the BufferedImage to String
* @param orginalImage
* @return
* @throws IOException
private String createBody(BufferedImage orginalImage) throws IOException {
StringBuffer sb = new StringBuffer();
Graphics2D graphics = orginalImage.createGraphics();
graphics.drawImage(orginalImage, 0, 0, null);
int height = orginalImage.getHeight();
int width = orginalImage.getWidth();
// int newWidth = width + 200;
int rgb, red, green, blue, index = 0;
char auxBinaryChar[] = {'0', '0', '0', '0', '0', '0', '0', '0'};
// widthBytes = width / 16 ;
// widthBytes = width % 8 > 0 ? (((int) (width / 8)) + 1) : width / 8;
widthBytes = width % 8 > 0 ? (((int) (width / 8)) + 1) : width / 8;
this.total = widthBytes * height;
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
rgb = orginalImage.getRGB(w, h);
red = (rgb >> 16) & 0x000000FF;
green = (rgb >> 8) & 0x000000FF;
blue = (rgb) & 0x000000FF;
char auxChar = '1';
int totalColor = red + green + blue;
if (totalColor > blackLimit) {
auxChar = '0';
auxBinaryChar[index] = auxChar;
index++;
if (index == 8 || w == (width - 1)) {
sb.append(fourByteBinary(new String(auxBinaryChar)));
auxBinaryChar = new char[]{'0', '0', '0', '0', '0', '0', '0', '0'};
index = 0;
sb.append("\n");
return sb.toString();
* @param binaryStr
* @return
private String fourByteBinary(String binaryStr) {
// int decimal = Integer.parseInt(binaryStr, 2);
int decimal = Integer.parseInt(binaryStr, 2);
return decimal > 15 ? Integer.toString(decimal, 16).toUpperCase() : "0" + Integer.toString(decimal, 16).toUpperCase();
* @param code
* @return
private String encodeHexAscii(String code) {
int maxlinea = widthBytes * 2;
StringBuffer sbCode = new StringBuffer();
StringBuffer sbLinea = new StringBuffer();
String previousLine = null;
int counter = 1;
char aux = code.charAt(0);
boolean firstChar = false;
for (int i = 1; i < code.length(); i++) {
if (firstChar) {
aux = code.charAt(i);
firstChar = false;
continue;
if (code.charAt(i) == '\n') {
if (counter >= maxlinea && aux == '0') {
sbLinea.append(",");
} else if (counter >= maxlinea && aux == 'F') {
sbLinea.append("!");
} else if (counter > 20) {
int multi20 = (counter / 20) * 20;
int resto20 = (counter % 20);
sbLinea.append(mapCode.get(multi20));
if (resto20 != 0) {
sbLinea.append(mapCode.get(resto20) + aux);
} else {
sbLinea.append(aux);
} else {
sbLinea.append(mapCode.get(counter) + aux);
if (mapCode.get(counter) == null) {
counter = 1;
firstChar = true;
if (sbLinea.toString().equals(previousLine)) {
sbCode.append(":");
} else {
sbCode.append(sbLinea.toString());
previousLine = sbLinea.toString();
sbLinea.setLength(0);
continue;
if (aux == code.charAt(i)) {
counter++;
} else {
if (counter > 20) {
int multi20 = (counter / 20) * 20;
int resto20 = (counter % 20);
sbLinea.append(mapCode.get(multi20));
if (resto20 != 0) {
sbLinea.append(mapCode.get(resto20) + aux);
} else {
sbLinea.append(aux);
} else {
sbLinea.append(mapCode.get(counter) + aux);
counter = 1;
aux = code.charAt(i);
return sbCode.toString();
private String encodeHexAscii(String code,int number) {
int maxlinea = widthBytes * 2;
StringBuffer sbCode = new StringBuffer();
StringBuffer sbLinea = new StringBuffer();
String previousLine = null;
int counter = 1;
char aux = code.charAt(0);
boolean firstChar = false;
for (int i = 1; i < code.length(); i++) {
if (firstChar) {
aux = code.charAt(i);
firstChar = false;
continue;
if (code.charAt(i) == '\n') {
if (counter >= maxlinea && aux == '0') {
sbLinea.append(",");
} else if (counter >= maxlinea && aux == 'F') {
sbLinea.append("!");
} else if (counter > number) {
int multi20 = (counter / number) * number;
int resto20 = (counter % number);
sbLinea.append(mapCode.get(multi20));
if (resto20 != 0) {
sbLinea.append(mapCode.get(resto20) + aux);
} else {
sbLinea.append(aux);
} else {
sbLinea.append(mapCode.get(counter) + aux);
if (mapCode.get(counter) == null) {
counter = 1;
firstChar = true;
if (sbLinea.toString().equals(previousLine)) {
sbCode.append(":");
} else {
sbCode.append(sbLinea.toString());
previousLine = sbLinea.toString();
sbLinea.setLength(0);
continue;
if (aux == code.charAt(i)) {
counter++;
} else {
if (counter > number) {
int multi20 = (counter / number) * number;
int resto20 = (counter % number);
sbLinea.append(mapCode.get(multi20));
if (resto20 != 0) {
sbLinea.append(mapCode.get(resto20) + aux);
} else {
sbLinea.append(aux);
} else {
sbLinea.append(mapCode.get(counter) + aux);
counter = 1;
aux = code.charAt(i);
return sbCode.toString();
注意这里再重复下打印出来的效果不一样;导致的原因有可能:
1 : 斑马打印机型号问题
2 : 斑马打印机的参数设置问题
3 : 图片自身的类型和图片的高度宽度等参数信息的设置
由于公司一个地方需要用到图片转换ZPL格式去打印;这里的ZPL格式是打印斑马打印机,这里面有一些小的地方是需要注意的.由于斑马打印机的型号不一样,设置不一样,外加自身的图片格式(.jpg,.png的不一样),图片的高度和宽度也不一样,就会直接导致打印出来的东西和你理想中的效果不一样,所以这里就需要设置图片的参数和斑马打印机自身的参数等设置。然后下面贴出来图片转换为ZPL格式的代码,也可以当...
实现思路: 1、获取图片的二值化字节数组 这一步是关键 2、将字节数组转为十六进制 3、压缩十六进制字符串 结尾为1、0或者与上一行相同的;相同的连续字符压缩 4、拼凑ZPL编码,宽度需要扩大,因为需要时8个点(1字节)的整数倍
条码名称如下:
"CODE 39" "PDF417" "Interleaved 2 of 5" " MaxiCode" "EAN 8""Code11"
"UPC-E" "Micro PDF417" "Code93" "Code49" "Code 128" "CoderBar" "EAN 13"
"Industrial 2 of 5"
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;