> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/web/get-started/samples/viewerpdfdifftest.md).

# PDF Comparison by image - ViewerPDFDiff

Here is compare pdf js samples showcasing how to compare pdf, DOCX files or images using. Track the changes that have been made in documents using JS.

{% hint style="info" %}
**Requirements**

*These packages are required to use these features in production. Trial keys have unlimited access to all features*

<a href="/web/get-started/readme.md" class="button primary">Web SDK</a><a href="/web/full-api/full-api-overview.md" class="button primary">Full API</a><a href="https://showcase.apryse.com/compare-files" class="button primary">Live demo</a>
{% endhint %}

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](https://sdk.apryse.com/samples/web/samples/advanced/diff/)). 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 IE11) and mobile devices without using plug-ins.

Learn more about our [Web SDK](/web/get-started/guides.md).

### **Implementation steps**

Step 1: [Get started with WebViewer](/web/get-started/readme.md) in your preferred web stack

Step 2: [Enable the full API](/web/full-api/full-api-overview.md)

Step 3: Add the sample code provided in this guide

This full sample is one of many included in the [manual download of WebViewer.](/web/get-started/manually.md#1-download-webviewer)

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
(async exports => {
  const PDFNet = exports.Core.PDFNet;
  let Core = null;
  let Annotations = null;

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

  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();
    instance.UI.loadDocument(newDoc);
  };

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

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

    compareButton.classList.remove('disabled');

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

  const getPDFDocFromUpload = async (file, fileIndex) => {
    const newDoc = await Core.createDocument(file, {});
    uploadedDoc[fileIndex] = await newDoc.getPDFDoc();
    if (uploadedDoc[1] !== null && uploadedDoc[0] !== null) {
      enableCompareButton();
    }
  };

  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 init = async () => {
    Core = window.Core;
    Annotations = window.Core.Annotations;
    Core.enableFullPDF();
    await PDFNet.initialize();
  };

  window.addEventListener('viewerLoaded', 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;
  });
})(window);
// eslint-disable-next-line spaced-comment
//# sourceURL=config.js
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/web/get-started/samples/viewerpdfdifftest.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
