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

时间:2015-06-07 11:39:21

标签: java inputstream pdfbox

我正在使用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(或我能得到的任何其他对象)转换为输入流吗?

3 个答案:

答案 0 :(得分:3)

在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创建软件的功能。找出它是什么类型的图像的一种方法是检查它是什么类(使用instanceof):

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

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:0)

如果您使用的是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()