无法从PDFA1(格式文档)中提取图像

时间:2015-01-06 13:50:35

标签: java pdf pdfbox

我使用以下代码从pdf中提取图像,这是PDFA1格式,但我无法获取图像。

List<PDPage> list = document.getDocumentCatalog().getAllPages();

String fileName = oldFile.getName().replace(".pdf", "_cover");
int totalImages = 1;
for (PDPage page : list) {

    PDResources pdResources = page.findResources();

    Map pageImages = pdResources.getImages();
    if (pageImages != null) {
        InputStream xmlInputStream = null;
        Iterator imageIter = pageImages.keySet().iterator();
        while (imageIter.hasNext()) {
            String key = (String) imageIter.next();
            PDXObjectImage pdxObjectImage = (PDXObjectImage) pageImages.get(key);

            System.out.println(convertStreamToString(xmlInputStream));
            System.out.println(pdxObjectImage.hashCode());
            System.out.println(pdxObjectImage.getColorSpace().getJavaColorSpace().isCS_sRGB());

            pdxObjectImage.write2file(destinationDir + fileName+ "_" + totalImages);
            totalImages++;

            break;
        }
    }
}

我能够使用上面的代码提取正常PDF的图像,但是无法为PDFA1-a格式pdf提取它。看来如下:

PDResources pdResources = page.findResources(); 

没有返回图像我甚至尝试过page.getResources()但仍然没有得到任何图像。我甚至尝试使用itext但仍然没有给我任何图像。

如果我尝试使用以下代码将PDF页面转换为图像

BufferedImage bufferedImage = page.convertToImage();
File outputfile = new File(destinationDir+"image1.JPEG");
ImageIO.write(bufferedImage, "JPEG", outputfile);

这些图像似乎没有与之相关的元数据所以我仍然无法知道它们的dpi或它们是彩色还是灰度。

目前我正在使用PDFBox执行此操作。我已经花了2天时间在谷歌上进行此搜索但仍然没有找到任何代码或文档来执行此操作。

如何在java中执行此操作?

是否可以在不提取图像的情况下获取DPI或pdf是彩色还是黑白???

1 个答案:

答案 0 :(得分:2)

您的问题是两个问题的组合:

1)“休息”。您的文件有两个图像。第一个是透明或灰色或任何和JPEG编码,但它不是你想要的。第二个是你想要的那个,但是在第一个图像之后中断就会中止。所以我只是改变了你的代码段:

while (imageIter.hasNext())
{
     String key = (String) imageIter.next();
     PDXObjectImage pdxObjectImage = (PDXObjectImage) pageImages.get(key);
     System.out.println(totalImages);
     pdxObjectImage.write2file("C:\\SOMEPATH\\" + fileName + "_" + totalImages);
     totalImages++;

     //break;
 }

2)你的第二张图片(有趣的一张)是JBIG2编码的。要对此进行解码,您需要在类路径中添加levigo插件,如上所述here。如果不这样做,除非您禁用日志记录,否则您将在1.8.8中收到此消息:

ERROR [main] org.apache.pdfbox.filter.JBIG2Filter:69 - Can't find an ImageIO plugin to decode the JBIG2 encoded datastream.

(您没有收到该错误消息,因为它是第二个JBIG2编码的消息)

三个奖励提示:

3)如果你自己创建了这个图像,例如在影印机上,了解如何在没有JBIG2压缩的情况下获取PDF图像,它是somewhat risky

4)不使用pdResources.getImages(),不推荐使用getImages调用。相反,使用getXObjects(),然后检查迭代时获得的类型。

 Iterator imageIter = pageImages.keySet().iterator();
 while (imageIter.hasNext())
 {
     String key = (String) imageIter.next();
     Object o = pageImages.get(key);
     if (o instanceof PDXObjectImage)
     {
         PDXObjectImage pdxObjectImage = (PDXObjectImage) o;

         // do stuff
     }
 }

5)使用foreach循环。

如果不是很明显:这与PDF / A无关: - )

6)我忘了你还问过如何查看它是否是黑白图像,这里是我在评论中提到的一些简单代码(未优化):

BufferedImage bim = pdxObjectImage.getRGBImage();

boolean bwImage = true;

int w = bim.getWidth();
int h = bim.getHeight();
for (int y = 0; y < h; y++)
{
    for (int x = 0; x < w; x++)
    {
        Color c = new Color(bim.getRGB(x, y));
        int red = c.getRed();
        int green = c.getGreen();
        int blue = c.getBlue();
        if (red == 0 && green == 0 && blue == 0)
        {
            continue;
        }
        if (red == 255 && green == 255 && blue == 255)
        {
            continue;
        }
        bwImage = false;
        break;
    }
    if (!bwImage)
        break;
}
System.out.println(bwImage);