无法从 PDFA1-a 格式文档中提取图像

Not able to extract images from PDFA1-a format document

我正在使用以下代码从 PDFA1-a 格式的 pdf 中提取图像,但我无法获取图像。

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() 但仍然没有得到任何图像 images.I 甚至尝试使用 itext 但它仍然没有给我任何图像。

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

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

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

目前我正在使用 PDFBox 来做 this.I 我已经花了 2 天时间在 google 上进行搜索,但我仍然没有找到任何代码或文档来做这件事。

如何在 java 中执行此操作??

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

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

1) "break;"。您的文件有两个图像。第一个是透明的或灰色的或其他任何东西,并且是 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 编码的。要对此进行解码,您需要在 class 路径中添加 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) 我忘了你还问过如何查看它是否是 b/w 图像,这里是我在评论中提到的一些简单代码(未优化):

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);