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
Dynamsoft Capture Vision Trial License: Obtain a 30-day free trial license to unlock the full capabilities of Dynamsoft Products.
Dynamsoft Document Viewer: This JavaScript SDK allows for seamless viewing of PDF, JPEG, PNG, TIFF, and BMP files. It also features PDF annotation rendering and saving. Download link: https://www.npmjs.com/package/dynamsoft-document-viewer.
Dynamsoft Barcode Reader Bundle: This powerful JavaScript barcode scanning SDK supports a wide range of 1D and 2D barcode formats, including DataMatrix, QR Code, PDF417, Code 128 and more. Download link: https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle.
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:
-
Deploy the project and open the web-based PDF document editor in your browser.
python -m http.server 8000
Click to load a PDF or other image file into the document viewer.
Click to insert a DataMatrix or other barcode into the document.
-
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.
-
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>
-
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, ], };
-
Handle the
loadDocument
event to load the PDF file with a password prompt inmain.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. UseFileReader
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
-
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>
-
Create a
CaptureVisionRouter
object inmain.js
:
cvRouter = await Dynamsoft.CVR.CaptureVisionRouter.createInstance();
-
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.
-
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
Top comments (0)