How to detect signature images from a pdf document via itextpdf in Java?

How to detect signature images from a pdf document via itextpdf in Java?
Photo by Estée Janssens / Unsplash

Image you have a pdf that requires customer signatures. Such as

You want to write a program to sign the signature automatically. First, you need to scan the whole PDF document and find all the places that require signature. Second, you need to replace those places with your fancy signature. In this post, I will focus on how to detect the images that requires signatures.

use itextpdf lib

com.itextpdf itextpdf 5.5.13, A Free Java-PDF library

PdfReaderContentParser::processContent

use PdfReader to read the pdf file and get the page numbers. Then PdfReaderContentParser::processContent to process the content of each page. The function accept a RenderListener interface to inform you when a text will be rendered, and when an image will be rendered.

try {
    Path path = Paths.get(new ClassPathResource("test.pdf").getFile().getAbsolutePath());
    byte[] pdf = Files.readAllBytes(path);
    PdfReader pdfReader = new PdfReader(pdf);
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    PdfStamper pdfStamper = new PdfStamper(pdfReader, byteArrayOutputStream);
    for (int page = 1; page <= pdfReader.getNumberOfPages(); page++) {
        PdfReaderContentParser parser = new PdfReaderContentParser(pdfReader);
        parser.processContent(page, new RenderListener() {...});
    }
    pdfStamper.close();
} catch (Exception e) {
    log.error("Oops!", e);
}

RenderListener::renderText & renderImage

Since in the above pdf, all the places requires signature will have the below structure orders: Text X Image Signature Place Holder Text Customer Signature. Then we make the assumption: If an Image is rendered between them(X and Customer), it can be considered as the Image for signature.

new RenderListener() {
    private String previousText;
    private PdfImageObject currentImg;
    @Override
    public void beginTextBlock() {}

    @Override
    public void renderText(TextRenderInfo textRenderInfo) {
        if (textRenderInfo.getText().equalsIgnoreCase("Customer")) {
            if (previousText.equalsIgnoreCase("X")) {
                if (currentImg != null) {
                    // this image is for customer signature
                    PdfDictionary pd = currentImg.getDictionary();
                    log.info("detect customer signature image with dimension : {} x {}", pd.get(PdfName.WIDTH), pd.get(PdfName.HEIGHT));
                    // reset to null
                    currentImg = null;
                }
            }
        }
        previousText = textRenderInfo.getText();
    }

    @Override
    public void endTextBlock() {}

    @SneakyThrows
    @Override
    public void renderImage(ImageRenderInfo imageRenderInfo) {
        PdfImageObject imgObj = imageRenderInfo.getImage();
        if (currentImg == null) {
            currentImg = imgObj;
        }
    }

Ok. Then we find out all the images place holders for signatures. In my next post, I will continue how to merge your fancy signature to replace them.

Subscribe to Post, Code and Quiet Time.

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe