iText 7从jar文件中读取背景图像

时间:2017-07-02 13:44:23

标签: java image pdf jar itext7

我使用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文档?

1 个答案:

答案 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无关。

相关问题