我使用iText 7 http://itextpdf.com/库:itext7-io-7.0.2.jar,itext7-kernel-7.0.2.jar,itext7-layout-7.0.2.jar,slf4j-api-1.7。 25.jar,slf4j-simple-1.7.25.jar在项目中 设置文档页面的背景图像,并在同一文档(pdf文件)中保存几个类似的页面。图像文件
final String IMAGE = "/resources/image.jpg";
必须作为资源存储在jar文件中。 ImageData对象是使用com.itextpdf.io.image.ImageDataFactory的方法create(java.awt.Image image,java.awt.Color color)创建的:
ImageData imgData = ImageDataFactory.create(new Main().loadImage(IMAGE), true);
java.awt.image.BufferedImage loadImage(String imageFilename)方法的代码是:
private BufferedImage loadImage(String imageFilename) {
BufferedImage img = null;
try {
img = javax.imageio.ImageIO.read(getClass().getResourceAsStream(imageFilename));
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
return img;
}
ImageData对象在循环中使用:
Document document = ... (get Document object)
PdfDocument pdf = document.getPdfDocument();
PageSize pageSize = pdf.getDefaultPageSize();
PdfPage page = pdf.addNewPage();
for (int i = 0; i < documents.size(); i++) {
PdfCanvas canvas = new PdfCanvas(page);
canvas.addImage(imgData, pageSize, false);
... (add document body)
if (i < documents.size() - 1) {
page = pdf.addNewPage();
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
}
}
document.close();
问题是,从jar文件运行程序后,我得到一个pdf文档,比我使用直接图像引用从IDE运行程序要大得多(81 MB,对于17页文档为9 MB) :
ImageData imgData = ImageDataFactory.create("src/resources/image.jpg");
如果使用com.itextpdf.io.image.ImageDataFactory的方法create(byte [] bytes,boolean recoverImage)从图像的字节创建ImageData对象:
ImageData imgData = ImageDataFactory.create(new Main().loadImageByte(IMAGE), true);
并使用byte [] loadImageByte(String imageFilename)方法:
private byte[] loadImageByte(String imageFilename) {
byte[] dataBytes = null;
try {
InputStream is = getClass().getResourceAsStream(imageFilename);
dataBytes = new byte[is.available()];
is.read(dataBytes);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
return dataBytes;
}
从IDE运行程序或从jar文件启动时,生成的pdf文档的大小都很小。 但是,在后一种情况下,文档无法打开,Adobe Acrobat 9会出现错误&#34;图像数据不足&#34; (两个文件的字节都不同)。
文件大小差异的原因是什么?是否有办法从jar文件开始通过程序获取小尺寸的pdf文档?
答案 0 :(得分:0)
通过使用PdfImageXObject
包装图像数据来解决问题:
public static final String IMAGE = "/resources/image.jpg";
public static final String DEST = "result.pdf";
public static void main(String[] args) throws FileNotFoundException {
int pageNumber = 5;
PdfWriter writer = new PdfWriter(DEST);
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf, PageSize.A4.rotate());
ImageData imgData = ImageDataFactory.create(new Main().loadImageByte(IMAGE), true);
/*Wrapping image data in a PdfImageXObject*/
PdfImageXObject imgObject = new PdfImageXObject(imgData);
/*Calculate the page area for the image - the image size will change*/
PageSize pageSize = pdf.getDefaultPageSize();
Rectangle rectangle = new Rectangle(pageSize.getWidth(), pageSize.getHeight());
/*Loop*/
PdfPage page = pdf.addNewPage();
for (int i = 0; i < pageNumber; i++) {
PdfCanvas canvas = new PdfCanvas(page);
/*Add background image as PdfImageXObject*/
canvas.addXObject(imgObject, rectangle);
(PDF building blocks adding)
if (i < pageNumber - 1) {
page = pdf.addNewPage();
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
}
}
document.close();
}
PDFXplorer中对生成的PDF文件的检查表明,当您使用Document
方法多次向add(Image image)
对象添加相同的前景图像时,图像将添加为引用单个PDF XObject。同时,使用PdfCanvas
方法将背景图像多次添加到addImage(ImageData image, Rectangle rect, boolean asInline)
对象会创建几个不同的PDF XObject实例。
注意这些方法的参数差异。对iText 7库源代码的分析表明Image
类每次创建PdfXObject
实例时都会创建一个Image
成员,但ImageData
类是与相应的PdfXObject
无关。