場合によっては、フルページの高解像度画像(文書スキャンの結果)でいっぱいの非常に大きなPDFに遭遇することがあります。たとえば、私は3500 +画像で1.7GBのPDFを持っています。ドキュメントの読み込みには約50秒かかりますが、イメージのカウントには約15分かかります。PDFBox 2.xを使用してPDF画像を数える最速の方法
これは、イメージバイトがAPI呼び出しの一部として読み取られるためです。実際にイメージバイトを読み取らずにイメージカウントを抽出する方法はありますか?
PDFBoxバージョン:2.0.2
コード例:
@Test
public void imageCountIsCorrect() throws Exception {
PDDocument pdf = readPdf();
try {
assertEquals(3558, countImages(pdf));
// assertEquals(3558, countImagesWithExtractor(pdf));
} finally {
if (pdf != null) {
pdf.close();
}
}
}
protected PDDocument readPdf() throws IOException {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
FileInputStream stream = new FileInputStream("large.pdf");
PDDocument pdf;
try {
pdf = PDDocument.load(stream, MemoryUsageSetting.setupMixed(1024 * 1024 * 250));
} finally {
stream.close();
}
stopWatch.stop();
log.info("PDF loaded: time={}s", stopWatch.getTime()/1000);
return pdf;
}
protected int countImages(PDDocument pdf) throws IOException {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
int imageCount = 0;
for (PDPage pdPage : pdf.getPages()) {
PDResources pdResources = pdPage.getResources();
for (COSName cosName : pdResources.getXObjectNames()) {
PDXObject xobject = pdResources.getXObject(cosName);
if (xobject instanceof PDImageXObject) {
imageCount++;
if (imageCount % 100 == 0) {
log.info("Found image: #" + imageCount);
}
}
}
}
stopWatch.stop();
log.info("Images counted: time={}s,imageCount={}", stopWatch.getTime()/1000, imageCount);
return imageCount;
}
私はCOSNameに頼るcountImages方法を変更した場合、カウントは1秒未満で完了しますが、私は少し不確かです名前の接頭辞に頼っていること。 (など、インライン画像を欠場する可能性が
if (cosName.getName().startsWith("QuickPDFIm")) {
imageCount++;
}
注意点として、あなたのコードは、ページごとに*即時ビットマップイメージ*リソースをカウント。どちらも、オブジェクトまたはパターンに含まれるインラインイメージやイメージではありません。一方、イメージリソースはページ上で使用する必要はありません。したがって、時にはあまりにも多くの画像を数えます。一般的なソリューションでは、コンテンツストリームを検討する必要があります。 – mkl
ああ、PDFGraphicsStreamEngineのカスタム実装を使用してイメージを数えたときにイメージ数の間に見つかった矛盾のいくつかを説明します。私はそのコードを掘り下げて私が逃しているものを見つけ出すでしょう。ありがとう! –
私が念頭に置いておきたいのは、ExtractImagesの例を修正し、イメージオブジェクトを作成するすべてのオブジェクトを削除し、xobjectsが作成されていない場合は 'DrawObject extends GraphicsOperatorProcessor'プロセッサで' addOperator(new DrawObject());フォームに従います。 org.apache.pdfbox.contentstream.operator.DrawObjectのソースコードを参照してください。 –