Some test text!

menu
search

Compare differences in two PDFs using JavaScript

This JavaScript sample compares two PDF files (can also be DOCX, XLSX, PPTX, PNG, JPG) and uses an image comparison algorithm to show where the documents are different (no servers or other external dependencies required). Comparison documents are typically displayed overlayed in the viewer but an option exists to show documents side by side by syncing different WebViewer instances (see side by side demo). Once two documents have been compared their difference will be displayed in red or blue. Red indicates a change that has occurred in the original document and blue indicates what has been added to the new document (black indicates no changes). This functionality is commonly used in construction software, where drawings or blueprints are compared to identify where changes have occurred. This sample works on all browsers (including IE10) and mobile devices without using plug-ins. To view an example visit our PDF Comparison demo.

Get StartedSamplesDownload

To run this sample, get started with a free trial of PDFTron SDK.

JavaScript

HTML

(() => {
  let PDFNet = null;
  let CoreControls = null;
  let Annotations = null;

  const parentDoc = window.parent.window.document;
  const uploadedDoc = [null, null];

  const viewerElement = parentDoc.getElementById('viewer');

  viewerElement.addEventListener('ready', async() => {
    await init();
    const doc1 = await PDFNet.PDFDoc.createFromURL('../../../samples/files/test_doc_1.pdf');
    const doc2 = await PDFNet.PDFDoc.createFromURL('../../../samples/files/test_doc_2.pdf');
    await compareDoc(doc1, doc2);

    parentDoc.getElementById('fileUpload1').disabled = false;
    parentDoc.getElementById('fileUpload2').disabled = false;
  });

  parentDoc.getElementById('fileUpload1').addEventListener('change', (e) => {
    getPDFDocFromUpload(e.target.files[0], 0);
  });

  parentDoc.getElementById('fileUpload2').addEventListener('change', (e) => {
    getPDFDocFromUpload(e.target.files[0], 1);
  });

  const enableCompareButton = async() => {
    const compareButton = parentDoc.getElementById('compareButton');

    if (!compareButton.classList.contains('disabled')) {
      return;
    }

    compareButton.classList.remove('disabled');

    compareButton.addEventListener('click', async() => {
      const doc1 = await uploadedDoc[0].getPDFDoc();
      const doc2 = await uploadedDoc[1].getPDFDoc();

      await compareDoc(doc1, doc2);
    });
  };

  const getPDFDocFromUpload = (file, fileIndex) => {
    const newDoc = new CoreControls.Document(file.name, 'pdf');

    const backendType = CoreControls.getDefaultBackendType();
    const options = {
      workerTransportPromise: CoreControls.initPDFWorkerTransports(backendType, {}),
      extension: 'pdf'
    };

    const partRetriever = new CoreControls.PartRetrievers.LocalPdfPartRetriever(file);

    newDoc.loadAsync(partRetriever, (err) => {
      if (err) {
        console.warn(err);
      }
      uploadedDoc[fileIndex] = newDoc;

      if (uploadedDoc[1] !== null && uploadedDoc[0] !== null) {
        enableCompareButton();
      }
    }, options);
  };

  const init = async() => {
    PDFNet = viewerElement.querySelector('iframe').contentWindow.PDFNet;
    const iframe = parentDoc.getElementById('viewer').getElementsByTagName('iframe')[0];
    CoreControls = iframe.contentWindow.CoreControls;
    Annotations = iframe.contentWindow.Annotations;
    PDFNet = viewerElement.querySelector('iframe').contentWindow.PDFNet;
    CoreControls.resetWorker();
    const type = await CoreControls.getDefaultBackendType();

    CoreControls.enableFullPDF(true);
    CoreControls.initPDFWorkerTransports(type, {});
    await PDFNet.initialize();
  };

  const getDiffOptions = async() => {
    const redColor = new Annotations.Color(200, 0, 0, 1);
    const blueColor = new Annotations.Color(0, 200, 200, 1);

    const options = await PDFNet.createDiffOptions();

    // instead of Annotations.Color, we can pass in an objects in the form {R: 200, G: 0, B: 0, A: 1}
    options.setColorA(redColor);
    options.setColorB(blueColor);

    options.setBlendMode(5);
    return options;
  };

  const compareDoc = async(doc1, doc2) => {
    const newDoc = await PDFNet.PDFDoc.create();
    newDoc.lock();

    const options = await getDiffOptions();

    const pages = [];
    const itr = await doc1.getPageIterator(1);
    const itr2 = await doc2.getPageIterator(1);

    let i = 0;
    for (itr; await itr.hasNext(); itr.next()) {
      const page = await itr.current();
      pages[i] = [page];
      i++;
    }

    i = 0;
    for (itr2; await itr2.hasNext(); itr2.next()) {
      const page = await itr2.current();
      (pages[i] || (pages[i] = [null])).push(page);
      i++;
    }

    pages.forEach(async([p1, p2]) => {
      if (!p1) {
        p1 = new PDFNet.Page(0);
      }
      if (!p2) {
        p2 = new PDFNet.Page(0);
      }

      await newDoc.appendVisualDiff(p1, p2, options);
    });

    await newDoc.unlock();
    readerControl.loadDocument(newDoc);
  };
})(window);
// eslint-disable-next-line spaced-comment
//# sourceURL=config.js
close

Free Trial

Get unlimited trial usage of PDFTron SDK to bring accurate, reliable, and fast document processing capabilities to any application or workflow.

Select a platform to get started with your free trial.

Unlimited usage. No email address required.

PDFTron Receives USD$71 Million Growth Investment Led By Silversmith Capital Partners

Learn More
close