1

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

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

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

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

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

我该如何解决这个问题谢谢。

下载文件示例以进行测试

    `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);
            }
        }
    }`
4

1 回答 1

6

正确提取图像

更新后的 PDF 清楚地表明,问题是它没有立即在页面上显示任何图像,但它具有绘制在其上的包含图像的表单 xobjects。因此,图像搜索必须递归到 xobjects 的形式。

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

实际上,这是 PDFBox 工具ExtractImages所做的事情。不幸的是,它并没有显示找到相关图像的页面,参见。ExtractImages.java测试方法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++;
    }
}

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

于 2016-11-15T22:50:52.323 回答