Skip to content

PDF overlay image comparison ​

From version 9.0.0, Foxit PDF SDK for Web provides APIs to compare PDFs by overlaying pages. The feature compares two documents pixel by pixel, finds differences, and produces an output image. You can use these APIs to implement overlay comparison in your application.

Overview ​

Steps

This section walks through overlay page comparison end to end:

  • Open documents
  • Create a document
  • Get PDF pages
  • Compare pages
  • Build a result page
  • Export the result document

Initialize PDFViewer ​

javascript
const libPath = window.top.location.origin + '/lib';
const pdfViewer = new PDFViewCtrl.PDFViewer({
    libPath: libPath,
    jr: {
        licenseSN: licenseSN,
        licenseKey: licenseKey
    }
});
pdfViewer.init(document.body);

Load documents to compare ​

javascript
async function loadFiles() {
    const sourcePDFDoc = await pdfViewer.loadPDFDocByHttpRangeRequest({
        range: {
            url: '/assets/test-doc1.pdf'
        }
    });
    const targetPDFDoc = await pdfViewer.loadPDFDocByHttpRangeRequest({
        range: {
            url: '/assets/test-doc2.pdf'
        }
    });
    return {sourcePDFDoc, targetPDFDoc};
}

Loading documents

The SDK offers two ways to load documents:

  1. loadPDFDocByHttpRangeRequest: Load a PDF from a remote URL with range requests
  2. loadPDFDocByFile: Load from an in-memory stream or a local file via <input type="file">

In production you can also use PDFViewer.getCurrentPDFDoc for the currently open document.

Create a blank document ​

javascript
function createBlankDoc() {
    return pdfViewer.createNewDoc();
}

Get bitmaps for pages to compare ​

javascript
async function getPageBitmaps(loadedFiles) {
    const {sourcePDFDoc, targetPDFDoc} = loadedFiles;

    const sourcePage = await sourcePDFDoc.getPageByIndex(0);
    const sourceBitmap = await sourcePage.render(1);

    const targetPage = await targetPDFDoc.getPageByIndex(0);
    const targetBitmap = await targetPage.render(1);

    return {sourceBitmap, targetBitmap};
}

Render options

To customize scale or rotation, pass arguments to render (scale, rotate). See API Reference for PDFPage.render.

Compare documents ​

javascript
function comparePageBitmap(sourceBitmap, targetBitmap) {
    const DiffColor = PDFViewCtrl.overlayComparison.DiffColor;
    const service = pdfViewer.getOverlayComparisonService();
    const resultCanvas = service.compareImageData({
        sourceBitmap,
        targetBitmap,
        combinePixelsOptions: {
            showDiffColor: true,
            sourceDiffColor: DiffColor.RED,
            targetDiffColor: DiffColor.BLUE,
            sourceOpacity: 0xFF,
            targetOpacity: 0xFF
        },
        transformation: {
            translateX: 0,
            translateY: 0,
            rotate: 2 / 180 * Math.PI
        }
    });
    return new Promise(resolve => {
        resultCanvas.toBlob(blob => {
            const fr = new FileReader();
            fr.onloadend = () => {
                resolve({
                    buffer: fr.result,
                    width: resultCanvas.width,
                    height: resultCanvas.height
                });
            };
            fr.readAsArrayBuffer(blob);
        });
    })
}

Comparison parameters

  1. showDiffColor: Differences are highlighted only when true
  2. sourceDiffColor and targetDiffColor: Must be colors from the DiffColor enum
  3. sourceOpacity and targetOpacity: Range 0–0xFF

Insert comparison result into a PDF page ​

javascript
async function insertResultIntoNewDoc(newDoc, resultImageData) {
    const page = await newDoc.getPageByIndex(0);

    / resultImageData is the return object of the comparePageBitmap function mentioned in the above example.
    / Convert the unit of width and height from pixel to point. 
    const newPageWidth = resultImageData.width / 4 * 3;
    const newPageHeight = resultImageData.height / 4 * 3;
    / Reset the size of PDF page to make it the same size as the comparison image.
    await page.setPageSize(newPageWidth, newPageHeight);
    / Last, insert it into the PDF page as a PDF image object.
    await page.addImage(resultImageData.buffer, {
        left: 0,
        right: newPageWidth,
        bottom: 0,
        top: newPageHeight
    });
}

Add comparison result to a new document ​

javascript
async function addComparisonResultToNewDoc(resultBitmap) {
    const newDoc = await createBlankDoc();
    const page = await newDoc.addPage(resultBitmap.width, resultBitmap.height);
    const image = await page.addImage(resultBitmap.buffer);
    const matrix = PDFViewCtrl.PDF.PDFMatrix.create();
    await page.addImageObject(image, matrix);
    return newDoc;
}

Export the result document ​

javascript
async function exportDoc(doc) {
    const file = await doc.getFile();
    const url = URL.createObjectURL(file);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'comparison-result.pdf';
    a.click();
    URL.revokeObjectURL(url);
}

Complete example ​

javascript
(async function() {
    const loadedFiles = await loadFiles();
    const {sourceBitmap, targetBitmap} = await getPageBitmaps(loadedFiles);
    const resultBitmap = await comparePageBitmap(sourceBitmap, targetBitmap);
    const resultDoc = await addComparisonResultToNewDoc(resultBitmap);
    await exportDoc(resultDoc);
})();

API reference ​

PDFViewer.getOverlayComparisonService() ​

Returns an OverlayComparisonService instance for comparing two images.

OverlayComparisonService.compareImageData(options) ​

Compares two images and returns a Canvas with the result.

Parameters:

typescript
interface CompareImageDataOptions {
    / Source image ImageData
    sourceBitmap: ImageData;
    / Target image ImageData
    targetBitmap: ImageData;
    / Pixel combine options
    combinePixelsOptions: {
        / Whether to show diff colors; default false
        showDiffColor?: boolean;
        / Color for differences in the source image
        sourceDiffColor?: DiffColor;
        / Color for differences in the target image
        targetDiffColor?: DiffColor;
        / Source opacity, 0~0xFF
        sourceOpacity?: number;
        / Target opacity, 0~0xFF
        targetOpacity?: number;
    };
    / Image transform options
    transformation?: {
        / X translation
        translateX?: number;
        / Y translation
        translateY?: number;
        / Rotation in radians
        rotate?: number;
    };
}

Available DiffColor Values:

  • DiffColor.RED
  • DiffColor.GREEN
  • DiffColor.BLUE
  • DiffColor.YELLOW
  • DiffColor.MAGENTA
  • DiffColor.CYAN
json
{
  "iframeOptions": {
    "style": "height: 800px"
  }
}

NOTE

Examples use ESNext syntax for clarity. Use a modern browser to run them in the developer guide. For older browsers, transpile with a tool such as Babel in your project.