Skip to content

Commit 0268a9d

Browse files
update to internal commit 86e8e72a
1 parent 5ec953c commit 0268a9d

File tree

8 files changed

+318
-6
lines changed

8 files changed

+318
-6
lines changed

_config.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ code_types: /code-parser/docs/core/code-types/
3535
dcvb_root: /capture-vision/docs/core/
3636
mrz_js: /mrz-scanner/docs/web/
3737

38+
dwt: /web-twain/docs/
39+
3840
useVersionTree: true
3941

4042
assets: /mrz-scanner/docs/web/assets/

_includes/sidelist-codegallery.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,7 @@
55
<ul>
66
<li><a href="{{ site.codegallery }}demo/index.html" class="otherLinkColour">Demo</a></li>
77
</ul>
8+
<ul>
9+
<li><a href="{{ site.codegallery }}dwt-mrz/index.html" class="otherLinkColour">DWT and MRZ</a></li>
10+
</ul>
811
</li>

api/enums-mrz-scanner.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ enum EnumMRZDocumentType {
3030
### Syntax
3131

3232
```ts
33-
export enum EnumResultStatus {
33+
enum EnumResultStatus {
3434
RS_SUCCESS = 0,
3535
RS_CANCELLED = 1,
3636
RS_FAILED = 2,
@@ -42,7 +42,7 @@ export enum EnumResultStatus {
4242
### Syntax
4343

4444
```ts
45-
export enum EnumMRZData {
45+
enum EnumMRZData {
4646
InvalidFields = "invalidFields",
4747
DocumentType = "documentType",
4848
DocumentNumber = "documentNumber",

assets/imgs/ResultEditUI-MRZ.png

158 KB
Loading

codegallery/dwt-mrz/index.md

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
---
2+
layout: default-layout
3+
needAutoGenerateSidebar: true
4+
needGenerateH3Content: true
5+
noTitleIndex: false
6+
title: Dynamsoft MRZ Scanner JavaScript Edition - Reading from Local Images
7+
keywords: Documentation, MRZ Scanner, Dynamsoft MRZ Scanner JavaScript Edition, Local Images, Load
8+
description: Reading from Local Images with the Dynamsoft MRZ Scanner JavaScript Edition
9+
permalink: /codegallery/dwt-mrz/index.html
10+
---
11+
12+
# Reading MRZs from Local Images - JavaScript Edition
13+
14+
So far, the [MRZ Scanner JS User Guide]({{ site.guides }}mrz-scanner.html) addressed how you can use the library to scan MRZs from a camera in an interactive live video scenario. The majority of use cases will involve using the camera of a phone or a laptop directly, but there could be cases where a camera is not needed at all. Although the **MRZ Scanner JavaScript Edition** has the ability to read from local static images via the Load Image feature of the MRZScannerView, that still requires connecting to a valid camera input.
15+
16+
In this article, we will address how you can use the foundational products of the MRZ Scanner (Dynamsoft Label Recognizer, Dynamsoft Code Parser) to implement the ability to read from static images without the need for a camera input.
17+
18+
## Initialization
19+
20+
The first thing that needs to be determined is what the source of the images will be. There are several methods in which you can load images in JavaScript application, but in this article we will be using another Dynamsoft product, [Dynamic Web TWAIN]({{ site.dwt }}about/index.html).
21+
22+
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.
23+
24+
### Setting up the Resources
25+
26+
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.
27+
28+
Alternatively, 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.
29+
30+
### Initializing the Input Source and Capture Vision Instance
31+
32+
Let's now introduce 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.dcvb_js_api }}index.html) of Dynamsoft Capture Vision.
33+
34+
```html
35+
<!DOCTYPE html>
36+
<html>
37+
38+
<head>
39+
<title>Hello World</title>
40+
<script type="text/javascript" src="Resources/dynamsoft.webtwain.initiate.js"></script>
41+
<script type="text/javascript" src="Resources/dynamsoft.webtwain.config.js"></script>
42+
<script src="https://cdn.jsdelivr.net/npm/dynamsoft-capture-vision-bundle@2.6.1000/dist/dcv.bundle.js"></script>
43+
</head>
44+
45+
<body>
46+
<input type="button" value="Scan" onclick="AcquireImage();" />
47+
<input type="button" value="Load" onclick="LoadImage();" />
48+
<input type="button" value="Read MRZ" onclick="readMRZ();" />
49+
<div id="dwtcontrolContainer" style="width: 350px; height: 380px;"></div>
50+
51+
<script type="text/javascript">
52+
var DWTObject;
53+
var cvRouter;
54+
55+
Dynamsoft.DWT.RegisterEvent("OnWebTwainReady", function () {
56+
initializeMRZ();
57+
DWTObject = Dynamsoft.DWT.GetWebTwain('dwtcontrolContainer'); // Get the Dynamic Web TWAIN object that is embedded in the div with id 'dwtcontrolContainer'
58+
});
59+
60+
/* The objective of this function is to initialize the Capture Vision instance and apply the necessary settings for reading MRZ */
61+
async function initializeMRZ() {
62+
// Inialize License Key
63+
Dynamsoft.License.LicenseManager.initLicense("MRZ_LICENSE_KEY_HERE");
64+
65+
// Load MRZ Resources
66+
Dynamsoft.Core.CoreModule.loadWasm(["DLR", "DCP"]);
67+
Dynamsoft.DCP.CodeParserModule.loadSpec("MRTD_TD3_PASSPORT");
68+
Dynamsoft.DCP.CodeParserModule.loadSpec("MRTD_TD1_ID");
69+
Dynamsoft.DCP.CodeParserModule.loadSpec("MRTD_TD2_ID");
70+
Dynamsoft.DLR.LabelRecognizerModule.loadRecognitionData("MRZ");
71+
72+
// Create Capture Vision Router Instance with MRZ templates
73+
cvRouter = await Dynamsoft.CVR.CaptureVisionRouter.createInstance();
74+
await cvRouter.initSettings("./Resources/mrz-template.json");
75+
76+
console.log("MRZ Initialized Successfully");
77+
}
78+
79+
/* This function is used to acquire an image from a physical scanner using the DWT API */
80+
function AcquireImage() {
81+
if (DWTObject) {
82+
DWTObject.SelectSourceAsync().then(function(){
83+
return DWTObject.AcquireImageAsync({
84+
IfCloseSourceAfterAcquire: true // Scanner source will be closed automatically after the scan.
85+
});
86+
}).catch(function (exp) {
87+
alert(exp.message);
88+
});
89+
}
90+
}
91+
92+
//Callback functions for async APIs
93+
function OnSuccess() {
94+
console.log('successful');
95+
}
96+
97+
function OnFailure(errorCode, errorString) {
98+
if(errorCode != -2326)
99+
alert(errorString);
100+
}
101+
102+
/* The fucntion that is triggered when the user clicks the "Load" button */
103+
function LoadImage() {
104+
if (DWTObject) {
105+
DWTObject.IfShowFileDialog = true; // Open the system's file dialog to load image
106+
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
107+
}
108+
}
109+
110+
/* A function to check if there are any images in the DWT buffer */
111+
function checkIfImagesInBuffer() {
112+
if (DWTObject.HowManyImagesInBuffer == 0) {
113+
console.log("There is no image in the buffer.")
114+
return false;
115+
}
116+
else
117+
return true;
118+
}
119+
</script>
120+
</body>
121+
122+
</html>
123+
```
124+
125+
## Implementing the MRZ Reader
126+
127+
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:
128+
129+
```js
130+
// Used by the Button on page, to trigger a MRZ read with the current select page
131+
async function readMRZ() {
132+
if (!checkIfImagesInBuffer()) {
133+
return;
134+
}
135+
if (!cvRouter) {
136+
console.log("cvRouter is not initialized.");
137+
return;
138+
}
139+
console.log("Reading MRZ on Index " + DWTObject.CurrentImageIndexInBuffer);
140+
let imgURL = DWTObject.GetImageURL(DWTObject.CurrentImageIndexInBuffer);
141+
let capturedResults = await cvRouter.capture(imgURL, "ReadPassportAndId");
142+
const recognizedResults = capturedResults.textLineResultItems;
143+
const parsedResults = capturedResults.parsedResultItems;
144+
console.log(parsedResults);
145+
if (!parsedResults || !parsedResults.length) {
146+
console.log("No Result");
147+
return;
148+
}
149+
150+
extractedResults = extractDocumentFields(parsedResults[0]);
151+
console.log(recognizedResults);
152+
console.log(extractedResults);
153+
console.log("Please See Detailed MRZ Result in Console");
154+
}
155+
156+
/**
157+
* Extracts and returns document fields from the parsed MRZ result
158+
*
159+
* @param {Object} result - The parsed result object containing document fields.
160+
* @returns {Object} An object with key-value pairs of the extracted fields.
161+
*/
162+
function extractDocumentFields(result) {
163+
if (!result || result.exception) {
164+
return {};
165+
}
166+
167+
const fieldWithStatus = (fieldName, raw=false) => ({
168+
text: raw ? result.getFieldRawValue(fieldName) : result.getFieldValue(fieldName),
169+
status: result.getFieldValidationStatus(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+
status: [yearField, monthField, dayField].every(
181+
(field) => result.getFieldValidationStatus(field) === Dynamsoft.DCP.EnumValidationStatus.VS_SUCCEEDED
182+
)
183+
? Dynamsoft.DCP.EnumValidationStatus.VS_SUCCEEDED
184+
: Dynamsoft.DCP.EnumValidationStatus.VS_FAILED,
185+
};
186+
};
187+
188+
// Add special case for Spanish IDs
189+
const getDocumentNumber = (codeType) => {
190+
const documentType = mapDocumentType(codeType);
191+
const documentNumberField =
192+
documentType === "passport" && codeType === "MRTD_TD3_PASSPORT"
193+
? "passportNumber"
194+
: result.getFieldRawValue("nationality") === "ESP" ?
195+
"optionalData1" : "documentNumber";
196+
197+
const primaryNumber = fieldWithStatus(documentNumberField);
198+
const longNumber = fieldWithStatus("longDocumentNumber");
199+
200+
return primaryNumber?.text ? primaryNumber : longNumber;
201+
};
202+
203+
// Document Type and Name
204+
const codeType = result.codeType;
205+
206+
return {
207+
Surname: fieldWithStatus("primaryIdentifier"),
208+
"Given Name": fieldWithStatus("secondaryIdentifier"),
209+
Nationality: fieldWithStatus("nationality", true),
210+
"Document Number": getDocumentNumber(codeType),
211+
"Document Type": documentTypeLabel(codeType),
212+
"Issuing State": fieldWithStatus("issuingState", true),
213+
Sex: fieldWithStatus("sex"),
214+
"Date of Birth (YYYY-MM-DD)": parseDate("birthYear", "birthMonth", "birthDay"),
215+
"Date of Expiry (YYYY-MM-DD)": parseDate("expiryYear", "expiryMonth", "expiryDay"),
216+
"Document Type": JSON.parse(result.jsonString).CodeType,
217+
};
218+
}
219+
220+
function mapDocumentType(codeType) {
221+
switch (codeType) {
222+
case "MRTD_TD1_ID":
223+
return "td1";
224+
225+
case "MRTD_TD2_ID":
226+
case "MRTD_TD2_VISA":
227+
case "MRTD_TD2_FRENCH_ID":
228+
return "td2";
229+
230+
case "MRTD_TD3_PASSPORT":
231+
case "MRTD_TD3_VISA":
232+
return "passport";
233+
234+
default:
235+
throw new Error(`Unknown document type: ${codeType}`);
236+
}
237+
}
238+
239+
function documentTypeLabel(codeType) {
240+
switch (codeType) {
241+
case "MRTD_TD1_ID":
242+
return "ID (TD1)";
243+
244+
case "MRTD_TD2_ID":
245+
return "ID (TD2)";
246+
case "MRTD_TD2_VISA":
247+
return "ID (VISA)";
248+
case "MRTD_TD2_FRENCH_ID":
249+
return "French ID (TD2)";
250+
251+
case "MRTD_TD3_PASSPORT":
252+
return "Passport (TD3)";
253+
case "MRTD_TD3_VISA":
254+
return "Visa (TD3)";
255+
256+
default:
257+
throw new Error(`Unknown document type: ${codeType}`);
258+
}
259+
}
260+
```
261+
262+
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.
263+
264+
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.
265+
266+
## Final Comments
267+
268+
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:
269+
270+
- [Dynamic Web TWAIN User Guide]({{ site.dwt }}general-usage/index.html)
271+
- [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)
272+
- [Dynamic Web TWAIN API Reference]({{ site.dwt }}info/api/)
273+
- [DCV Foundational API Reference]({{ site.dcvb_js_api }}index.html)
274+
275+
If there are any questions regarding this sample or your own implementation, do not hesitate to get in touch with the [Dynamsoft Support Team](https://www.dynamsoft.com/company/contact/).

codegallery/index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ The demo implementation adds a bit more colour and character to the Hello World
2626

2727
The full code of the Demo can be found [**here**](demo/index.md).
2828

29+
## Dynamic Web TWAIN integration with MRZ
30+
31+
There could be some cases where the use of a camera is not the target input source. In this sample, we explore the integration of the MRZ Scanner with one of Dynamsoft's star products, Dynamic Web TWAIN (DWT for short). DWT is mainly used to acquire images from a physical scanner or loading/downloading images. Using Dynamsoft Capture Vision's foundational API, we demonstrate how you can integrate MRZ reading capabilities into a DWT application.
32+
33+
The full code and breakdown can be found [**here**](dwt-mrz/index.md).
34+
2935
## Official Dynamsoft MRZ Scanner Online Demo
3036

3137
For the best demonstration of the full capabilities of the MRZ Scanner JavaScript Edition, please visit the [official Dynamsoft MRZ Scanner JavaScript demo](https://demo.dynamsoft.com/mrz-scanner/).

guides/mrz-scanner-customization.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ const mrzScanner = new Dynamsoft.MRZScanner({
7070

7171
## `MRZScannerViewConfig` Overview
7272

73-
**`MRZScannerViewConfig`** control the UI elements of the `**MRZScannerView**`, which is the view responsible for scanning operations. Here are its three properties in detail:
73+
**`MRZScannerViewConfig`** control the UI elements of the `**MRZScannerView**`, which is the view responsible for scanning operations. Here are its properties in detail:
7474

7575
1. **`cameraEnhancerUIPath`** - define the path to a custom HTML user interface file for the `MRZScannerView`, which is based on the UI for the Dynamsoft Camera Enhancer SDK used by the MRZ Scanner. Setting the path to a custom file allows this custom UI to take effect for any `MRZScanner` instance created within your application. We recommend you to reach out to the [Dynamsoft Technical Support Team](https://www.dynamsoft.com/company/contact/) to assist you in creating such a custom UI.
7676

@@ -153,7 +153,7 @@ const mrzScanner = new Dynamsoft.MRZScanner({
153153
},
154154
resultViewConfig: {
155155
showOriginalImage: false, // hides the cropped image of the MRZ document in the result view; true by default
156-
allowResultEditing: false, // disables the ability to edit the result fields should the parsed information not match the MRZ document; true by default
156+
allowResultEditing: true, // enables the ability to edit the result fields should the parsed information not match the MRZ document; false by default
157157
toolbarButtonsConfig: {
158158
retake: {
159159
icon: "path to a png/svg file" // Changes the icon image of the retake button
@@ -192,4 +192,30 @@ const mrzScanner = new Dynamsoft.MRZScanner({
192192
});
193193
```
194194

195-
Here, when the user clicks *Done*, the application prints the result status code, status message, and the first name from the scanned document to the console. The `MRZResult` object (named `result` in the sample) contains each parsed text field, the full MRZ text string, and the cropped image of the scanned MRZ document. You web application can rely on the MRZ Scanner to parse the MRZ string and easily use MRZ fields using the `result.data.{fieldName}` scheme as shown above.
195+
Here, when the user clicks *Done*, the application prints the result status code, status message, and the first name from the scanned document to the console. The `MRZResult` object (named `result` in the sample) contains each parsed text field, the full MRZ text string, and the cropped image of the scanned MRZ document. You web application can rely on the MRZ Scanner to parse the MRZ string and easily use MRZ fields using the `result.data.{fieldName}` scheme as shown above.
196+
197+
### Enable Result Editing
198+
199+
There could be certain cases where the parsed fields in the final **MRZResultView** do not pass validation as they fail the check digit step of the parsing process. To better deal with those cases, the MRZ Scanner has the feature to allow the user to edit the result fields directly.
200+
201+
By enabling this feature, users can verify the parsed information provided by the MRZ Scanner is correct compared to the information present on the MRZ document. This feature acts as a sort of safety net for any results that don't pass the validation check or if the user just wants to make sure that the parsed information from the MRZ matches the information on the MRZ document.
202+
203+
```ts
204+
const mrzScanner = new Dynamsoft.MRZScanner({
205+
license: "YOUR_LICENSE_KEY_HERE",
206+
scannerViewConfig: {
207+
/* see the MRZScannerViewConfig section to learn how to set this */
208+
},
209+
resultViewConfig: {
210+
allowResultEditing: false,
211+
}
212+
});
213+
```
214+
215+
By changing *allowResultEditing* in the `resultViewConfig`, the user will now see a slightly different UI in the result view. Below is a screenshot showing the UI difference
216+
217+
<div align="center">
218+
<img src="../assets/imgs/ResultEditUI-MRZ.png" alt="MRZ Result View Editing Feature" width="70%" />
219+
</div>
220+
221+
As you can see above, when result editing is enabled, the result fields will change into editable fields like in a form.

guides/mrz-scanner.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ Let's now go through the code of the Hello World sample to understand how the co
168168
</html>
169169
```
170170
171-
The first step in setting up the HTML in the Hello World project is to include the SDK. (We discussed the two available methods to include the SDK resources in the earlier section [Quick Start](#quick-start---hello-world) section) In this example, we include the precompiled MRZ Scanner SDK script via CDN in the header:
171+
The first step in setting up the HTML in the Hello World project is to include the SDK. (We discussed the two available methods to include the SDK resources in the earlier [Quick Start](#quick-start---hello-world) section) In this example, we include the precompiled MRZ Scanner SDK script via CDN in the header:
172172
173173
MRZ Scanner comes with a **Ready-to-Use UI**. When the MRZ Scanner launches, it creates a container which it populates with the **Ready-to-Use UI**.
174174

0 commit comments

Comments
 (0)