PDFBox:从 ​​pdf 中提取图像到输入流

PDFBox: extracting images from pdf to inputstream

我正在使用 PDFBox 从我的 pdf(仅包含 jpg)中提取图像。

因为我会将这些图像保存在我的数据库中,所以我想先将每个图像直接转换为输入流对象,而不是将文件临时放置在我的文件系统中。但是,我在这方面遇到了困难。我认为它必须这样做,因为我在以下示例中使用了 image.getPDFStream().createInputStream()

while (imageIter.hasNext()) {
    String key = (String) imageIter.next();
    PDXObjectImage image = (PDXObjectImage) images.get(key);

    FileOutputStream output = new FileOutputStream(new File(
            "C:\Users\Anton\Documents\lol\test.jpg"));
    InputStream is = image.getPDStream().createInputStream(); //this gives me a corrupt file
    byte[] buffer = new byte[1024];
    while (is.read(buffer) > 0) {
        output.write(buffer);
    }
}

然而这有效:

while (iter.hasNext()) {
    PDPage page = (PDPage) iter.next();
    PDResources resources = page.getResources();
    Map<String, PDXObject> images = resources.getXObjects();
        if (images != null) {
            Iterator<?> imageIter = images.keySet().iterator();
            while (imageIter.hasNext()) {
            String key = (String) imageIter.next();
            PDXObjectImage image = (PDXObjectImage) images.get(key);
            image.write2file(new File("C:\Users\Anton\Documents\lol\test.jpg")); //this works however
        }
    }
}

知道如何将每个 PDXObjectImage(或我可以获得的任何其他对象)转换为输入流吗?

在 PDFBox 1.8 中,最简单的方法是使用 write2OutputStream(),因此您的第一个代码块现在如下所示:

while (imageIter.hasNext()) {
    String key = (String) imageIter.next();
    PDXObjectImage image = (PDXObjectImage) images.get(key);

    FileOutputStream output = new FileOutputStream(new File(
            "C:\Users\Anton\Documents\lol\test.jpg"));
    image.write2OutputStream(output);
}

高级解决方案,只要您确定只有 JPEG 可以正确显示,即没有异常的色彩空间:

while (imageIter.hasNext()) {
    String key = (String) imageIter.next();
    PDXObjectImage image = (PDXObjectImage) images.get(key);

    FileOutputStream output = new FileOutputStream(new File(
            "C:\Users\Anton\Documents\lol\test.jpg"));
    InputStream is = image.getPDStream().getPartiallyFilteredStream(DCT_FILTERS);
    byte[] buffer = new byte[1024];
    while (is.read(buffer) > 0) {
        output.write(buffer);
    }
}

第二种解决方案删除除 DCT (= JPEG) 滤镜之外的所有滤镜。一些较旧的 PDF 有多个过滤器,例如ascii85 和 DCT。

现在即使您使用 JPEG 创建图像,您也不知道您的 PDF 创建软件做了什么。找出图像类型的一种方法是检查 class 它是什么(使用 instanceof):

- PDPixelMap => PNG
- PDJpeg => JPEG
- PDCcitt => TIF

另一种方法是使用 image.getSuffix()。

PDXObjectImage 有方法 write2OutputStream(OutputStream out),您可以从中从输出流中获取任一字节数组。

检查 How to convert OutputStream to InputStream? 以将 OutputStream 转换为 InputStream。

如果您使用的是 PDFBox 2.0.0 或更高版本

PDDocument document = PDDocument.load(new File("filePath")); //filePath is the path to your .pdf
PDFRenderer pdfRenderer = new PDFRenderer(document);

for(int i=0; i<document.getPages().getCount(); i++){
    BufferedImage bim = pdfRenderer.renderImage(i, 1.0f, ImageType.RGB); //Get bufferedImage for page "i" with scale 1
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    ImageIO.write(bim, "jpg", os);
    InputStream is = new ByteArrayInputStream(os.toByteArray());
    //Do whatever you need with the inputstream
}
document.close()