Skip to content

Commit 86f10d1

Browse files
authored
Merge pull request #899 from dynamsoft-docs/preview
update to internal commit 39066676
2 parents 5ea669a + 25665fe commit 86f10d1

File tree

4 files changed

+275
-0
lines changed

4 files changed

+275
-0
lines changed

_articles/indepth/development/mrz.md

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
---
2+
layout: default-layout
3+
needAutoGenerateSidebar: true
4+
title: Dynamic Web TWAIN SDK Development - MRZ Scanner Integration
5+
keywords: Dynamic Web TWAIN, Documentation, Development, MRZ, MRZ Scanner, Integration
6+
breadcrumbText: MRZ Scanner Integration
7+
description: Dynamic Web TWAIN SDK Documentation MRZ Scanner Integration Page
8+
---
9+
10+
# Integrating the MRZ Scanner into a Dynamic Web TWAIN Application
11+
12+
One of the solutions that Dynamsoft offers is the [MRZ Scanner](https://www.dynamsoft.com/use-cases/mrz-scanner/), which is built on the foundational products [Dynamsoft Label Recognizer]({{ site.dcv }}core/introduction/?ver=latest&ver=latest#dynamsoft-label-recognizer) and the [Dynamsoft Code Parser]({{ site.dcv }}core/introduction/?ver=latest&ver=latest#dynamsoft-code-parser). This solution allows the user to scan MRZs in a web or native mobile application, either via a camera or static images from the local photo library.
13+
14+
In this article, we will address how you can integrate the foundational products of the MRZ Scanner JavaScript Edition (Dynamsoft Label Recognizer, Dynamsoft Code Parser) with Dynamic Web TWAIN to implement the ability to read from static images without the need for a camera input.
15+
16+
> You can download the [full sample code](https://github.com/Dynamsoft/mrz-scanner-javascript/tree/main/samples/dwt-mrz) from the Github repository of the MRZ Scanner Samples. Please use this sample as reference when building your own application.
17+
18+
## Initialization
19+
20+
Dynamic Web TWAIN (DWT for short) allows users to acquire images from scanners in a web application, as well as load or download existing documents. One of the advantages of using Dynamic Web TWAIN is that it allows the user to load in PDFs as well as images. So whether you are loading in a local image or acquiring an image from a physical scanner, Dynamic Web TWAIN keeps things simple and implements these features with a few simple API.
21+
22+
### Setting up the Resources
23+
24+
The first thing to do when creating a web application that utilizes DWT is to include the Resources folder of DWT. In this folder, the template for the MRZ Reader needs to also be included since it will be referenced by the MRZ Reader. To get a copy of the DWT Resources, please download the [30-day free trial](https://www.dynamsoft.com/web-twain/downloads) of Dynamic Web TWAIN.
25+
26+
To get started with setting up the DWT resources and license key, please refer to the [General Usage]({{ site.general-usage }}index.html) page of the DWT docs. For the implementation that this guide will address, we will keep it to the basic functionalities of DWT, which is to [acquire images from a scanner]({{ site.general-usage }}scanner-image-acquisition.html) and [loading documents from local files]({{ site.extended-usage }}file-import.html).
27+
28+
### Initializing the Input Source and Capture Vision Instance
29+
30+
The following is the full code needed to implement the basic functionalities of Dynamic Web TWAIN as well as the initialization of the MRZ reader using the [foundational API]({{ site.dcv }}web/programming/javascript/api-reference/index.html) of Dynamsoft Capture Vision.
31+
32+
```html
33+
<!DOCTYPE html>
34+
<html>
35+
36+
<head>
37+
<title>Hello World</title>
38+
<script type="text/javascript" src="Resources/dynamsoft.webtwain.initiate.js"></script>
39+
<script type="text/javascript" src="Resources/dynamsoft.webtwain.config.js"></script>
40+
<script src="https://cdn.jsdelivr.net/npm/dynamsoft-capture-vision-bundle@2.6.1000/dist/dcv.bundle.js"></script>
41+
</head>
42+
43+
<body>
44+
<input type="button" value="Scan" onclick="AcquireImage();" />
45+
<input type="button" value="Load" onclick="LoadImage();" />
46+
<input type="button" value="Read MRZ" onclick="readMRZ();" />
47+
<div id="dwtcontrolContainer" style="width: 350px; height: 380px;"></div>
48+
49+
<p>MRZ Result:</p>
50+
<div
51+
id="divNoteMessage"
52+
style="width: 500px; height: 450px; border: 1px solid #ccc; overflow: auto; white-space: pre-line"
53+
></div>
54+
55+
<script type="text/javascript">
56+
var DWTObject;
57+
var cvRouter;
58+
59+
Dynamsoft.DWT.RegisterEvent("OnWebTwainReady", function () {
60+
initializeMRZ();
61+
DWTObject = Dynamsoft.DWT.GetWebTwain('dwtcontrolContainer'); // Get the Dynamic Web TWAIN object that is embedded in the div with id 'dwtcontrolContainer'
62+
});
63+
64+
/* The objective of this function is to initialize the Capture Vision instance and apply the necessary settings for reading MRZ */
65+
async function initializeMRZ() {
66+
// Inialize License Key
67+
Dynamsoft.License.LicenseManager.initLicense("MRZ_LICENSE_KEY_HERE");
68+
69+
// Load MRZ Resources
70+
Dynamsoft.Core.CoreModule.loadWasm(["DLR", "DCP"]);
71+
Dynamsoft.DCP.CodeParserModule.loadSpec("MRTD_TD3_PASSPORT");
72+
Dynamsoft.DCP.CodeParserModule.loadSpec("MRTD_TD1_ID");
73+
Dynamsoft.DCP.CodeParserModule.loadSpec("MRTD_TD2_ID");
74+
Dynamsoft.DLR.LabelRecognizerModule.loadRecognitionData("MRZ");
75+
76+
// Create Capture Vision Router Instance with MRZ templates
77+
cvRouter = await Dynamsoft.CVR.CaptureVisionRouter.createInstance();
78+
await cvRouter.initSettings("./Resources/mrz-template.json");
79+
80+
console.log("MRZ Initialized Successfully");
81+
}
82+
83+
/* This function is used to acquire an image from a physical scanner using the DWT API */
84+
function AcquireImage() {
85+
if (DWTObject) {
86+
DWTObject.SelectSourceAsync().then(function(){
87+
return DWTObject.AcquireImageAsync({
88+
IfCloseSourceAfterAcquire: true // Scanner source will be closed automatically after the scan.
89+
});
90+
}).catch(function (exp) {
91+
alert(exp.message);
92+
});
93+
}
94+
}
95+
96+
//Callback functions for async APIs
97+
function OnSuccess() {
98+
console.log('successful');
99+
}
100+
101+
function OnFailure(errorCode, errorString) {
102+
if(errorCode != -2326)
103+
alert(errorString);
104+
}
105+
106+
/* The fucntion that is triggered when the user clicks the "Load" button */
107+
function LoadImage() {
108+
if (DWTObject) {
109+
DWTObject.IfShowFileDialog = true; // Open the system's file dialog to load image
110+
DWTObject.LoadImageEx("", Dynamsoft.DWT.EnumDWT_ImageType.IT_ALL, OnSuccess, OnFailure); // Load images in all supported formats (.bmp, .jpg, .tif, .png, .pdf). OnSuccess or OnFailure will be called after the operation
111+
}
112+
}
113+
114+
/* A function to check if there are any images in the DWT buffer */
115+
function checkIfImagesInBuffer() {
116+
if (DWTObject.HowManyImagesInBuffer == 0) {
117+
console.log("There is no image in the buffer.")
118+
return false;
119+
}
120+
else return true;
121+
}
122+
</script>
123+
</body>
124+
125+
</html>
126+
```
127+
128+
## Implementing the MRZ Reader
129+
130+
Now that we introduced the code to initialize DWT and the MRZ Reader, as well as defined the functions that implement the scanning and loading capabilities of Web TWAIN, it's time now to implement the MRZ reading portion of the code. Continuing the **script** from the previous section:
131+
132+
```js
133+
// Used by the Button on page, to trigger a MRZ read with the current select page
134+
async function readMRZ() {
135+
if (!checkIfImagesInBuffer()) {
136+
return;
137+
}
138+
if (!cvRouter) {
139+
console.log("cvRouter is not initialized.");
140+
return;
141+
}
142+
let imgURL = DWTObject.GetImageURL(DWTObject.CurrentImageIndexInBuffer);
143+
let capturedResults = await cvRouter.capture(imgURL, "ReadPassportAndId");
144+
const recognizedResults = capturedResults.textLineResultItems;
145+
const parsedResults = capturedResults.parsedResultItems;
146+
if (!parsedResults || !parsedResults.length) {
147+
console.log("No Result");
148+
return;
149+
}
150+
151+
let extractedResults = JSON.stringify(extractDocumentFields(parsedResults[0]));
152+
extractedResults = extractedResults.split(",").join("\n");
153+
extractedResults = extractedResults.replace(/{"text":|[{"}]/g, "");
154+
document.getElementById("divNoteMessage").innerHTML = extractedResults; // print the result to the result div
155+
}
156+
157+
/**
158+
* Extracts and returns document fields from the parsed MRZ result
159+
*
160+
* @param {Object} result - The parsed result object containing document fields.
161+
* @returns {Object} An object with key-value pairs of the extracted fields.
162+
*/
163+
function extractDocumentFields(result) {
164+
if (!result || result.exception) {
165+
return {};
166+
}
167+
168+
const fieldWithStatus = (fieldName, raw=false) => ({
169+
text: raw ? result.getFieldRawValue(fieldName) : result.getFieldValue(fieldName),
170+
});
171+
172+
const parseDate = (yearField, monthField, dayField) => {
173+
const year = result.getFieldValue(yearField);
174+
const currentYear = new Date().getFullYear() % 100;
175+
const baseYear =
176+
yearField === "expiryYear" ? (parseInt(year) >= 60 ? "19" : "20") : parseInt(year) > currentYear ? "19" : "20";
177+
178+
return {
179+
text: `${baseYear}${year}-${result.getFieldValue(monthField)}-${result.getFieldValue(dayField)}`,
180+
};
181+
};
182+
183+
// Add special case for Spanish IDs
184+
const getDocumentNumber = (codeType) => {
185+
const documentType = mapDocumentType(codeType);
186+
const documentNumberField =
187+
documentType === "passport" && codeType === "MRTD_TD3_PASSPORT"
188+
? "passportNumber"
189+
: result.getFieldRawValue("nationality") === "ESP" ?
190+
"optionalData1" : "documentNumber";
191+
192+
const primaryNumber = fieldWithStatus(documentNumberField);
193+
const longNumber = fieldWithStatus("longDocumentNumber");
194+
195+
return primaryNumber?.text ? primaryNumber : longNumber;
196+
};
197+
198+
// Document Type and Name
199+
const codeType = result.codeType;
200+
201+
return {
202+
Surname: fieldWithStatus("primaryIdentifier"),
203+
"Given Name": fieldWithStatus("secondaryIdentifier"),
204+
Nationality: fieldWithStatus("nationality", true),
205+
"Document Number": getDocumentNumber(codeType),
206+
"Document Type": documentTypeLabel(codeType),
207+
"Issuing State": fieldWithStatus("issuingState", true),
208+
Sex: fieldWithStatus("sex", true),
209+
"Date of Birth (YYYY-MM-DD)": parseDate("birthYear", "birthMonth", "birthDay"),
210+
"Date of Expiry (YYYY-MM-DD)": parseDate("expiryYear", "expiryMonth", "expiryDay"),
211+
"Document Type": JSON.parse(result.jsonString).CodeType,
212+
};
213+
}
214+
215+
function mapDocumentType(codeType) {
216+
switch (codeType) {
217+
case "MRTD_TD1_ID":
218+
return "td1";
219+
220+
case "MRTD_TD2_ID":
221+
case "MRTD_TD2_VISA":
222+
case "MRTD_TD2_FRENCH_ID":
223+
return "td2";
224+
225+
case "MRTD_TD3_PASSPORT":
226+
case "MRTD_TD3_VISA":
227+
return "passport";
228+
229+
default:
230+
throw new Error(`Unknown document type: ${codeType}`);
231+
}
232+
}
233+
234+
function documentTypeLabel(codeType) {
235+
switch (codeType) {
236+
case "MRTD_TD1_ID":
237+
return "ID (TD1)";
238+
239+
case "MRTD_TD2_ID":
240+
return "ID (TD2)";
241+
case "MRTD_TD2_VISA":
242+
return "ID (VISA)";
243+
case "MRTD_TD2_FRENCH_ID":
244+
return "French ID (TD2)";
245+
246+
case "MRTD_TD3_PASSPORT":
247+
return "Passport (TD3)";
248+
case "MRTD_TD3_VISA":
249+
return "Visa (TD3)";
250+
251+
default:
252+
throw new Error(`Unknown document type: ${codeType}`);
253+
}
254+
}
255+
```
256+
257+
By completing the script with the code above, you can now go ahead and test the app that you just created. Please note that in order to properly function, the sample will need to be hosted on a server.
258+
259+
If you are using VS Code, a quick and easy way to serve the project is using the [Five Server VSCode extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server). Simply install the extension, open the `hello-world.html` file in the editor, and click "Go Live" in the bottom right corner of the editor. This will serve the application at `http://127.0.0.1:5500/hello-world.html`. Alternatively, you can also use IIS or Github Pages to quickly serve your application.
260+
261+
## Final Comments
262+
263+
This sample was built based on the Hello World sample code of Web TWAIN as well as the Hello World code of the previous version of the MRZ Scanner that was dependent fully on the foundational API of Dynamsoft Capture Vision. Here are some references to check out:
264+
265+
- [Dynamic Web TWAIN User Guide]({{ site.general-usage }}index.html)
266+
- [MRZ Scanner User Guide using Foundational DCV API](https://www.dynamsoft.com/mrz-scanner/docs/web/guides/mrz-scanner-v1.1.html?ver=1.1&matchVer=true&cVer=true)
267+
- [Dynamic Web TWAIN API Reference]({{ site.api }})
268+
- [DCV Foundational API Reference]({{ site.dcv }}web/programming/javascript/api-reference/index.html)
269+
270+
If there are any questions regarding this sample or your own implementation, please feel free to contact the [Dynamsoft Support Team](https://www.dynamsoft.com/company/contact/).

_config.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ general-usage: /web-twain/docs/general-usage/
2828
extended-usage: /web-twain/docs/extended-usage/
2929
api: /web-twain/docs/info/api/
3030

31+
dcv: /capture-vision/docs/
32+
3133
dynamsoft_logo: /web-twain/docs/assets/img-icon/dynamsoft-logo.png
3234
dbr_logo: /web-twain/docs/assets/img-icon/dbr-logo.png
3335
edit_icon: /web-twain/docs/assets/img-icon/edit-icon.png

_data/full_tree.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ tree_list:
125125
path: /indepth/development/react.html
126126
- name: Use Web TWAIN in Vue
127127
path: /indepth/development/vue.html
128+
- name: Use Web TWAIN with the MRZ Scanner
129+
path: /indepth/development/mrz.html
128130
# - name: Use Web TWAIN in Vue 3
129131
# path: /indepth/development/vue3.html
130132
# - name: Using Web TWAIN with REST API

index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ permalink: /index.html
5959
- [Use Web TWAIN in Angular]({{site.indepth}}development/angular.html)
6060
- [Use Web TWAIN in React]({{site.indepth}}development/react.html)
6161
- [Use Web TWAIN in Vue]({{site.indepth}}development/vue.html)
62+
- [Use Web TWAIN with the MRZ Scanner]({{site.indepth}}development/mrz.html)
6263
- [Code Gallery](https://www.dynamsoft.com/web-twain/resources/code-gallery/)
6364

6465
### [API Reference]({{site.api}}index.html)

0 commit comments

Comments
 (0)