有人可能问,族长今天为什么要写有关“PDF生成图片”呢?
我之所以写这篇文章,是因为最近的项目中有实际场景需要用到,因此将实现的过程分享大家,可能在你的以后的项目中也会用到,所谓前人种树后人乘凉嘛,希望我种的每棵“树”能为大家提供便利;
言归正传,由于我们之前提供给用户下载的电子发票都是pdf格式,可是很多人在手机上下载电子发票后发现不能打开pdf格式的电子发票,这就给用户带来了很多不便,于是乎,我们就着手将pdf格式的发票转成图片格式便于查看;下面我们就一起去看看怎样去实现该功能;
pdf转图片的类库有好几种,我今天就只说两种我实际用过的pdfbox和pdfrenderer,两种类库各有优势:
pdfbox->转换效率较低,图片DPI值容易控制,图片高清,pdf页数过多或者DPI设置过大容易内存溢出,但是内含字体较为全面,如果考虑到要求转换高清、文件小、内含特殊字体可选用该类库;
pdfrenderer->这个应该是我知道的所有转换效率最高的一个,可是包含字体较少,有些pdf是无法转换的,比如国内的那种发票就转不成图片,经过我实际测试大部分转换时没问题;
看了上面两个类库的优缺点如果是你想做发票转换你会选哪个呢?
相信聪明的你已经想到了我选用的是pdfbox,因为我们的一个订单最多不会超过5张发票,还需要高清展示,加上pdfrenderer貌似对中国那种电子发票内的字体识别的不是很好,生成出来就有一个税务部门的一个红印章,因此选择pdfbox是最好不过的;
操作四部曲:
第一步:下载并引入的相关jar包,需要用到jar文件分别是pdfbox-2.0.4.jar、fontbox-2.0.4.jar和commons-logging-1.2.jar;
第二部:将pdf转成的所有图片加载到内存中,如下:
public static List<BufferedImage> convertToImage(byte[] file) throws IOException {
PDDocument document = PDDocument.load(file);
PDFRenderer pdfRenderer = new PDFRenderer(document);
//存储pdf中每一页BufferedImage
List<BufferedImage> bufferedImageList = new ArrayList<>();
//遍历PDF文件中的所有页,每一个都会生成一个单独的图片
for (int page = 0;page<document.getNumberOfPages();page++){
BufferedImage img = pdfRenderer.renderImageWithDPI(page, 100, ImageType.RGB);//注意此处的参数100可以调整,值越大图片越清晰
bufferedImageList.add(img);
}
document.close();
return bufferedImageList;
}
第三部:下来我们就需要将所有内存中的图片拼接成一张图片,拼接方法如下:
public static BufferedImage concat(List<BufferedImage> images) throws IOException {
int heightTotal = 0;
for(int j = 0; j < images.size(); j++) {
heightTotal += images.get(j).getHeight();
}
int heightCurr = 0;
BufferedImage concatImage = new BufferedImage(images.get(0).getWidth(), heightTotal, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = concatImage.createGraphics();
for(int j = 0; j < images.size(); j++) {
g2d.drawImage(images.get(j), 0, heightCurr, null);
heightCurr += images.get(j).getHeight();
}
g2d.dispose();
return concatImage;
}
第四部:将内存中拼接好的图片生成实际图片
public static void generalImage(BufferedImage image,String path) throws ImageFormatException, IOException {
FileOutputStream out = new FileOutputStream(path);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(image);
out.close();
}
有了以上四部我们就可以进行测试了,将test.pdf转成test.jpg(因为手头没有多页发票pdf且随便找一个多页pdf进行测试)
List<BufferedImage> list = FileManagerSystem.convertToImage(IoCommonUtil.readInputStream(new FileInputStream(new File("F:/迅雷下载/test.pdf"))));
FileManagerSystem.generalImage(FileManagerSystem.concat(list), "F:/迅雷下载/test.jpg");