如何检查 PDF 页面是否为 PDFBOX、XPDF 图像(扫描)

How can I check if PDF page is image(scanned) by PDFBOX, XPDF

PDFBox 提取图像时出现问题。 嗨,我如何检查 pdf 页面是否为图像并通过 PDFBOX 库提取它,有一种获取图像的方法,但如果 PDF 页面是图像,则无法获取。有人可以帮我解决这个问题吗?

关于提取图像的 Xpdf 问题。 我尝试通过另一个库 xpdf 提取图像,如果它是图像,它会在页面上进行奇怪的翻转。如果 pdf 包含一个小图像作为对象图像,它给我确定,如果页面被扫描,他我们正在翻转。

我想从 PDF 中提取所有图像,如果扫描页面以将它们作为图像获取,如果页面包含纯文本和图像也从该页面获取图像。

我的意思是从 PDF 中提取所有图像。不仅形成一个页面,而且即使页面是一个图像也可以将它们提取为图像但不要跳过它们我认为 PDFbox 是怎么做的。

XPDF 正在做一些事情,但是当他导出扫描的页面时,页面上的 FLIP(top,right) 出现问题

请问如何解决这个问题,谢谢。

Download File example for to test

    `PDDocument document = PDDocument.load(new File("/home/dru/IdeaProjects2/PDFExtractor/test/t1.pdf"));
    PDPageTree list = document.getPages();

    for (PDPage page : list) {
        PDResources pdResources = page.getResources();
        System.out.println(pdResources.getResourceCache());

        for (COSName c : pdResources.getXObjectNames()) {
            PDXObject o = pdResources.getXObject(c);

            if (o instanceof org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject) {
                File file = new File("/home/dru/IdeaProjects2/PDFExtractor/test/out/" + System.nanoTime() + ".png");
                ImageIO.write(((org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject)o).getImage(), "png", file);
            }
        }
    }`

正确提取图像

正如更新后的 PDF 所表明的那样,问题是它没有任何图像 直接在页面上 但它绘制了包含图像的 xobjects 形式。因此,图像搜索必须递归为 xobjects 形式。

这还不是全部:更新后的 PDF 中的所有页面都共享相同的资源字典,它们只是选择不同形式的 xobjects 来显示。因此,确实必须解析相应的页面内容流以确定给定页面上存在哪个 xobject(带有哪些图像)。

实际上,这是 PDFBox 工具 ExtractImages 所做的事情。不幸的是,它没有显示它在上面找到有问题的图像的页面,cf。 ExtractImages.java test method testExtractPageImagesTool10948New.

但我们可以简单地借鉴该工具使用的技术:

PDDocument document = PDDocument.load(resource);
int page = 1;
for (final PDPage pdPage : document.getPages())
{
    final int currentPage = page;
    PDFGraphicsStreamEngine pdfGraphicsStreamEngine = new PDFGraphicsStreamEngine(pdPage)
    {
        int index = 0;
        
        @Override
        public void drawImage(PDImage pdImage) throws IOException
        {
            if (pdImage instanceof PDImageXObject)
            {
                PDImageXObject image = (PDImageXObject)pdImage;
                File file = new File(RESULT_FOLDER, String.format("10948-new-engine-%s-%s.%s", currentPage, index, image.getSuffix()));
                ImageIOUtil.writeImage(image.getImage(), image.getSuffix(), new FileOutputStream(file));
                index++;
            }
        }

        @Override
        public void appendRectangle(Point2D p0, Point2D p1, Point2D p2, Point2D p3) throws IOException { }

        @Override
        public void clip(int windingRule) throws IOException { }

        @Override
        public void moveTo(float x, float y) throws IOException {  }

        @Override
        public void lineTo(float x, float y) throws IOException { }

        @Override
        public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) throws IOException {  }

        @Override
        public Point2D getCurrentPoint() throws IOException { return null; }

        @Override
        public void closePath() throws IOException { }

        @Override
        public void endPath() throws IOException { }

        @Override
        public void strokePath() throws IOException { }

        @Override
        public void fillPath(int windingRule) throws IOException { }

        @Override
        public void fillAndStrokePath(int windingRule) throws IOException { }

        @Override
        public void shadingFill(COSName shadingName) throws IOException { }
    };
    pdfGraphicsStreamEngine.processPage(pdPage);
    page++;
}

(ExtractImages.java测试方法testExtractPageImages10948New)

此代码输出文件名为“10948-new-engine-1-0.tiff”、“10948-new-engine-2-0.tiff”、“10948-new-engine”的图像-3-0.tiff”和“10948-new-engine-4-0.tiff”,即每页一个。

PS: 请记住在类路径中包含 com.github.jai-imageio:jai-imageio-core,这是 TIFF 输出所必需的。

翻转图像

OP 的另一个问题是图像有时上下颠倒,例如以他现在最新的示例文件“t1_edited.pdf”为例。原因是这些图片确实作为图片资源在PDF中是倒着存储的。

当这些图像绘制到页面上时,当前有效的变换矩阵会镜像垂直绘制的图像,从而创建预期的外观。

通过稍微增强上面代码中的 drawImage 实现,可以在导出图像的名称中包含此类翻转的指示符:

public void drawImage(PDImage pdImage) throws IOException
{
    if (pdImage instanceof PDImageXObject)
    {
        Matrix ctm = getGraphicsState().getCurrentTransformationMatrix();
        String flips = "";
        if (ctm.getScaleX() < 0)
            flips += "h";
        if (ctm.getScaleY() < 0)
            flips += "v";
        if (flips.length() > 0)
            flips = "-" + flips;
        PDImageXObject image = (PDImageXObject)pdImage;
        File file = new File(RESULT_FOLDER, String.format("t1_edited-engine-%s-%s%s.%s", currentPage, index, flips, image.getSuffix()));
        ImageIOUtil.writeImage(image.getImage(), image.getSuffix(), new FileOutputStream(file));
        index++;
    }
}

现在垂直或水平翻转的图像会相应标记。