How to Read DataMatrix and Other 1D/2D Barcodes from PDF Files in HTML5 and JavaScript

Xiao Ling
6 min readDec 4, 2024

--

In today’s digital world, barcodes have become an integral part of many industries, including healthcare, logistics, retail, and more. A significant use case is in medical forms, where 1D and 2D barcodes, such as DataMatrix, are embedded within PDF documents. These barcodes contain crucial information such as patient identification, medical codes, and treatment details, ensuring a smooth and efficient workflow. In this article, we will demonstrate how to extract and read DataMatrix and other 1D/2D barcodes from PDF files using HTML5 and JavaScript.

Demo Video: Read DataMatrix from PDF Files

Online Demo

https://yushulx.me/web-document-annotation/

Prerequisites

Steps to Read DataMatrix and Other Barcodes from PDF Files

In a previous article, we created a web-based PDF document editor with barcode insertion capabilities using Dynamsoft Document Viewer. The source code from that article will be used as the starting point for this tutorial.

In the latest version of Dynamsoft Document Viewer, a flattened property has been added to the annotation object, making it more flexible and efficient to flatten target annotations into a document. When barcodes are inserted as annotations into PDF documents, they are typically stored as vector graphics and are unreadable until they are flattened into the document. This process converts the vector graphics into raster images.

Step 1: Flatten 1D/2D Barcode Annotations in PDF Files

If you don’t have a PDF document with barcode annotations, you can create one as follows:

  1. Deploy the project and open the web-based PDF document editor in your browser.
 python -m http.server 8000

2. Click

to load a PDF or other image file into the document viewer.

3. Click

to insert a DataMatrix or other barcode into the document.

4. Click

to save the modified PDF file to your local disk.

Explanation

  • The password is optional. You can encrypt the PDF file with a password.
  • The annotation type specifies how to save the annotations. The default value is None, which means the annotations will not be saved in the PDF file. Other options include Image, Annotation, and Flattened. Select Annotation to save the barcode annotations to ensure they can be edited when importing the PDF file back into the document viewer.

Next, load the saved PDF file into the document viewer. The default built-in loading method does not support entering the PDF password, so we need to customize the loading button to prompt for the password.

  1. Create a prompt container in index.html:
<div id="password-input" class="overlay">
<div class="popup">
<h2>Input PDF Password</h2>
<form id="passwordForm">
<div class="form-group">
<label for="password">Password:</label>
<input type="password" id="pdfpassword" name="pdfpassword" placeholder="Enter password" required>
</div>
<div class="popup-buttons">
<button type="button" id="submitPassword">Submit</button>
<button type="button" id="cancelPassword">Cancel</button>
</div>
</form>
</div>
</div>

2. Create an element object and insert it into the UI configuration in main.js:

const loadButton = {
type: Dynamsoft.DDV.Elements.Button,
className: "ddv-button ddv-load-image",
tooltip: "Load a document",
events: {
click: "loadDocument",
},
}

const pcEditViewerUiConfig = {
type: Dynamsoft.DDV.Elements.Layout,
flexDirection: "column",
className: "ddv-edit-viewer-desktop",
children: [
{
type: Dynamsoft.DDV.Elements.Layout,
className: "ddv-edit-viewer-header-desktop",
children: [
...
{
type: Dynamsoft.DDV.Elements.Layout,
children: [
{
type: Dynamsoft.DDV.Elements.Pagination,
className: "ddv-edit-viewer-pagination-desktop",
},
loadButton,
downloadButton,
],
},
],
},
Dynamsoft.DDV.Elements.MainView,
],
};

3. Handle the loadDocument event to load the PDF file with a password prompt in main.js:

editViewer.on("loadDocument", loadDocument);

function loadDocument() {
let fileInput = document.createElement("input");
fileInput.type = "file";
fileInput.accept = ".jpg,.jpeg,.png,.tiff,.tif,.bmp,.pdf";
fileInput.onchange = async (e) => {
let file = e.target.files[0];
if (!file) return;

const reader = new FileReader();

reader.onload = async function (e) {
fileBlob = new Blob([e.target.result], { type: file.type });
load(fileBlob);
};

reader.readAsArrayBuffer(file);


};
fileInput.click();
}

async function load(blob, password) {
try {
if (!currentDoc) {
currentDoc = Dynamsoft.DDV.documentManager.createDocument({
name: Date.now().toString(),
author: "DDV",
});
}

const source = {
fileData: blob,
password: password,
renderOptions: {
renderAnnotations: "loadAnnotations"
}
};
await currentDoc.loadSource([source]);
editViewer.openDocument(currentDoc);
} catch (error) {
console.error(error);

// PDF is encrypted
if (error.cause.code == -80202) {
document.getElementById("password-input").style.display = "flex";
}
}
}

let fileBlob = null;
const submitPasswordButton = document.getElementById('submitPassword');
const cancelPasswordButton = document.getElementById('cancelPassword');

cancelPasswordButton.addEventListener('click', () => {
document.getElementById("password-input").style.display = "none";
}
);

submitPasswordButton.addEventListener('click', async () => {
const password = document.getElementById('pdfpassword').value;
load(fileBlob, password);
document.getElementById("password-input").style.display = "none";
});

Explanation

  • loadDocument(): Create an input element for loading PDF files. Use FileReader to read the file content and convert it into a blob.
  • load(blob, password): Load the PDF file into the document viewer. If the PDF is encrypted, display a password input element.

As a PDF file is loaded into the document viewer, change the status of all annotations to flattened. This creates a raster image for barcode detection later.

let currentPageId = currentDoc.pages[editViewer.getCurrentPageIndex()];
let annotations = Dynamsoft.DDV.annotationManager.getAnnotationsByPage(currentPageId);

for (let i = 0; i < annotations.length; i++) {
annotations[i].flattened = true;
}
const image = await editViewer.currentDocument.saveToJpeg(editViewer.getCurrentPageIndex(), settings);

Step 2: Read DataMatrix and Other Barcodes with Dynamsoft Barcode Reader

  1. Include the Dynamsoft Barcode Reader Bundle in index.html:
<script src="https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@10.4.2002/dist/dbr.bundle.js"></script>

2. Create a CaptureVisionRouter object in main.js:

cvRouter = await Dynamsoft.CVR.CaptureVisionRouter.createInstance();

3. Read the barcodes from the raster image in main.js:

const result = await cvRouter.capture(image, "ReadBarcodes_Default");

The second parameter is the a template name preset in the Capture Vision Router. Click here to learn more about the preset templates.

4. Display the barcode results by drawing annotations in main.js:

for (let item of result.items) {
if (item.type !== Dynamsoft.Core.EnumCapturedResultItemType.CRIT_BARCODE) {
continue;
}
console.log(JSON.stringify(item));
let text = item.text;
let points = item.location.points;

let currentPageId = currentDoc.pages[editViewer.getCurrentPageIndex()];
let pageData = await currentDoc.getPageData(currentPageId);

// https://www.dynamsoft.com/document-viewer/docs/api/interface/annotationinterface/texttypewriterannotationoptions.html
let textX = Math.min(points[0].x, points[1].x, points[2].x, points[3].x) / pageData.display.width * pageData.mediaBox.width;
let textY = Math.min(points[0].y, points[1].y, points[2].y, points[3].y) / pageData.display.height * pageData.mediaBox.height;

const textTypewriterOptions = {
x: textX < 0 ? 0 : textX,
y: textY - 15 < 0 ? 0 : textY - 15,
textContents: [{ content: text, color: "rgb(255,0,0)" }],
flags: {
print: false,
noView: false,
readOnly: false,

}
}

// https://www.dynamsoft.com/document-viewer/docs/api/class/annotationmanager.html#createAnnotation
let textTypewriter = await Dynamsoft.DDV.annotationManager.createAnnotation(currentPageId, "textTypewriter", textTypewriterOptions)
savedAnnotations.push(textTypewriter);
textTypewriter['name'] = 'overlay';

// https://www.dynamsoft.com/document-viewer/docs/api/interface/annotationinterface/polygonannotationoptions.html
const polygonOptions = {
points: points.map(p => {
return {
x: p.x / pageData.display.width * pageData.mediaBox.width,
y: p.y / pageData.display.height * pageData.mediaBox.height
}
}),
borderColor: "rgb(255,0,0)",
flags: {
print: false,
noView: false,
readOnly: false,

}
}

let polygon = Dynamsoft.DDV.annotationManager.createAnnotation(currentPageId, "polygon", polygonOptions);
polygon['name'] = 'overlay';
savedAnnotations.push(polygon);
}

Source Code

https://github.com/yushulx/web-twain-document-scan-management/tree/main/examples/document_annotation

Originally published at https://www.dynamsoft.com on December 4, 2024.

--

--

Xiao Ling
Xiao Ling

Written by Xiao Ling

Manager of Dynamsoft Open Source Projects | Tech Lover

No responses yet