PDF.co endpoint ‘/pdf/edit/replace-text-with-image’ replaces text with image inside the provided PDF file. This feature is useful in various scenarios, for example when we need to insert a signature at various places into an agreement PDF document.

For example, let’s take a look at the following input PDF image.

This is a two-page PDF agreement that expects the signatures of a deponent at places marked with “Your_Sign_Here”.

In the next section, we’ll be demonstrating what output looks like.

Output Demo

The following GIF demonstrates a simple HTML application developed with PDF.co.

This looks interesting, isn’t it? This application is a simple HTML file, and with the use of JavaScript libraries we’re achieving the desired result.

Let’s take a look at the input form again.

Following are the input fields and controls used in this form.

PDF.co API Key This input field is a placeholder for the PDF.co API key.
Input PDF URL Contains input PDF URL where processing needs to be done.
Signature Canvas A place where the user will sign his/her signature.
Text to Replace With Placeholder for which text to be replaced with signature.
“Add to PDF” button Upon clicking this button, PDF.co API will be called; and it’ll replace text with a signature image.

Source Code

Following is the JavaScript source code for this application.

var $canvas, $signaturePad;

$(document).ready(function () {
    $canvas = $('canvas');

    $("#btnAddSignatureToPDF").click(resizeSignatureAndProceedWithAppendingToPDF);

    $signaturePad = $('.clsCanvasContainer').signaturePad({
        drawOnly: true,
        defaultAction: 'drawIt',
        validateFields: false,
        lineWidth: 0,
        output: null,
        sigNav: null,
        name: null,
        typed: null,
        clear: '#btnClear',
        typeIt: null,
        drawIt: null,
        typeItDesc: null,
        drawItDesc: null
    });
});

function resizeSignatureAndProceedWithAppendingToPDF() {

    const ctx = $canvas[0].getContext("2d");
    ctx.clearRect(0, 0, $canvas.width, $canvas.height);

    const originalImageFromCanvas = $canvas[0].toDataURL();

    const callbackFn = function (respImage) {
        addSignatureToPDF(respImage);
    }

    resizeCanvasImage(originalImageFromCanvas, 0.28, callbackFn);
}

function addSignatureToPDF(signatureImage) {

    $("#btnAddSignatureToPDF").prop("disabled", true).text("Please Wait...");

    var myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");
    myHeaders.append("x-api-key", $("#txtPDFcoAPIKey").val());

    // You can also upload your own file into PDF.co and use it as url. Check "Upload File" samples for code snippets: https://github.com/bytescout/pdf-co-api-samples/tree/master/File%20Upload/    
    var raw = JSON.stringify({
        "url": $("#txtInputPDFUrl").val(),
        "searchString": $("#txtTextToReplaceWith").val(),
        "caseSensitive": false,
        "replaceImage": signatureImage,//"https://bytescout-com.s3-us-west-2.amazonaws.com/files/demo-files/cloud-api/pdf-edit/logo.png",
        "async": false,
        "profiles": "{ 'AutoCropImages': true }"
    });

    var requestOptions = {
        method: 'POST',
        headers: myHeaders,
        body: raw,
        redirect: 'follow'
    };

    fetch("https://api.pdf.co/v1/pdf/edit/replace-text-with-image", requestOptions)
        .then(response => response.text())
        .then(result => handleSuccessResponse(result))
        .catch(error => {
            $("#btnAddSignatureToPDF").prop("disabled", false).text("Add to PDF");
            console.log('error', error);
        });
}

function handleSuccessResponse(result) {
    $("#btnAddSignatureToPDF").prop("disabled", true).text("Add to PDF");
    var oResult = JSON.parse(result);
    if (oResult.error) {
        $("#divError").show();
        $("#divError").html(oResult.message);
    }
    else {
        $("#aViewResult").show();
        $("#aViewResult").attr("href", oResult.url);
    }
    $("#btnAddSignatureToPDF").prop("disabled", false);
}

function resizeCanvasImage(sourceImage, resizePercentage, callbackFn) {

    // const canvas = document.getElementById("canvas");
    // const ctx = canvas.getContext("2d");
    const img = new Image();
    img.src = sourceImage;

    img.onload = function () {
        const oc = document.createElement('canvas');
        const octx = oc.getContext('2d');
        octx.clearRect(0, 0, oc.width, oc.height);

        // Set the width & height to 75% of image
        oc.width = img.width * resizePercentage;
        oc.height = img.height * resizePercentage;
        // step 2, resize to temporary size
        octx.drawImage(img, 0, 0, oc.width, oc.height);

        // Get canvas image
        const resizedImageFromCanvas = oc.toDataURL();

        callbackFn(resizedImageFromCanvas);
    }
}

The full source code is available at this GitHub Link.
Now, there are two important pieces of code in this source code.

  1. How to make a user’s signature
  2. Logic where we’re calling PDF.co endpoint and generating output

How to Get a User’s Signature with jQuery Signaturepad

jQuery Signature pad is a lightweight open-source JavaScript library (based on jQuery). It turns the HTML canvas into a signature-pad. Source code and documentation can be found here.

In this sample, we’re calling the following jQuery method for turning-out canvas.

$signaturePad = $('.clsCanvasContainer').signaturePad({
        drawOnly: true,
        defaultAction: 'drawIt',
        validateFields: false,
        lineWidth: 0,
        output: null,
        sigNav: null,
        name: null,
        typed: null,
        clear: '#btnClear',
        typeIt: null,
        drawIt: null,
        typeItDesc: null,
        drawItDesc: null
    });

At this stage, we have the ability to take the user’s signature and get an output base64 image.

Moving to the next issue, the image captured by canvas is big and does not fit well in the input PDF’s signature placeholders. To tackle this situation, we obviously need to reduce signature image size. Once, the image is in proper size dimensions, it’s ready for use in the PDF.co endpoint.

Following is the logic we’ve used to reduce image size. Please note, that there are mainly two javascript functions.

  1. resizeSignatureAndProceedWithAppendingToPDF
  2. resizeCanvasImage
function resizeSignatureAndProceedWithAppendingToPDF() {
 
    const ctx = $canvas[0].getContext("2d");
    ctx.clearRect(0, 0, $canvas.width, $canvas.height);
 
    const originalImageFromCanvas = $canvas[0].toDataURL();
 
    const callbackFn = function (respImage) {
        addSignatureToPDF(respImage);
    }
 
    resizeCanvasImage(originalImageFromCanvas, 0.28, callbackFn);
}
function resizeCanvasImage(sourceImage, resizePercentage, callbackFn) {
 
    // const canvas = document.getElementById("canvas");
    // const ctx = canvas.getContext("2d");
    const img = new Image();
    img.src = sourceImage;
 
    img.onload = function () {
        const oc = document.createElement('canvas');
        const octx = oc.getContext('2d');
        octx.clearRect(0, 0, oc.width, oc.height);
 
        // Set the width & height to 75% of image
        oc.width = img.width * resizePercentage;
        oc.height = img.height * resizePercentage;
        // step 2, resize to temporary size
        octx.drawImage(img, 0, 0, oc.width, oc.height);
 
        // Get canvas image
        const resizedImageFromCanvas = oc.toDataURL();
 
        callbackFn(resizedImageFromCanvas);
    }
}

Function “resizeSignatureAndProceedWithAppendingToPDF” gets the user’s full-sized signature from canvas. After that, it passes-on this signature to another function “resizeCanvasImage”.

This function “resizeCanvasImage”, creates an in-memory canvas with provided reduced size; draws an image to it, and invokes a callback with the output resized image.

Then, this callback function calls function “addSignatureToPDF” for PDF.co related processing.

How to Add a Signature with PDF.co

In this final stage, we’re invoking the function “addSignatureToPDF”. Here, initially, we’re preparing PDF.co request headers.

  var myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");
    myHeaders.append("x-api-key", $("#txtPDFcoAPIKey").val());

Please note that we’re passing PDF.co API key “x-api-key” in the request header. PDF.co API Key is necessary for authentication of requests at the PDF.co side. One can receive this API key by signing up at PDF.co.

Next, we’re preparing a PDF.co request payload. It contains parameters such as input URL, the string that needs to be replaced, image URL which should replace the placeholder text, etc.

// You can also upload your own file into PDF.co and use it as url. Check "Upload File" samples for code snippets: https://github.com/bytescout/pdf-co-api-samples/tree/master/File%20Upload/    
    var raw = JSON.stringify({
        "url": $("#txtInputPDFUrl").val(),
        "searchString": $("#txtTextToReplaceWith").val(),
        "caseSensitive": false,
        "replaceImage": signatureImage,//"https://bytescout-com.s3-us-west-2.amazonaws.com/files/demo-files/cloud-api/pdf-edit/logo.png",
        "async": false,
        "profiles": "{ 'AutoCropImages': true }"
    });

In addition to that, the Request payload also contains profile parameters for enabling auto-cropping white space from the input image.

PDF.co endpoint “/pdf/edit/replace-text-with-image” is used to perform text replacement with image. Please refer to this URL for more information about this endpoint.

Once a response arrives, we’re using it and display a link with the output URL. As simple as that!

Summary

Well, that’s it! I hope this article is helpful to you. Please try source code in your machine for better exposure. Thank you!