1

画像抽出時の PDFBox の問題。こんにちは、pdfページが画像であるかどうかを確認し、PDFBOXライブラリでそれを抽出する方法はありますが、画像を取得する方法がありますが、PDFページが画像の場合は取得できません。誰かがこの問題を解決するのを手伝ってくれませんか。

画像の抽出に関する Xpdf の問題。別のライブラリ xpdf で画像を抽出しようとしましたが、画像の場合、ページ上で奇妙なフリップが行われます。PDFにオブジェクト画像として小さな画像が含まれている場合は問題ありません。ページがスキャンされている場合、彼はフリップを行っています。

ページをスキャンして画像として取得する場合、ページにプレーンテキストと画像が含まれている場合、このページから画像を取得する場合、PDF からすべての画像を抽出したいと考えています。

私のポイントは、PDFからすべての画像を抽出することです。ページを形成するだけでなく、ページが画像であっても画像として抽出しますが、それらをスキップしないでください PDFbox はどうなっていると思いますか。

XPDF は何らかの処理を行っていますが、スキャンしたページをエクスポートするときに、ページに FLIP(上、右) という問題があります。

どうすればこの問題を解決できますか ありがとう。

テスト用のダウンロード ファイルの例

    `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」、つまり 1 ページに 1 つ。

PS:クラスパスに含めることを忘れないcom.github.jai-imageio:jai-imageio-coreでください。これは TIFF 出力に必要です。

反転した画像

OP のもう 1 つの問題は、たとえば、彼の最新のサンプル ファイル「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 に答える