Creating Visible Signatures with Apache PDFBox v2 Java Library

Learn how to add a static base64 encoded signature image to a PDF using PDFBox, with a coordinate system starting from the bottom left for natural placement.

21 Aug
,
2023
5 May
,
2025
# min read
Diagram showing PDF rectangle coordinates for digital document layout and design

One of the most common features in document signing applications is the ability to show a visual representation of a user's signature—essentially, an image—on the final signed PDF.

In this article, we’ll walk through how to achieve that using Apache PDFBox and a base64-encoded PNG image. This approach is based on the official PDFBox CreateVisibleSignature2 example, with a few key differences:

What's Different in This Approach?

  • Static image: Instead of generating the signature image dynamically, we use a pre-generated base64-encoded PNG.
  • Coordinate system: We position the image starting from the bottom-left corner of the page, which is more intuitive—most signatures appear at the bottom of documents.

Full Java Example

Below is a working example that loads a base64-encoded PDF, applies a base64-encoded signature image at a given position on the first page, and prepares the document for signing:

public class VisualSigner {
    public void addVisibleSignatureToPdf() throws IOException {
        String pdfInBase64 = "JVBERi0xLjQKJdPr....jEwODg5CiUlRU9G";
        String signatureImageInBase64 = "iVBORw0KGgoAAAA...gAAAAASUVORK5CYII=";
        long signatureTime = 1692617329341L;

        PDDocument document = PDDocument.load(Base64.getDecoder().decode(pdfInBase64));
        PDSignature signature = new PDSignature();
        signature.setType(COSName.getPDFName("Sig"));
        signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
        signature.setSubFilter(PDSignature.SUBFILTER_ETSI_CADES_DETACHED);

        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date(signatureTime));
        signature.setSignDate(cal);

        SignatureOptions options = new SignatureOptions();
        options.setPreferredSignatureSize(SignatureOptions.DEFAULT_SIGNATURE_SIZE);

        int pageNum = 0;
        options.setPage(pageNum);

        Rectangle2D rect = new Rectangle2D.Float(20, 10, 200, 100);
        PDRectangle pdfRect = createSignatureRectangle(document, rect);
        options.setVisualSignature(createVisualSignatureTemplate(document, pageNum, pdfRect, signatureImageInBase64));

        document.addSignature(signature, options);

        try (FileOutputStream output = new FileOutputStream("prepared.pdf")) {
            document.saveIncrementalForExternalSigning(output);
        }

        document.close();
        IOUtils.closeQuietly(options);
    }

    // (Helper methods continue below...)
}

The helper methods createSignatureRectangle and createVisualSignatureTemplate handle coordinate alignment and image rendering. (See the full code in the repo or below.)

Understanding PDFBox Coordinates

In createSignatureRectangle, we position the rectangle using:

rect.setLowerLeftX(...);
rect.setLowerLeftY(...);
rect.setUpperRightX(...);
rect.setUpperRightY(...);

This defines the rectangle where the signature image will appear. Here’s how it works visually:

(Insert diagram showing bottom-left origin, with arrows showing how the coordinates define a rectangle.)

  • Lower-left corner defines the starting point (x, y)
  • Upper-right corner defines the end (x + width, y + height)

The rotation of the page is also taken into account, ensuring the signature always appears correctly oriented.

Why Use a Base64-Encoded Image?

Using base64 allows flexibility in how the image is sourced. You can:

  • Store it in a database
  • Embed it in an API payload
  • Generate it on the client (e.g., from a canvas) and pass it to the backend

No temporary files needed—just decode and apply it directly.

Final Thoughts

This method is useful when:

  • You need a quick, consistent visual signature
  • You don't want to generate the image server-side each time
  • You need to preview or test signing flows before integrating full cryptographic operations

It also plays nicely with external signing flows, such as when the signature is applied by a remote Trust Service Provider after preparing the visual layer.

More latest articles

See all news
See all news