功能
使用Java将多张图片合并保存到同一页PDF中
依赖框架
pdfbox-2.0.19
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.19</version>
</dependency>
代码内容
package com.fangjing.fjdemo.pdf;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
/**
* @author:fangjing
* @date: Created in 14:21 2021-02-19.
* @desc: PDF转换相关
*/
public class PdfConverterUtil {
private PdfConverterUtil() {
// empty method
}
/**
* @desc 将多个图片放置到一个PDF页中
* @param imageStreamList 图片流列表
* @return 最终生成PDF流
* @throws IOException 执行失败的异常
*/
public static ByteArrayInputStream buildSinglePagePdfFromImage(List<BufferedImage> imageStreamList) throws IOException {
// 页高度取所有图片的高度之和+间隔,页宽度取所有图片中最宽的一个+固定间隔*2
// 间隔暂时取50
int interval = 50;
int pageHeight = interval;
int pageWidth = 0;
for (BufferedImage image : imageStreamList) {
pageHeight = image.getHeight() + pageHeight + interval;
pageWidth = Math.max(image.getWidth(), pageWidth);
}
pageWidth = pageWidth + interval * 2;
try (PDDocument pdDocument = new PDDocument()) {
// 生成单页
PDPage pdPage = new PDPage(new PDRectangle(pageWidth, pageHeight));
pdDocument.addPage(pdPage);
int currentHeight = pageHeight;
for (BufferedImage imageStream : imageStreamList) {
currentHeight = currentHeight - imageStream.getHeight() - interval;
try (PDPageContentStream contentStream = new PDPageContentStream(pdDocument, pdPage, PDPageContentStream.AppendMode.APPEND, false)) {
PDImageXObject pdImageObject = LosslessFactory.createFromImage(pdDocument, imageStream);
contentStream.drawImage(pdImageObject, getXCoordinate(pageWidth, imageStream.getWidth()), currentHeight, imageStream.getWidth(), imageStream.getHeight());
}
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
pdDocument.save(outputStream);
pdDocument.close();
return new ByteArrayInputStream(outputStream.toByteArray());
}
}
/**
* @desc 计算使图片居中的坐标
* @param pageWidth 页面宽度
* @param imageWidth 图片宽度
* @return 图片应该设置的页面坐标
*/
private static float getXCoordinate(int pageWidth, int imageWidth) {
return new BigDecimal(pageWidth - imageWidth)
.divide(new BigDecimal(2), RoundingMode.DOWN)
.floatValue();
}
}
单测
package com.fangjing.fjdemo.pdf;
import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
/**
* @author fangjing
* @date 8/3/2022-9:52 PM
* @desc Pdf转换相关单测
*/
public class PdfConverterUtilTest {
@Test
public void testBuildSinglePagePdfFromImage() throws IOException {
BufferedImage imageStream1 = ImageIO.read(new URL("https://image1.com/f?raw=1"));
BufferedImage imageStream2 = ImageIO.read(new URL("https:/image2/f?raw=1"));
ByteArrayInputStream pdfFromImage = PdfConverterUtil.buildSinglePagePdfFromImage(Arrays.asList(imageStream1, imageStream2));
File file = new File("test.pdf");
FileUtils.copyInputStreamToFile(pdfFromImage, file);
Assert.assertNotNull(pdfFromImage);
boolean delete = file.delete();
Assert.assertTrue(delete);
}
}