画像を適切に抽出する
更新された 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++;
}
}
垂直方向または水平方向に反転された画像がそれに応じてマークされるようになりました。