首页 > 解决方案 > 如何检测 PDF 页面中是否包含图像

问题描述

我正在处理 PDF/A 样式的 PDF 文档,这些文档混合了扫描的全页大小的图像,然后是在 ColumnText 对象中包含文本的图像页面之后的一两页。

使用 Java,我如何检测哪些页面有图像?

检测哪些页面具有图像或文本的目的是确定具有文本的第一页出现的位置。我需要编辑文本或将页面替换为具有更新文本的文本。带有图像的页面将保持不变。

我正在使用 iText5,目前没有升级到 iText7 的选项。

这是我使用@mkl 提供的解决方案实现的解决方案:

ImageDetector.java

package org.test.pdf;

import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;

public class ImageDetector implements RenderListener {
    public void beginTextBlock() { }
    public void endTextBlock() { }
    public void renderText(TextRenderInfo renderInfo) {
        textFound = true;
    }

    public void renderImage(ImageRenderInfo renderInfo) {
        imageFound = true;
    }

    boolean textFound = false;
    boolean imageFound = false;
}

PdfDocumentServiceTest.java

package org.test.pdf;

import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.test.PdfService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

@ActiveProfiles({"local", "testing"})
@DirtiesContext
@Transactional
@RunWith(SpringRunner.class)
@SpringBootTest
public class PdfDocumentServiceTest {

    @Autowired
    private PdfService pdfService;

    @Test
    public void testFindImagesInPdf(Long pdfId)) {
        final byte[] resource = PdfService.getPdf(pdfId);
        int imagePageCount = 0;
        int textPageCount = 0;
        if (resource != null && resource.length > 0) {
            PdfReader reader = new PdfReader(resource);
            PdfReaderContentParser parser = new PdfReaderContentParser(reader);

            for (int pageNumber = 1; pageNumber <= reader.getNumberOfPages(); pageNumber++) {

                ImageDetector imageDetector = new ImageDetector();
                parser.processContent(pageNumber, imageDetector);

                if (imageDetector.imageFound) {
                    imagePageCount++;
                }
                if (imageDetector.textFound) {
                    textPageCount++;
                }
            }
            Assert.assertTrue(imagePageCount > 0);
            Assert.assertTrue(textPageCount > 0);
        }
    }
}

标签: javapdfitext

解决方案


使用 iText 5,您可以通过将页面内容解析为自定义RenderListener实现来确定图像是否实际显示在页面上。例如

class ImageDetector implements RenderListener {
    public void beginTextBlock() { }
    public void endTextBlock() { }
    public void renderText(TextRenderInfo renderInfo) { }

    public void renderImage(ImageRenderInfo renderInfo) {
        imageFound = true;
    }

    boolean imageFound = false;
}

像这样使用:

PdfReader reader = new PdfReader(resource);
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
for (int pageNumber = 1; pageNumber <= reader.getNumberOfPages(); pageNumber++)
{
    ImageDetector imageDetector = new ImageDetector();
    parser.processContent(pageNumber, imageDetector);
    if (imageDetector.imageFound) {
        // There is at least one image rendered on page i
        // Thus, handle it as an image page
    } else {
        // There is no image rendered on page i
        // Thus, handle it as a no-image page
    }
}

作为一个可能的改进:在评论中你提到full-page-size images。因此,在该ImageDetector方法中,renderImage您可能希望在设置imageFound为之前检查图像大小true。通过该ImageRenderInfo参数,您可以检索有关图像在页面上显示的大小和实际大小的信息。


推荐阅读