使用Itext将Pdf页面转换为Byte数组

时间:2016-06-17 15:08:03

标签: java pdf itext bytearray pdf-conversion

我的问题

我正在寻找一种方法将单个pdf页面转换为byte [](如每个pdf页面的一个字节[]),这样我就可以将它们转换为BufferedImage []。< / em>

这样,所有转换都在内存中完成,而不是制作临时文件,使其更快,更简洁。我也可以稍后使用字节数组进行服务调用。如果我可以将库使用仅限于itext,那将是很好的,但是,如果没有任何其他方式,我可以对其他库开放。

我现在拥有什么

这是我目前的代码

INSERT

这是我到目前为止检查过的(非代表性)链接列表。

source code

Useful, but not quite what I want

1 个答案:

答案 0 :(得分:3)

我做了一些挖掘并找到了解决方案!希望其他人在需要时找到它,并尽可能地帮助它。干杯!

扩展RenderListener类

我环顾四周,发现this.查看代码和类,我发现PdfImageObjects有一个getBufferedImage(),这正是我想要的。现在没有必要转换为byte[],这是我原本以为我将要做的事情。使用给定的示例代码,我想出了这个类:

public class MyImageRenderListener implements RenderListener {

protected String path = "";
protected ArrayList<BufferedImage> bimg = new ArrayList<>();

/**
 * Creates a RenderListener that will look for images.
 */
public MyImageRenderListener(String path) {
    this.path = path;
}

public ArrayList<BufferedImage> getBimgArray() {
    return bimg;
}

/**
 * @see com.itextpdf.text.pdf.parser.RenderListener#renderImage(
 * com.itextpdf.text.pdf.parser.ImageRenderInfo)
 */
public void renderImage(ImageRenderInfo renderInfo) {
    try {

        PdfImageObject image = renderInfo.getImage();

        if (image == null) {
            return;
        }
        bimg.add(image.getBufferedImage());

    } catch (IOException e) {
        System.out.println(e.getMessage());
    }
}

与上述链接相比,此处需要注意的重要更改是添加了新字段ArrayList<BufferedImage> bimg,该字段的getter以及renderImage()函数的重组。

我还改变了项目其他类中的一些方法:

将PDF发布到BufferedImage []

的代码
// Credit to Mihai. Code found here: http://stackoverflow.com/questions/6851385/save-tiff-ccittfaxdecode-from-pdf-page-using-itext-and-java
public static ArrayList<BufferedImage> getBufImgArr(final String BasePath) throws IOException {

    PdfReader reader = new PdfReader(BasePath);
    PdfReaderContentParser parser = new PdfReaderContentParser(reader);
    MyImageRenderListener listener = new MyImageRenderListener(BasePath + "extract/image%s.%s");

    for (int page = 1; page <= reader.getNumberOfPages(); page++) {
        parser.processContent(page, listener);
    }

    reader.close();
    return listener.getBimgArray();

}

将BufferedImage []转换为Multi-Page Tiff

的代码
public static void convert(String fin) throws FileNotFoundException, IOException {

    ArrayList<BufferedImage> bimgArrL = getBufImgArr(fin);
    BufferedImage[] bim = new BufferedImage[bimgArrL.size()];
    bimgArrL.toArray(bim);

    try (RandomAccessOutputStream rout = new FileCacheRandomAccessOutputStream(
        new FileOutputStream("/path/you/want/result/to/go.tiff"))) {

        // The options for the tiff file are set here. 
        // **THIS BLOCK USES THE ICAFE LIBRARY TO CONVERT TO MULTIPAGE-TIFF**
        // ICAFE: https://github.com/dragon66/icafe
        ImageParam.ImageParamBuilder builder = ImageParam.getBuilder();
        TIFFOptions tiffOptions = new TIFFOptions();
        tiffOptions.setApplyPredictor(true);
        tiffOptions.setTiffCompression(Compression.CCITTFAX4);
        tiffOptions.setDeflateCompressionLevel(0);
        builder.imageOptions(tiffOptions);
        TIFFTweaker.writeMultipageTIFF(rout, bim);
        // I found this block of code here: https://github.com/dragon66/icafe/wiki
        // About 3/4 of the way down the page

    }
}

开始整个过程​​:

public static void main(String[] args){
    convert("/path/to/pdf/image.pdf");
}

重要提示:

您可能会注意到我的代码中从不显式调用listener.renderImage()。似乎renderImage()是一个辅助函数,当侦听器对象传递给解析器对象时,该函数在其他地方被调用。这种情况发生在getBufImgArr(param)方法中。

正如下面评论中的@mkl所述,代码正在提取pdf页面中的所有图像,因为pdf页面本身并不是图像。如果您在使用OCR扫描的pdf上运行此代码,或者具有多个层的pdf,则可能会出现问题。在这种情况下,当您(可能)希望它们在一个页面上保持在一起时,您可以将单个pdf页面中的多个图像转换为多个tiff图像。

我找到了很好的资料来源:

Programcreek search for PdfReaderContentParser