Java | PDF和Image格式的面单转ZPL格式 - 工具类
PDF的Maven依赖
<!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.27</version>
</dependency>
转换工具类ZPLConveterUtil
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class ZPLConveterUtil {
private static int blackLimit = 380;
private static int total;
private static int widthBytes;
/**
* 是否压缩 true=压缩 false=不压缩
**/
private static boolean isCompressHex = true;
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");
}
/**
* the BufferedImage to String
*
* @param orginalImage
* @return
* @throws IOException
*/
private static 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 rgb, red, green, blue, index=0;
char auxBinaryChar[] = {'0', '0', '0', '0', '0', '0', '0', '0'};
widthBytes = width/8;
if(width%8>0){
widthBytes= (((int)(width/8))+1);
} else {
widthBytes= width/8;
}
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();
}
private static String fourByteBinary(String binaryStr){
int decimal = Integer.parseInt(binaryStr,2);
if (decimal>15){
return Integer.toString(decimal,16).toUpperCase();
} else {
return "0" + Integer.toString(decimal,16).toUpperCase();
}
}
/**
* Image to zpl string data.
*
* @param image
* @return
* @throws IOException
*/
public String convertFromImg(BufferedImage image) throws IOException {
String cuerpo = createBody(image);
if (isCompressHex) {
cuerpo = encodeHexAscii(cuerpo, 20);
}
return headDoc() + cuerpo + footDoc();
}
private static 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();
}
private static String headDoc(){
String str = "^XA " +
"^FO0,0^GFA,"+ total + ","+ total + "," + widthBytes +", ";
return str;
}
private static String footDoc(){
String str = "^FS"+
"^XZ";
return str;
}
public void setCompressHex(boolean compressHex) {
this.isCompressHex = compressHex;
}
public void setBlacknessLimitPercentage(int percentage){
blackLimit = (percentage * 768 / 100);
}
/**
* PDF转ZPL格式
* @param pdf pdf文件字节数组
* @return 返回ZPL格式
* @throws IOException
*/
public static String convertPdfToZpl(byte[] pdf) throws IOException {
PDDocument doc = PDDocument.load(pdf);
PDFRenderer renderer = new PDFRenderer(doc);
BufferedImage orginalImage = renderer.renderImageWithDPI(0, 200);
return ZPLConveterUtil.convertImgToZpl(orginalImage);
}
/**
* PDF转ZPL格式(压缩会返回用null表示英文字母的字符串)
* @param pdfPath pdf文件路径
* @return 返回ZPL格式
* @throws IOException
*/
public static String convertPdfToZpl(String pdfPath) throws IOException {
PDDocument doc = PDDocument.load(new File(pdfPath));
PDFRenderer renderer = new PDFRenderer(doc);
BufferedImage orginalImage = renderer.renderImageWithDPI(0, 200);
return ZPLConveterUtil.convertImgToZpl(orginalImage);
}
/**
* PDF转ZPL格式(压缩不会返回用null表示的字符串,压缩的更彻底一点)
* @param pdfPath pdf文件路径
* @return 返回ZPL格式
*/
public static String convertPDFToZPL(String pdfPath) {
File sourceFile = new File(pdfPath);
PDDocument document = null;
try {
if (sourceFile.exists()) {
document = PDDocument.load(sourceFile);
PDFRenderer pdfRenderer = new PDFRenderer(document);
int dpi = 203;// use less dpi for to save more space in harddisk. For professional usage you
BufferedImage bImage = pdfRenderer.renderImageWithDPI(0, dpi, ImageType.RGB);
ZPLConveterUtil zplConveterUtil = new ZPLConveterUtil();
String zplStr = zplConveterUtil.convertFromImg(bImage);
zplStr = zplStr.replace("\n", "");
return zplStr;
} else {
log.error("generate pdf failed");
}
} catch (Exception e) {
log.error("error is {}", e);
} finally {
try {
if (document != null) {
document.close();
}
} catch (IOException e) {
log.error("close stram failed,the exception is {}", e);
}
}
return "";
}
/**
* PDF转ZPL格式
* @param imagePath 图片文件路径
* @return 返回ZPL格式
* @throws IOException
*/
public static String convertImgToZpl(String imagePath) throws IOException {
BufferedImage orginalImage = ImageIO.read(new File(imagePath));
return ZPLConveterUtil.convertImgToZpl(orginalImage);
}
public static String convertImgToZpl(BufferedImage image) throws IOException {
String cuerpo = createBody(image);
if(isCompressHex)
cuerpo = encodeHexAscii(cuerpo);
return headDoc() + cuerpo + footDoc();
}
public static void main(String[] args) throws Exception {
String pdf = ZPLConveterUtil.convertPdfToZpl("D:\\label.pdf");
System.out.println(pdf);
String pdf2 = ZPLConveterUtil.convertPDFToZPL("D:\\label.pdf");
System.out.println(pdf2);
}
}
欢迎关注公众号:慌途L
后面会慢慢将文章迁移至公众号,也是方便在没有电脑的情况下可以进行翻阅,更新的话会两边同时更新,大家不用担心!