├── README.md └── examples ├── 9.x ├── barcode-reader.html ├── barcode-result-overlay.html ├── dbr-scanner-wrapper.js ├── dbr-scanner-wrapper.ts ├── driver_license │ ├── README.md │ ├── driverlicense.js │ └── index.html ├── hello-world.html ├── manually-load.html ├── overlay.js ├── pwa │ ├── README.md │ ├── favicon.ico │ ├── icons │ │ ├── icon-128.png │ │ ├── icon-144.png │ │ ├── icon-152.png │ │ ├── icon-192.png │ │ ├── icon-256.png │ │ └── icon-32.png │ ├── index.html │ ├── manifest.json │ ├── overlay.js │ ├── service-worker.js │ └── style.css ├── qr-code-scanner.html ├── salesforce_visualforce_page │ ├── .eslintignore │ ├── .forceignore │ ├── .gitignore │ ├── .prettierignore │ ├── .prettierrc │ ├── .vscode │ │ ├── extensions.json │ │ ├── launch.json │ │ └── settings.json │ ├── README.md │ ├── config │ │ └── project-scratch-def.json │ ├── force-app │ │ └── main │ │ │ └── default │ │ │ ├── aura │ │ │ └── .eslintrc.json │ │ │ ├── lwc │ │ │ └── .eslintrc.json │ │ │ └── pages │ │ │ ├── DecodeFile.html │ │ │ ├── DecodeFile.page │ │ │ ├── DecodeFile.page-meta.xml │ │ │ ├── DecodeVideo.html │ │ │ ├── DecodeVideo.page │ │ │ └── DecodeVideo.page-meta.xml │ ├── package.json │ ├── scripts │ │ ├── apex │ │ │ └── hello.apex │ │ └── soql │ │ │ └── account.soql │ └── sfdx-project.json ├── ui-customization.html ├── webgl │ ├── README.md │ ├── grayscale-image │ │ ├── 640x480.jpg │ │ └── index.html │ ├── index.html │ ├── loading.gif │ ├── m4.js │ ├── util.js │ └── webgl-utils.js └── wrapper-test.html ├── aadhaar_card └── index.html ├── barcode_mrz_document ├── README.md ├── default.png ├── full.json ├── index.html ├── main.js ├── styles.css └── utils.js ├── barcode_ocr_text ├── index.html ├── main.css ├── main.js └── template.json ├── camera_only ├── README.md └── index.html ├── mrz-vin-scanner ├── README.md ├── default.png ├── full.json ├── index.html ├── main.js ├── mrz.json ├── styles.css └── vin.json └── mrz_scanner_rtu ├── README.md ├── helloworld.html ├── index.html └── main.css /README.md: -------------------------------------------------------------------------------- 1 | # Scan 1D/2D Barcode, MRZ and Documents in JavaScript 2 | This repository contains **JavaScript** examples demonstrating how to use [Dynamsoft Capture Vision](https://www.npmjs.com/package/dynamsoft-capture-vision-bundle) to build web applications for scanning **1D/2D barcodes**, **MRZ**, and **documents**. 3 | 4 | ## Prerequisites 5 | - Obtain a [30-day trial license](https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform). 6 | 7 | ## Try Examples 8 | - [barcode-reader.html](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/barcode-reader.html) 9 | - [barcode-result-overlay.html](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/barcode-result-overlay.html) 10 | - [hello-world.html](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/hello-world.html) 11 | - [manually-load.html](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/manually-load.html) 12 | - [qr-code-scanner.html](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/qr-code-scanner.html) 13 | - [ui-customization.html](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/ui-customization.html) 14 | - [wrapper-test.html](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/wrapper-test.html) 15 | 16 | Build the TypeScript file: 17 | 18 | ```bash 19 | tsc --target ES5 dbr-scanner-wrapper.ts 20 | ``` 21 | 22 | - [WebGL](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/webgl/) 23 | - [Driver License PDF417 Scanner](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/driver_license/) 24 | - [Scan 1D Barcode and OCR Text](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/barcode_ocr_text) 25 | - [Detect Barcode, MRZ and Document](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/barcode_mrz_document/) 26 | - [Aadhaar Card](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/aadhaar_card/) 27 | 28 | ## Blog 29 | - [How to Use WebGL to Accelerate Web Barcode and QR Code Decoding Speed](https://www.dynamsoft.com/codepool/webgl-accelerate-web-barcode-decoding-speed.html) 30 | - [Build a Barcode Scanner Using JavaScript and HTML5](https://www.dynamsoft.com/codepool/html5-barcode-reader-javascript-webassembly.html) 31 | - [Reading Driver’s License Information from PDF417 in JavaScript](https://www.dynamsoft.com/codepool/javascript-driver-license-pdf417-web.html) 32 | -------------------------------------------------------------------------------- /examples/9.x/barcode-reader.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dynamsoft JavaScript Barcode Reader 8 | 9 | 10 | 67 | 68 | 69 | 70 |
71 |

Parameter Panel

72 | Online 73 | Documentation 74 | 75 | 76 |
77 | 78 | 80 | 81 |
82 |
83 |
84 |

Image Panel

85 | Loading Library... 86 |
87 | 88 | 89 |
90 | 91 |
92 | 93 |
94 | 95 | 96 |
97 | 98 | 99 |
100 | 101 | 102 | 103 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /examples/9.x/barcode-result-overlay.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dynamsoft JavaScript Barcode Scanner 8 | 9 | 10 | 47 | 48 | 49 | 50 |
51 | Barcode Result: N/A 52 |
53 |
54 | Loading Library... 55 |
56 | 57 |
58 | 59 | 60 |
61 | 62 |
63 |
64 | 65 |
66 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /examples/9.x/dbr-scanner-wrapper.js: -------------------------------------------------------------------------------- 1 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 2 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | var __generator = (this && this.__generator) || function (thisArg, body) { 11 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 12 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 13 | function verb(n) { return function (v) { return step([n, v]); }; } 14 | function step(op) { 15 | if (f) throw new TypeError("Generator is already executing."); 16 | while (_) try { 17 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 18 | if (y = 0, t) op = [op[0] & 2, t.value]; 19 | switch (op[0]) { 20 | case 0: case 1: t = op; break; 21 | case 4: _.label++; return { value: op[1], done: false }; 22 | case 5: _.label++; y = op[1]; op = [0]; continue; 23 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 24 | default: 25 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 26 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 27 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 28 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 29 | if (t[2]) _.ops.pop(); 30 | _.trys.pop(); continue; 31 | } 32 | op = body.call(thisArg, _); 33 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 34 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 35 | } 36 | }; 37 | var DBRWrapper = /** @class */ (function () { 38 | function DBRWrapper() { 39 | try { 40 | this.scanner = null; 41 | this.videoContainer = null; 42 | this.cameraSourceElement = null; 43 | this.cameraViewElement = null; 44 | this.overlay = null; 45 | this.context = null; 46 | this.selectElement = null; 47 | this.cameraInfo = {}; 48 | this.openCamera = this.openCamera.bind(this); 49 | this.onCameraReady = this.onCameraReady.bind(this); 50 | } 51 | catch (ex) { 52 | alert(ex.message); 53 | throw ex; 54 | } 55 | } 56 | DBRWrapper.createInstance = function () { 57 | return new DBRWrapper(); 58 | }; 59 | DBRWrapper.prototype.createCustomScanner = function (callback) { 60 | return __awaiter(this, void 0, void 0, function () { 61 | var _a, cameras; 62 | var _this = this; 63 | return __generator(this, function (_b) { 64 | switch (_b.label) { 65 | case 0: 66 | this.initCameraSource(); 67 | this.initCameraView(); 68 | return [4 /*yield*/, Dynamsoft.DBR.BarcodeScanner.loadWasm()]; 69 | case 1: 70 | _b.sent(); 71 | _a = this; 72 | return [4 /*yield*/, Dynamsoft.DBR.BarcodeScanner.createInstance()]; 73 | case 2: 74 | _a.scanner = _b.sent(); 75 | return [4 /*yield*/, this.scanner.updateRuntimeSettings("speed")]; 76 | case 3: 77 | _b.sent(); 78 | return [4 /*yield*/, this.scanner.setUIElement(this.videoContainer)]; 79 | case 4: 80 | _b.sent(); 81 | return [4 /*yield*/, this.scanner.getAllCameras()]; 82 | case 5: 83 | cameras = _b.sent(); 84 | this.appendCameraSource(cameras); 85 | return [4 /*yield*/, this.openCamera()]; 86 | case 6: 87 | _b.sent(); 88 | this.scanner.onFrameRead = function (results) { 89 | _this.clearOverlay(); 90 | var txts = []; 91 | var localization; 92 | if (results.length > 0) { 93 | for (var i = 0; i < results.length; ++i) { 94 | txts.push(results[i].barcodeText); 95 | localization = results[i].localizationResult; 96 | _this.drawOverlay(localization, results[i].barcodeText); 97 | } 98 | if (callback) { 99 | callback(txts.join(', ')); 100 | } 101 | } 102 | else { 103 | if (callback) { 104 | callback("No barcode found"); 105 | } 106 | } 107 | }; 108 | this.scanner.onUnduplicatedRead = function (txt, result) { }; 109 | this.scanner.onPlayed = this.onCameraReady; 110 | return [2 /*return*/, this.scanner]; 111 | } 112 | }); 113 | }); 114 | }; 115 | DBRWrapper.prototype.createDefaultScanner = function (callback) { 116 | return __awaiter(this, void 0, void 0, function () { 117 | var _a; 118 | var _this = this; 119 | return __generator(this, function (_b) { 120 | switch (_b.label) { 121 | case 0: 122 | _a = this; 123 | return [4 /*yield*/, Dynamsoft.DBR.BarcodeScanner.createInstance()]; 124 | case 1: 125 | _a.scanner = _b.sent(); 126 | return [4 /*yield*/, this.scanner.updateRuntimeSettings("speed")]; 127 | case 2: 128 | _b.sent(); 129 | this.scanner.onFrameRead = function (results) { 130 | _this.clearOverlay(); 131 | var txts = []; 132 | var localization; 133 | if (results.length > 0) { 134 | for (var i = 0; i < results.length; ++i) { 135 | txts.push(results[i].barcodeText); 136 | localization = results[i].localizationResult; 137 | _this.drawOverlay(localization, results[i].barcodeText); 138 | } 139 | } 140 | if (callback) { 141 | callback(results); 142 | } 143 | }; 144 | this.scanner.onUnduplicatedRead = function (txt, result) { }; 145 | this.scanner.onPlayed = this.onCameraReady; 146 | return [2 /*return*/, this.scanner]; 147 | } 148 | }); 149 | }); 150 | }; 151 | DBRWrapper.prototype.patchOverlay = function () { 152 | var containers = document.getElementsByClassName("dce-video-container"); 153 | if (containers == null || containers.length == 0) { 154 | return; 155 | } 156 | // Always select last element. 157 | var container = document.getElementsByClassName("dce-video-container")[containers.length - 1]; 158 | var lastElement = container.lastElementChild; 159 | if (lastElement && lastElement.id === "custom-overlay") 160 | container.removeChild(lastElement); 161 | this.overlay = document.createElement('canvas'); 162 | this.overlay.id = "custom-overlay"; 163 | this.overlay.style.position = 'absolute'; 164 | this.overlay.style.top = '0'; 165 | this.overlay.style.left = '0'; 166 | // this.overlay.style.zIndex = '2'; 167 | this.overlay.style.width = '100%'; 168 | this.overlay.style.height = '100%'; 169 | this.overlay.style.objectFit = 'contain'; 170 | this.context = this.overlay.getContext('2d'); 171 | container.appendChild(this.overlay); 172 | }; 173 | DBRWrapper.prototype.appendCameraSource = function (deviceInfos) { 174 | for (var i = 0; i < deviceInfos.length; ++i) { 175 | var deviceInfo = deviceInfos[i]; 176 | var option = document.createElement('option'); 177 | option.value = deviceInfo.deviceId; 178 | option.text = deviceInfo.label; 179 | this.cameraInfo[deviceInfo.deviceId] = deviceInfo; 180 | this.selectElement.appendChild(option); 181 | } 182 | }; 183 | DBRWrapper.prototype.initCameraSource = function () { 184 | this.cameraSourceElement = document.createElement('div'); 185 | this.selectElement = document.createElement('select'); 186 | this.selectElement.onchange = this.openCamera; 187 | this.cameraSourceElement.appendChild(this.selectElement); 188 | }; 189 | DBRWrapper.prototype.onCameraReady = function () { 190 | var resolution = this.scanner.getResolution(); 191 | this.updateOverlay(resolution[0], resolution[1]); 192 | }; 193 | DBRWrapper.prototype.openCamera = function () { 194 | return __awaiter(this, void 0, void 0, function () { 195 | var deviceId; 196 | return __generator(this, function (_a) { 197 | switch (_a.label) { 198 | case 0: 199 | this.clearOverlay(); 200 | deviceId = this.selectElement.value; 201 | if (!this.scanner) return [3 /*break*/, 2]; 202 | return [4 /*yield*/, this.scanner.setCurrentCamera(this.cameraInfo[deviceId])]; 203 | case 1: 204 | _a.sent(); 205 | _a.label = 2; 206 | case 2: return [2 /*return*/]; 207 | } 208 | }); 209 | }); 210 | }; 211 | DBRWrapper.prototype.initCameraView = function () { 212 | this.cameraViewElement = document.createElement('div'); 213 | this.cameraViewElement.style.position = 'relative'; 214 | this.cameraViewElement.style.width = '100vw'; 215 | this.cameraViewElement.style.height = '100vh'; 216 | this.videoContainer = document.createElement('div'); 217 | this.videoContainer.style.position = 'relative'; 218 | this.videoContainer.style.width = '100%'; 219 | this.videoContainer.style.height = '100%'; 220 | this.videoContainer.style.zIndex = '1'; 221 | this.videoContainer.className = "dce-video-container"; 222 | this.cameraViewElement.appendChild(this.videoContainer); 223 | this.overlay = document.createElement('canvas'); 224 | this.overlay.style.position = 'absolute'; 225 | this.overlay.style.top = '0'; 226 | this.overlay.style.left = '0'; 227 | this.overlay.style.zIndex = '2'; 228 | this.overlay.style.width = '100%'; 229 | this.overlay.style.height = '100%'; 230 | this.overlay.style.objectFit = 'contain'; 231 | this.context = this.overlay.getContext('2d'); 232 | this.cameraViewElement.appendChild(this.overlay); 233 | }; 234 | DBRWrapper.prototype.getCameraSource = function () { 235 | return this.cameraSourceElement; 236 | }; 237 | DBRWrapper.prototype.getCameraView = function () { 238 | return this.cameraViewElement; 239 | }; 240 | DBRWrapper.prototype.updateOverlay = function (width, height) { 241 | if (this.overlay) { 242 | this.overlay.width = width; 243 | this.overlay.height = height; 244 | this.clearOverlay(); 245 | } 246 | }; 247 | DBRWrapper.prototype.clearOverlay = function () { 248 | if (this.context) { 249 | this.context.clearRect(0, 0, this.overlay.width, this.overlay.height); 250 | this.context.strokeStyle = '#ff0000'; 251 | this.context.lineWidth = 5; 252 | } 253 | }; 254 | DBRWrapper.prototype.drawOverlay = function (localization, text) { 255 | if (this.context) { 256 | this.context.beginPath(); 257 | this.context.moveTo(localization.x1, localization.y1); 258 | this.context.lineTo(localization.x2, localization.y2); 259 | this.context.lineTo(localization.x3, localization.y3); 260 | this.context.lineTo(localization.x4, localization.y4); 261 | this.context.lineTo(localization.x1, localization.y1); 262 | this.context.stroke(); 263 | this.context.font = '18px Verdana'; 264 | this.context.fillStyle = '#ff0000'; 265 | var x = [localization.x1, localization.x2, localization.x3, localization.x4]; 266 | var y = [localization.y1, localization.y2, localization.y3, localization.y4]; 267 | x.sort(function (a, b) { 268 | return a - b; 269 | }); 270 | y.sort(function (a, b) { 271 | return b - a; 272 | }); 273 | var left = x[0]; 274 | var top_1 = y[0]; 275 | this.context.fillText(text, left, top_1 + 50); 276 | } 277 | }; 278 | DBRWrapper.prototype.showOverlay = function () { 279 | this.overlay.style.display = 'block'; 280 | document.getElementsByClassName('cvs-scan-region-overlay-0')[0].style.display = 'block'; 281 | }; 282 | DBRWrapper.prototype.hideOverlay = function () { 283 | this.overlay.style.display = 'none'; 284 | document.getElementsByClassName('cvs-scan-region-overlay-0')[0].style.display = 'none'; 285 | }; 286 | DBRWrapper.prototype.showCamera = function () { 287 | if (this.scanner) { 288 | this.scanner.show(); 289 | } 290 | }; 291 | DBRWrapper.prototype.hideCamera = function () { 292 | if (this.scanner) { 293 | this.scanner.hide(); 294 | } 295 | }; 296 | // Dynamically load Dynamsoft Barcode Reader JS library 297 | DBRWrapper.prototype.loadDBR = function (callback) { 298 | var script = document.createElement('script'); 299 | script.src = "https://cdn.jsdelivr.net/npm/dynamsoft-javascript-barcode@9.0.2/dist/dbr.js"; 300 | script.onload = function () { 301 | callback(Dynamsoft); 302 | }; 303 | document.head.appendChild(script); 304 | }; 305 | DBRWrapper.prototype.constructView = function () { 306 | document.body.appendChild(this.getCameraSource()); 307 | document.body.appendChild(this.getCameraView()); 308 | }; 309 | return DBRWrapper; 310 | }()); 311 | -------------------------------------------------------------------------------- /examples/9.x/dbr-scanner-wrapper.ts: -------------------------------------------------------------------------------- 1 | class DBRWrapper { 2 | private scanner: Dynamsoft.DBR.BarcodeScanner; 3 | private videoContainer: HTMLDivElement; 4 | private cameraSourceElement: HTMLDivElement; 5 | private cameraViewElement: HTMLDivElement; 6 | private overlay: HTMLCanvasElement; 7 | private context: CanvasRenderingContext2D; 8 | private selectElement: HTMLSelectElement; 9 | private cameraInfo: any; 10 | 11 | constructor() { 12 | try { 13 | this.scanner = null; 14 | this.videoContainer = null; 15 | this.cameraSourceElement = null; 16 | this.cameraViewElement = null; 17 | this.overlay = null; 18 | this.context = null; 19 | this.selectElement = null; 20 | this.cameraInfo = {}; 21 | this.openCamera = this.openCamera.bind(this); 22 | this.onCameraReady = this.onCameraReady.bind(this); 23 | } 24 | catch (ex) { 25 | alert(ex.message); 26 | throw ex; 27 | } 28 | } 29 | 30 | async createCustomScanner(callback) { 31 | this.initCameraSource(); 32 | this.initCameraView(); 33 | 34 | await Dynamsoft.DBR.BarcodeScanner.loadWasm(); 35 | this.scanner = await Dynamsoft.DBR.BarcodeScanner.createInstance(); 36 | await this.scanner.updateRuntimeSettings("speed"); 37 | await this.scanner.setUIElement(this.videoContainer); 38 | let cameras = await this.scanner.getAllCameras(); 39 | this.appendCameraSource(cameras); 40 | await this.openCamera(); 41 | this.scanner.onFrameRead = results => { 42 | this.clearOverlay(); 43 | 44 | let txts = []; 45 | let localization; 46 | if (results.length > 0) { 47 | for (var i = 0; i < results.length; ++i) { 48 | txts.push(results[i].barcodeText); 49 | localization = results[i].localizationResult; 50 | this.drawOverlay(localization, results[i].barcodeText); 51 | } 52 | 53 | if (callback) { 54 | callback(txts.join(', ')); 55 | } 56 | } 57 | else { 58 | if (callback) { 59 | callback("No barcode found"); 60 | } 61 | } 62 | }; 63 | this.scanner.onUnduplicatedRead = (txt, result) => { }; 64 | this.scanner.onPlayed = this.onCameraReady; 65 | return this.scanner; 66 | } 67 | 68 | async createDefaultScanner(callback) { 69 | this.scanner = await Dynamsoft.DBR.BarcodeScanner.createInstance(); 70 | await this.scanner.updateRuntimeSettings("speed"); 71 | this.scanner.onFrameRead = results => { 72 | this.clearOverlay(); 73 | 74 | let txts = []; 75 | let localization; 76 | if (results.length > 0) { 77 | for (var i = 0; i < results.length; ++i) { 78 | txts.push(results[i].barcodeText); 79 | localization = results[i].localizationResult; 80 | this.drawOverlay(localization, results[i].barcodeText); 81 | } 82 | } 83 | 84 | if (callback) { 85 | callback(results); 86 | } 87 | }; 88 | this.scanner.onUnduplicatedRead = (txt, result) => { }; 89 | this.scanner.onPlayed = this.onCameraReady; 90 | return this.scanner; 91 | } 92 | 93 | patchOverlay() { 94 | let containers = document.getElementsByClassName("dce-video-container"); 95 | 96 | if (containers == null || containers.length == 0) { 97 | return; 98 | } 99 | 100 | // Always select last element. 101 | let container = document.getElementsByClassName("dce-video-container")[containers.length - 1]; 102 | let lastElement = container.lastElementChild; 103 | 104 | if (lastElement && lastElement.id === "custom-overlay") 105 | container.removeChild(lastElement); 106 | 107 | this.overlay = document.createElement('canvas'); 108 | this.overlay.id = "custom-overlay"; 109 | this.overlay.style.position = 'absolute'; 110 | this.overlay.style.top = '0'; 111 | this.overlay.style.left = '0'; 112 | // this.overlay.style.zIndex = '2'; 113 | this.overlay.style.width = '100%'; 114 | this.overlay.style.height = '100%'; 115 | this.overlay.style.objectFit = 'contain'; 116 | this.context = this.overlay.getContext('2d'); 117 | container.appendChild(this.overlay); 118 | } 119 | 120 | appendCameraSource(deviceInfos) { 121 | for (var i = 0; i < deviceInfos.length; ++i) { 122 | var deviceInfo = deviceInfos[i]; 123 | var option = document.createElement('option'); 124 | option.value = deviceInfo.deviceId; 125 | option.text = deviceInfo.label; 126 | this.cameraInfo[deviceInfo.deviceId] = deviceInfo; 127 | this.selectElement.appendChild(option); 128 | } 129 | } 130 | 131 | initCameraSource() { 132 | this.cameraSourceElement = document.createElement('div'); 133 | this.selectElement = document.createElement('select'); 134 | this.selectElement.onchange = this.openCamera; 135 | this.cameraSourceElement.appendChild(this.selectElement); 136 | } 137 | 138 | onCameraReady() { 139 | let resolution = this.scanner.getResolution(); 140 | this.updateOverlay(resolution[0], resolution[1]); 141 | } 142 | 143 | async openCamera() { 144 | this.clearOverlay(); 145 | let deviceId = this.selectElement.value; 146 | if (this.scanner) { 147 | await this.scanner.setCurrentCamera(this.cameraInfo[deviceId]); 148 | } 149 | } 150 | 151 | initCameraView() { 152 | this.cameraViewElement = document.createElement('div'); 153 | this.cameraViewElement.style.position = 'relative'; 154 | this.cameraViewElement.style.width = '100vw'; 155 | this.cameraViewElement.style.height = '100vh'; 156 | 157 | this.videoContainer = document.createElement('div'); 158 | this.videoContainer.style.position = 'relative'; 159 | this.videoContainer.style.width = '100%'; 160 | this.videoContainer.style.height = '100%'; 161 | this.videoContainer.style.zIndex = '1'; 162 | this.videoContainer.className = "dce-video-container"; 163 | this.cameraViewElement.appendChild(this.videoContainer); 164 | 165 | this.overlay = document.createElement('canvas'); 166 | this.overlay.style.position = 'absolute'; 167 | this.overlay.style.top = '0'; 168 | this.overlay.style.left = '0'; 169 | this.overlay.style.zIndex = '2'; 170 | this.overlay.style.width = '100%'; 171 | this.overlay.style.height = '100%'; 172 | this.overlay.style.objectFit = 'contain'; 173 | this.context = this.overlay.getContext('2d'); 174 | 175 | this.cameraViewElement.appendChild(this.overlay); 176 | } 177 | 178 | getCameraSource() { 179 | return this.cameraSourceElement; 180 | } 181 | 182 | getCameraView() { 183 | return this.cameraViewElement; 184 | } 185 | 186 | updateOverlay(width, height) { 187 | if (this.overlay) { 188 | this.overlay.width = width; 189 | this.overlay.height = height; 190 | this.clearOverlay(); 191 | } 192 | } 193 | 194 | clearOverlay() { 195 | if (this.context) { 196 | this.context.clearRect(0, 0, this.overlay.width, this.overlay.height); 197 | this.context.strokeStyle = '#ff0000'; 198 | this.context.lineWidth = 5; 199 | } 200 | } 201 | 202 | drawOverlay(localization, text) { 203 | if (this.context) { 204 | this.context.beginPath(); 205 | this.context.moveTo(localization.x1, localization.y1); 206 | this.context.lineTo(localization.x2, localization.y2); 207 | this.context.lineTo(localization.x3, localization.y3); 208 | this.context.lineTo(localization.x4, localization.y4); 209 | this.context.lineTo(localization.x1, localization.y1); 210 | this.context.stroke(); 211 | 212 | this.context.font = '18px Verdana'; 213 | this.context.fillStyle = '#ff0000'; 214 | let x = [localization.x1, localization.x2, localization.x3, localization.x4]; 215 | let y = [localization.y1, localization.y2, localization.y3, localization.y4]; 216 | x.sort(function (a, b) { 217 | return a - b; 218 | }); 219 | y.sort(function (a, b) { 220 | return b - a; 221 | }); 222 | let left = x[0]; 223 | let top = y[0]; 224 | 225 | this.context.fillText(text, left, top + 50); 226 | } 227 | } 228 | 229 | showOverlay() { 230 | this.overlay.style.display = 'block'; 231 | document.getElementsByClassName('cvs-scan-region-overlay-0')[0].style.display = 'block'; 232 | } 233 | 234 | hideOverlay() { 235 | this.overlay.style.display = 'none'; 236 | document.getElementsByClassName('cvs-scan-region-overlay-0')[0].style.display = 'none'; 237 | } 238 | 239 | showCamera() { 240 | if (this.scanner) { 241 | this.scanner.show(); 242 | } 243 | } 244 | 245 | hideCamera() { 246 | if (this.scanner) { 247 | this.scanner.hide(); 248 | } 249 | } 250 | 251 | static createInstance() : DBRWrapper { 252 | return new DBRWrapper(); 253 | } 254 | 255 | // Dynamically load Dynamsoft Barcode Reader JS library 256 | loadDBR(callback) { 257 | let script = document.createElement('script'); 258 | script.src = "https://cdn.jsdelivr.net/npm/dynamsoft-javascript-barcode@9.0.2/dist/dbr.js"; 259 | script.onload = function () { 260 | callback(Dynamsoft); 261 | }; 262 | document.head.appendChild(script); 263 | } 264 | 265 | constructView() { 266 | document.body.appendChild(this.getCameraSource()); 267 | document.body.appendChild(this.getCameraView()); 268 | } 269 | } -------------------------------------------------------------------------------- /examples/9.x/driver_license/README.md: -------------------------------------------------------------------------------- 1 | # Driver License PDF417 Scanner in JavaScript 2 | This sample demonstrates how to read and extract driver's license information from PDF417 barcodes using the Dynamsoft [JavaScript barcode SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/). 3 | 4 | ## Usage 5 | 1. Obtain a [free trial license](https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform) and update the following code: 6 | 7 | ```js 8 | Dynamsoft.DBR.BarcodeReader.license = "LICENSE-KEY"; 9 | ``` 10 | 11 | 2. Deploy the project to a web server and then open the driver's license scanner in a web browser: 12 | 13 | ```bash 14 | python -m http.server 15 | ``` 16 | 17 | ![JavaScript driver's license](https://www.dynamsoft.com/codepool/wp-content/uploads/2020/06/javascript-driver-license.png) 18 | 19 | ## Online Demo 20 | [https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/driver_license/](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/driver_license/) 21 | 22 | ## References 23 | - https://www.aamva.org/DL-ID-Card-Design-Standard/ 24 | - https://github.com/Dynamsoft/javascript-barcode/tree/master/example/web/decode-driver-license-for-AAMVA 25 | 26 | ## Blog 27 | [Reading Driver’s License Information from PDF417 in JavaScript](https://www.dynamsoft.com/codepool/javascript-driver-license-pdf417-web.html) 28 | -------------------------------------------------------------------------------- /examples/9.x/driver_license/driverlicense.js: -------------------------------------------------------------------------------- 1 | // AAMVA2016, driver license abbreviation-description map 2 | const DLAbbrDesMap = { 3 | 'DCA': 'Jurisdiction-specific vehicle class', 4 | 'DBA': 'Expiry Date', 5 | 'DCS': 'Last Name', 6 | 'DAC': 'First Name', 7 | 'DBD': 'Issue Date', 8 | 'DBB': 'Birth Date', 9 | 'DBC': 'Gender', 10 | 'DAY': 'Eye Color', 11 | 'DAU': 'Height', 12 | 'DAG': 'Street', 13 | 'DAI': 'City', 14 | 'DAJ': 'State', 15 | 'DAK': 'Zip', 16 | 'DAQ': 'License Number', 17 | 'DCF': 'Document Discriminator', 18 | 'DCG': 'Issue Country', 19 | 'DAH': 'Street 2', 20 | 'DAZ': 'Hair Color', 21 | 'DCI': 'Place of birth', 22 | 'DCJ': 'Audit information', 23 | 'DCK': 'Inventory Control Number', 24 | 'DBN': 'Alias / AKA Family Name', 25 | 'DBG': 'Alias / AKA Given Name', 26 | 'DBS': 'Alias / AKA Suffix Name', 27 | 'DCU': 'Name Suffix', 28 | 'DCE': 'Physical Description Weight Range', 29 | 'DCL': 'Race / Ethnicity', 30 | 'DCM': 'Standard vehicle classification', 31 | 'DCN': 'Standard endorsement code', 32 | 'DCO': 'Standard restriction code', 33 | 'DCP': 'Jurisdiction-specific vehicle classification description', 34 | 'DCQ': 'Jurisdiction-specific endorsement code description', 35 | 'DCR': 'Jurisdiction-specific restriction code description', 36 | 'DDA': 'Compliance Type', 37 | 'DDB': 'Card Revision Date', 38 | 'DDC': 'HazMat Endorsement Expiration Date', 39 | 'DDD': 'Limited Duration Document Indicator', 40 | 'DAW': 'Weight(pounds)', 41 | 'DAX': 'Weight(kilograms)', 42 | 'DDH': 'Under 18 Until', 43 | 'DDI': 'Under 19 Until', 44 | 'DDJ': 'Under 21 Until', 45 | 'DDK': 'Organ Donor Indicator', 46 | 'DDL': 'Veteran Indicator', 47 | // old standard 48 | 'DAA': 'Customer Full Name', 49 | 'DAB': 'Customer Last Name', 50 | 'DAE': 'Name Suffix', 51 | 'DAF': 'Name Prefix', 52 | 'DAL': 'Residence Street Address1', 53 | 'DAM': 'Residence Street Address2', 54 | 'DAN': 'Residence City', 55 | 'DAO': 'Residence Jurisdiction Code', 56 | 'DAR': 'License Classification Code', 57 | 'DAS': 'License Restriction Code', 58 | 'DAT': 'License Endorsements Code', 59 | 'DAV': 'Height in CM', 60 | 'DBE': 'Issue Timestamp', 61 | 'DBF': 'Number of Duplicates', 62 | 'DBH': 'Organ Donor', 63 | 'DBI': 'Non-Resident Indicator', 64 | 'DBJ': 'Unique Customer Identifier', 65 | 'DBK': 'Social Security Number', 66 | 'DBM': 'Social Security Number', 67 | 'DCH': 'Federal Commercial Vehicle Codes', 68 | 'DBR': 'Name Suffix', 69 | 'PAA': 'Permit Classification Code', 70 | 'PAB': 'Permit Expiration Date', 71 | 'PAC': 'Permit Identifier', 72 | 'PAD': 'Permit IssueDate', 73 | 'PAE': 'Permit Restriction Code', 74 | 'PAF': 'Permit Endorsement Code', 75 | 'ZVA': 'Court Restriction Code', 76 | 'DAD': 'Middle Name' 77 | }; 78 | 79 | // Get driver license abbreviation-content map from raw txt 80 | var parseDriverLicense = txt => { 81 | console.log(txt); 82 | let lines = txt.split('\n'); 83 | let abbrs = Object.keys(DLAbbrDesMap); 84 | let map = {}; 85 | lines.forEach((line, i) => { 86 | let abbr; 87 | let content; 88 | if(i === 1){ 89 | abbr = 'DAQ'; 90 | content = line.substring(line.indexOf(abbr) + 3); 91 | }else{ 92 | abbr = line.substring(0, 3); 93 | content = line.substring(3).trim(); 94 | } 95 | if(abbrs.includes(abbr)){ 96 | map[abbr] = { 97 | description: DLAbbrDesMap[abbr], 98 | content: content 99 | }; 100 | } 101 | }); 102 | return map; 103 | }; 104 | -------------------------------------------------------------------------------- /examples/9.x/driver_license/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 38 | 39 | 40 | 41 |
42 | Loading Library... 43 |
44 | 45 |
46 | 47 | 48 |
49 | 50 |
51 |
52 |
53 |
54 | 55 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /examples/9.x/hello-world.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dynamsoft JavaScript Barcode Scanner 8 | 9 | 10 | 11 | 12 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/9.x/manually-load.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dynamsoft JavaScript Barcode Scanner 8 | 9 | 10 | 11 | 12 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /examples/9.x/overlay.js: -------------------------------------------------------------------------------- 1 | var overlay = null; 2 | var context = null; 3 | 4 | function initOverlay(ol) { 5 | overlay = ol; 6 | context = overlay.getContext('2d'); 7 | } 8 | 9 | function updateOverlay(width, height) { 10 | if (overlay) { 11 | overlay.width = width; 12 | overlay.height = height; 13 | clearOverlay(); 14 | } 15 | } 16 | 17 | function clearOverlay() { 18 | if (context) { 19 | context.clearRect(0, 0, overlay.width, overlay.height); 20 | context.strokeStyle = '#ff0000'; 21 | context.lineWidth = 5; 22 | } 23 | } 24 | 25 | function drawOverlay(localization, text) { 26 | if (context) { 27 | context.beginPath(); 28 | context.moveTo(localization.x1, localization.y1); 29 | context.lineTo(localization.x2, localization.y2); 30 | context.lineTo(localization.x3, localization.y3); 31 | context.lineTo(localization.x4, localization.y4); 32 | context.lineTo(localization.x1, localization.y1); 33 | context.stroke(); 34 | 35 | context.font = '18px Verdana'; 36 | context.fillStyle = '#ff0000'; 37 | let x = [localization.x1, localization.x2, localization.x3, localization.x4]; 38 | let y = [localization.y1, localization.y2, localization.y3, localization.y4]; 39 | x.sort(function (a, b) { 40 | return a - b; 41 | }); 42 | y.sort(function (a, b) { 43 | return b - a; 44 | }); 45 | let left = x[0]; 46 | let top = y[0]; 47 | 48 | context.fillText(text, left, top + 50); 49 | } 50 | } 51 | 52 | function drawQuad(points) { 53 | if (context) { 54 | context.beginPath(); 55 | context.moveTo(points[0].x, points[0].y); 56 | context.lineTo(points[1].x, points[1].y); 57 | context.lineTo(points[2].x, points[2].y); 58 | context.lineTo(points[3].x, points[3].y); 59 | context.lineTo(points[0].x, points[0].y); 60 | context.stroke(); 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /examples/9.x/pwa/README.md: -------------------------------------------------------------------------------- 1 | # Barcode Reader PWA 2 | 3 | The sample demonstrates how to integrate [Dynamsoft JavaScript Barcode SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) into a progressive web app. 4 | 5 | ## License 6 | Get a [30-day FREE trial license](https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform). 7 | 8 | ## Usage 9 | 1. Set a valid license key: 10 | 11 | ```js 12 | Dynamsoft.DBR.BarcodeReader.license = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="; 13 | ``` 14 | 2. Deploy the PWA project to a web server. 15 | 16 | ![PWA barcode reader](https://www.codepool.biz/wp-content/uploads/2019/04/pwa-barcode-reader.gif) 17 | 18 | ## Online Demo 19 | https://yushulx.me/javascript-barcode-qr-code-scanner/pwa 20 | 21 | 22 | ## Blog 23 | [How to Build a Simple PWA Barcode Reader](https://www.codepool.biz/build-simple-pwa-barcode-reader.html) 24 | -------------------------------------------------------------------------------- /examples/9.x/pwa/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yushulx/javascript-barcode-qr-code-scanner/d11a6439fc2f877b450a15646ece21686c1b8462/examples/9.x/pwa/favicon.ico -------------------------------------------------------------------------------- /examples/9.x/pwa/icons/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yushulx/javascript-barcode-qr-code-scanner/d11a6439fc2f877b450a15646ece21686c1b8462/examples/9.x/pwa/icons/icon-128.png -------------------------------------------------------------------------------- /examples/9.x/pwa/icons/icon-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yushulx/javascript-barcode-qr-code-scanner/d11a6439fc2f877b450a15646ece21686c1b8462/examples/9.x/pwa/icons/icon-144.png -------------------------------------------------------------------------------- /examples/9.x/pwa/icons/icon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yushulx/javascript-barcode-qr-code-scanner/d11a6439fc2f877b450a15646ece21686c1b8462/examples/9.x/pwa/icons/icon-152.png -------------------------------------------------------------------------------- /examples/9.x/pwa/icons/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yushulx/javascript-barcode-qr-code-scanner/d11a6439fc2f877b450a15646ece21686c1b8462/examples/9.x/pwa/icons/icon-192.png -------------------------------------------------------------------------------- /examples/9.x/pwa/icons/icon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yushulx/javascript-barcode-qr-code-scanner/d11a6439fc2f877b450a15646ece21686c1b8462/examples/9.x/pwa/icons/icon-256.png -------------------------------------------------------------------------------- /examples/9.x/pwa/icons/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yushulx/javascript-barcode-qr-code-scanner/d11a6439fc2f877b450a15646ece21686c1b8462/examples/9.x/pwa/icons/icon-32.png -------------------------------------------------------------------------------- /examples/9.x/pwa/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Dynamsoft Barcode Reader 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | Barcode Result: N/A 24 |
25 |
26 | Loading Library... 27 |
28 | 29 |
30 | 31 | 32 |
33 | 34 |
35 |
36 | 37 |
38 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /examples/9.x/pwa/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BarcodeScanner", 3 | "short_name": "BarcodeScanner", 4 | "description": "A progressive web app for reading barcode and QR code.", 5 | "icons": [ 6 | { 7 | "src": "icons/icon-192.png", 8 | "sizes": "192x192", 9 | "type": "image/png" 10 | } 11 | ], 12 | "start_url": "./", 13 | "display": "standalone", 14 | "theme_color": "#2F3BA2", 15 | "background_color": "#3E4EB8" 16 | } -------------------------------------------------------------------------------- /examples/9.x/pwa/overlay.js: -------------------------------------------------------------------------------- 1 | var overlay = null; 2 | var context = null; 3 | 4 | function initOverlay(ol) { 5 | overlay = ol; 6 | context = overlay.getContext('2d'); 7 | } 8 | 9 | function updateOverlay(width, height) { 10 | if (overlay) { 11 | overlay.width = width; 12 | overlay.height = height; 13 | clearOverlay(); 14 | } 15 | } 16 | 17 | function clearOverlay() { 18 | if (context) { 19 | context.clearRect(0, 0, overlay.width, overlay.height); 20 | context.strokeStyle = '#ff0000'; 21 | context.lineWidth = 5; 22 | } 23 | } 24 | 25 | function drawOverlay(localization, text) { 26 | if (context) { 27 | context.beginPath(); 28 | context.moveTo(localization.x1, localization.y1); 29 | context.lineTo(localization.x2, localization.y2); 30 | context.lineTo(localization.x3, localization.y3); 31 | context.lineTo(localization.x4, localization.y4); 32 | context.lineTo(localization.x1, localization.y1); 33 | context.stroke(); 34 | 35 | context.font = '18px Verdana'; 36 | context.fillStyle = '#ff0000'; 37 | let x = [localization.x1, localization.x2, localization.x3, localization.x4]; 38 | let y = [localization.y1, localization.y2, localization.y3, localization.y4]; 39 | x.sort(function (a, b) { 40 | return a - b; 41 | }); 42 | y.sort(function (a, b) { 43 | return b - a; 44 | }); 45 | let left = x[0]; 46 | let top = y[0]; 47 | 48 | context.fillText(text, left, top + 50); 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /examples/9.x/pwa/service-worker.js: -------------------------------------------------------------------------------- 1 | self.addEventListener('fetch', event => { 2 | 3 | if (event.request.method !== 'GET') return; 4 | 5 | return; 6 | }); -------------------------------------------------------------------------------- /examples/9.x/pwa/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | } 6 | 7 | #videoview { 8 | position: relative; 9 | width: 90%; 10 | height: 64vh; 11 | } 12 | 13 | #videoContainer { 14 | position: relative; 15 | width: 100%; 16 | height: 100%; 17 | z-index: 1 18 | } 19 | 20 | #overlay { 21 | position: absolute; 22 | top: 0; 23 | left: 0; 24 | width: 100%; 25 | height: 100%; 26 | z-index: 2; 27 | object-fit: contain 28 | } -------------------------------------------------------------------------------- /examples/9.x/qr-code-scanner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dynamsoft JavaScript Barcode Scanner 8 | 9 | 10 | 47 | 48 | 49 | 50 |
51 | Barcode Result: N/A 52 |
53 |
54 | Loading Library... 55 |
56 | 57 |
58 | 59 | 60 |
61 | 62 |
63 |
64 | 65 |
66 | 67 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/.eslintignore: -------------------------------------------------------------------------------- 1 | **/lwc/**/*.css 2 | **/lwc/**/*.html 3 | **/lwc/**/*.json 4 | **/lwc/**/*.svg 5 | **/lwc/**/*.xml 6 | **/aura/**/*.auradoc 7 | **/aura/**/*.cmp 8 | **/aura/**/*.css 9 | **/aura/**/*.design 10 | **/aura/**/*.evt 11 | **/aura/**/*.json 12 | **/aura/**/*.svg 13 | **/aura/**/*.tokens 14 | **/aura/**/*.xml 15 | .sfdx -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/.forceignore: -------------------------------------------------------------------------------- 1 | # List files or directories below to ignore them when running force:source:push, force:source:pull, and force:source:status 2 | # More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm 3 | # 4 | 5 | package.xml 6 | 7 | # LWC configuration files 8 | **/jsconfig.json 9 | **/.eslintrc.json 10 | 11 | # LWC Jest 12 | **/__tests__/** -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used for Git repositories to specify intentionally untracked files that Git should ignore. 2 | # If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore 3 | # For useful gitignore templates see: https://github.com/github/gitignore 4 | 5 | # Salesforce cache 6 | .sfdx/ 7 | .localdevserver/ 8 | 9 | # LWC VSCode autocomplete 10 | **/lwc/jsconfig.json 11 | 12 | # LWC Jest coverage reports 13 | coverage/ 14 | 15 | # Logs 16 | logs 17 | *.log 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | # Dependency directories 23 | node_modules/ 24 | 25 | # Eslint cache 26 | .eslintcache 27 | 28 | # MacOS system files 29 | .DS_Store 30 | 31 | # Windows system files 32 | Thumbs.db 33 | ehthumbs.db 34 | [Dd]esktop.ini 35 | $RECYCLE.BIN/ 36 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/.prettierignore: -------------------------------------------------------------------------------- 1 | # List files or directories below to ignore them when running prettier 2 | # More information: https://prettier.io/docs/en/ignore.html 3 | # 4 | 5 | **/staticresources/** 6 | .localdevserver 7 | .sfdx 8 | .vscode 9 | 10 | coverage/ -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "overrides": [ 4 | { 5 | "files": "**/lwc/**/*.html", 6 | "options": { "parser": "lwc" } 7 | }, 8 | { 9 | "files": "*.{cmp,page,component}", 10 | "options": { "parser": "html" } 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "salesforce.salesforcedx-vscode", 4 | "redhat.vscode-xml", 5 | "dbaeumer.vscode-eslint", 6 | "esbenp.prettier-vscode" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch Apex Replay Debugger", 9 | "type": "apex-replay", 10 | "request": "launch", 11 | "logFile": "${command:AskForLogFileName}", 12 | "stopOnEntry": true, 13 | "trace": true 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "search.exclude": { 3 | "**/node_modules": true, 4 | "**/bower_components": true, 5 | "**/.sfdx": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/README.md: -------------------------------------------------------------------------------- 1 | # 1D/2D Barcode Detection in Salesforce Visualforce Page 2 | 3 | This sample demonstrates how to integrate the [Dynamsoft JavaScript Barcode SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) into **Salesforce Visualforce pages** for efficient barcode detection. 4 | 5 | ## Prerequisites 6 | - Obtain a [30-day FREE trial license](https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform) to try out the SDK. 7 | 8 | ## Getting Started 9 | Follow these steps to set up the project: 10 | 1. Open the project in Visual Studio Code. 11 | 2. Replace `LICENSE-KEY` with your own license key in the code: 12 | 13 | ```js 14 | Dynamsoft.DBR.BarcodeReader.license = "LICENSE-KEY"; 15 | ``` 16 | 3. Authorize the project within your Salesforce organization. 17 | 4. Deploy the source files to your Salesforce organization. 18 | 5. Test the barcode detection by previewing the Visualforce pages within the Salesforce environment. 19 | 20 | ![Salesforce barcode reader](https://www.dynamsoft.com/codepool/wp-content/uploads/2020/09/salesforce-barcode-reader.png) 21 | 22 | ![decode barcodes from camera video stream](https://www.dynamsoft.com/codepool/wp-content/uploads/2020/09/salesforce-decode-video.png) 23 | 24 | 25 | ## Blog 26 | [Step-by-Step Guide to Creating a Barcode Reader App for Salesforce AppExchange](https://www.dynamsoft.com/codepool/salesforce-appexchange-barcode-reader-app.html) 27 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/config/project-scratch-def.json: -------------------------------------------------------------------------------- 1 | { 2 | "orgName": "Dynamsoft", 3 | "edition": "Developer", 4 | "features": [], 5 | "settings": { 6 | "lightningExperienceSettings": { 7 | "enableS1DesktopEnabled": true 8 | }, 9 | "securitySettings": { 10 | "passwordPolicies": { 11 | "enableSetPasswordInApi": true 12 | } 13 | }, 14 | "mobileSettings": { 15 | "enableS1EncryptedStoragePref2": false 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/force-app/main/default/aura/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["@salesforce/eslint-plugin-aura"], 3 | "extends": ["plugin:@salesforce/eslint-plugin-aura/recommended", "prettier"], 4 | "rules": { 5 | "func-names": "off", 6 | "vars-on-top": "off", 7 | "no-unused-expressions": "off" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/force-app/main/default/lwc/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@salesforce/eslint-config-lwc/recommended", "prettier"], 3 | "overrides": [ 4 | { 5 | "files": ["*.test.js"], 6 | "rules": { 7 | "@lwc/lwc/no-unexpected-wire-adapter-usages": "off" 8 | } 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/force-app/main/default/pages/DecodeFile.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

Dynamsoft JavaScript Barcode SDK

9 |

10 |
11 | 12 |
13 | 14 |
15 | 16 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/force-app/main/default/pages/DecodeFile.page: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

Dynamsoft JavaScript Barcode SDK

10 |

11 |
12 | 13 |
14 | 15 |
16 | 17 | 84 | 85 | 86 | 87 |
-------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/force-app/main/default/pages/DecodeFile.page-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 49.0 4 | 5 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/force-app/main/default/pages/DecodeVideo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | 21 | 22 |

Dynamsoft JavaScript Barcode SDK

23 |

24 |
25 | Video source: 26 | 27 |
28 |
29 | 30 | 31 |
32 |
N/A
33 |
34 |
35 |
36 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/force-app/main/default/pages/DecodeVideo.page: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 20 | 21 | 22 | 23 |

Dynamsoft JavaScript Barcode SDK

24 |

25 |
26 | Video source: 27 | 28 |
29 |
30 | 31 | 32 |
33 |
N/A
34 |
35 |
36 |
37 | 136 | 137 | 138 | 139 | 140 |
-------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/force-app/main/default/pages/DecodeVideo.page-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 49.0 4 | 5 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "salesforce-app", 3 | "private": true, 4 | "version": "1.0.0", 5 | "description": "Salesforce App", 6 | "scripts": { 7 | "lint": "npm run lint:lwc && npm run lint:aura", 8 | "lint:aura": "eslint **/aura/**", 9 | "lint:lwc": "eslint **/lwc/**", 10 | "test": "npm run test:unit", 11 | "test:unit": "sfdx-lwc-jest", 12 | "test:unit:watch": "sfdx-lwc-jest --watch", 13 | "test:unit:debug": "sfdx-lwc-jest --debug", 14 | "test:unit:coverage": "sfdx-lwc-jest --coverage", 15 | "prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", 16 | "prettier:verify": "prettier --list-different \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"" 17 | }, 18 | "devDependencies": { 19 | "@prettier/plugin-xml": "^0.10.0", 20 | "@salesforce/eslint-config-lwc": "^0.7.0", 21 | "@salesforce/eslint-plugin-aura": "^1.4.0", 22 | "@salesforce/sfdx-lwc-jest": "^0.9.2", 23 | "eslint": "^7.6.0", 24 | "eslint-config-prettier": "^6.11.0", 25 | "husky": "^4.2.1", 26 | "lint-staged": "^10.0.7", 27 | "prettier": "^2.0.5", 28 | "prettier-plugin-apex": "^1.6.0" 29 | }, 30 | "husky": { 31 | "hooks": { 32 | "pre-commit": "lint-staged" 33 | } 34 | }, 35 | "lint-staged": { 36 | "**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}": [ 37 | "prettier --write" 38 | ], 39 | "**/{aura|lwc}/**": [ 40 | "eslint" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/scripts/apex/hello.apex: -------------------------------------------------------------------------------- 1 | // Use .apex files to store anonymous Apex. 2 | // You can execute anonymous Apex in VS Code by selecting the 3 | // apex text and running the command: 4 | // SFDX: Execute Anonymous Apex with Currently Selected Text 5 | // You can also execute the entire file by running the command: 6 | // SFDX: Execute Anonymous Apex with Editor Contents 7 | 8 | string tempvar = 'Enter_your_name_here'; 9 | System.debug('Hello World!'); 10 | System.debug('My name is ' + tempvar); -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/scripts/soql/account.soql: -------------------------------------------------------------------------------- 1 | // Use .soql files to store SOQL queries. 2 | // You can execute queries in VS Code by selecting the 3 | // query text and running the command: 4 | // SFDX: Execute SOQL Query with Currently Selected Text 5 | 6 | SELECT Id, Name FROM Account 7 | -------------------------------------------------------------------------------- /examples/9.x/salesforce_visualforce_page/sfdx-project.json: -------------------------------------------------------------------------------- 1 | { 2 | "packageDirectories": [ 3 | { 4 | "path": "force-app", 5 | "default": true 6 | } 7 | ], 8 | "namespace": "", 9 | "sfdcLoginUrl": "https://login.salesforce.com", 10 | "sourceApiVersion": "49.0" 11 | } 12 | -------------------------------------------------------------------------------- /examples/9.x/ui-customization.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dynamsoft JavaScript Barcode Scanner 8 | 9 | 45 | 46 | 47 | 48 |
49 | Barcode Result: N/A 50 |
51 |
52 | Loading Library... 53 |
54 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /examples/9.x/webgl/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript Barcode and QR Code Reader: WebGL vs. Canvas 2 | Use WebGL to convert color images to grayscale, speeding up barcode and QR code decoding in JavaScript. 3 | 4 | ## License Activation 5 | Get a [trial license](https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform) to activate the [JavaScript barcode SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/): 6 | 7 | ```javascript 8 | Dynamsoft.DBR.BarcodeReader.license = "LICENSE-KEY"; 9 | ``` 10 | 11 | ## Try Example 12 | [https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/webgl/](https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/webgl/) 13 | 14 | ![WebGL for JavaScript barcode](https://www.dynamsoft.com/codepool/wp-content/uploads/2020/07/webgl-javascript-barcode.png) 15 | 16 | ## References 17 | - https://webglfundamentals.org/webgl/lessons/webgl-2d-drawimage.html 18 | - https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texImage2D 19 | 20 | ## Blog 21 | [How to Use WebGL to Accelerate Web Barcode Decoding Speed](https://www.dynamsoft.com/codepool/webgl-accelerate-web-barcode-decoding-speed.html) 22 | -------------------------------------------------------------------------------- /examples/9.x/webgl/grayscale-image/640x480.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yushulx/javascript-barcode-qr-code-scanner/d11a6439fc2f877b450a15646ece21686c1b8462/examples/9.x/webgl/grayscale-image/640x480.jpg -------------------------------------------------------------------------------- /examples/9.x/webgl/grayscale-image/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | WebGL - 2D - DrawImage basic 9 | 10 | 11 | 12 | 13 | 14 | 27 | 28 | 42 | 49 | 50 | 51 | 209 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /examples/9.x/webgl/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 34 | 35 | 36 | 37 | 38 |

Web Barcode Scanning with WebGL

39 | 40 |
41 | 42 | 43 |
44 | 45 | 46 |
47 | 48 |
49 | 50 | 51 |
52 |
53 |
54 |
55 | 56 | 57 | 58 | 59 | 72 | 73 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /examples/9.x/webgl/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yushulx/javascript-barcode-qr-code-scanner/d11a6439fc2f877b450a15646ece21686c1b8462/examples/9.x/webgl/loading.gif -------------------------------------------------------------------------------- /examples/9.x/webgl/util.js: -------------------------------------------------------------------------------- 1 | // Make sure to set the key before you call any other APIs under Dynamsoft.DBR 2 | //You can register for a free 30-day trial here: https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform 3 | Dynamsoft.DBR.BarcodeReader.license = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="; 4 | 5 | var barcodereader; 6 | var barcode_result = document.getElementById('barcode_result'); 7 | (async () => { 8 | barcodereader = await Dynamsoft.DBR.BarcodeReader.createInstance(); 9 | await barcodereader.updateRuntimeSettings('speed'); 10 | let settings = await barcodereader.getRuntimeSettings(); 11 | settings.deblurLevel = 0; 12 | barcodereader.updateRuntimeSettings(settings); 13 | 14 | document.getElementById('anim-loading').style.display = 'none'; 15 | btWebGL.disabled = false; 16 | btCanvas.disabled = false; 17 | })(); 18 | 19 | var videoSelect = document.querySelector('select#videoSource'); 20 | var videoOption = document.getElementById('videoOption'); 21 | var btWebGL = document.getElementById('bt-webgl'); 22 | btWebGL.disabled = true; 23 | var btCanvas = document.getElementById('bt-canvas'); 24 | btCanvas.disabled = true; 25 | 26 | var videoElement = document.getElementById('videoContainer'); 27 | document.getElementById('videoview').style.display = 'block'; 28 | var overlay = document.getElementById('overlay'); 29 | var overlayContext = overlay.getContext('2d'); 30 | 31 | var canvas = document.getElementById('pcCanvas'); 32 | var ctx = canvas.getContext('2d'); 33 | 34 | var count = 1; 35 | var total = 0; 36 | 37 | var decoding_count = 1; 38 | var decoding_total = 0; 39 | 40 | var width, height; 41 | 42 | var isWebGL = false; 43 | 44 | // Initialize canvas 45 | var canvasWebGL = document.createElement('canvas'); 46 | var gl = canvasWebGL.getContext("webgl") || canvasWebGL.getContext("experimental-webgl"); 47 | 48 | var canvas2d = document.createElement('canvas'); 49 | var ctx2d = canvas2d.getContext('2d'); 50 | 51 | var gray = null; 52 | var buffer = null; 53 | 54 | function clearOverlay() { 55 | overlayContext.clearRect(0, 0, width, height); 56 | overlayContext.strokeStyle = '#ff0000'; 57 | overlayContext.lineWidth = 5; 58 | return overlayContext; 59 | } 60 | 61 | function drawResult(context, localization, text) { 62 | context.beginPath(); 63 | context.moveTo(localization.x1, localization.y1); 64 | context.lineTo(localization.x2, localization.y2); 65 | context.lineTo(localization.x3, localization.y3); 66 | context.lineTo(localization.x4, localization.y4); 67 | context.lineTo(localization.x1, localization.y1); 68 | context.stroke(); 69 | 70 | context.font = '18px Verdana'; 71 | context.fillStyle = '#ff0000'; 72 | let x = [localization.x1, localization.x2, localization.x3, localization.x4]; 73 | let y = [localization.y1, localization.y2, localization.y3, localization.y4]; 74 | x.sort(function (a, b) { 75 | return a - b; 76 | }); 77 | y.sort(function (a, b) { 78 | return b - a; 79 | }); 80 | let left = x[0]; 81 | let top = y[0]; 82 | 83 | context.fillText(text, left, top + 50); 84 | } 85 | 86 | function run() { 87 | count = 1; 88 | total = 0; 89 | decoding_count = 1; 90 | decoding_total = 0; 91 | scanBarcode(); 92 | } 93 | 94 | btWebGL.onclick = function () { 95 | clearOverlay(); 96 | btWebGL.disabled = true; 97 | btCanvas.disabled = false; 98 | isWebGL = true; 99 | run(); 100 | }; 101 | 102 | btCanvas.onclick = function () { 103 | clearOverlay(); 104 | btCanvas.disabled = true; 105 | btWebGL.disabled = false; 106 | isWebGL = false; 107 | run(); 108 | }; 109 | 110 | // scan barcode 111 | function scanBarcode() { 112 | 113 | // let start = window.performance.now(); 114 | let start = Date.now(); 115 | let end; 116 | 117 | buffer = new Uint8Array(width * height * 4); 118 | 119 | if (isWebGL) { 120 | gray = new Uint8Array(width * height); 121 | 122 | var drawInfo = { 123 | x: 0, 124 | y: 0, 125 | dx: 1, 126 | dy: 1, 127 | textureInfo: loadImageAndCreateTextureInfo(videoElement) 128 | }; 129 | 130 | draw(drawInfo); 131 | 132 | gl.readPixels( 133 | 0, 134 | 0, 135 | gl.drawingBufferWidth, 136 | gl.drawingBufferHeight, 137 | gl.RGBA, 138 | gl.UNSIGNED_BYTE, 139 | buffer 140 | ); 141 | // end = window.performance.now(); 142 | // end = Date.now(); 143 | 144 | // Grayscale image 145 | let gray_index = 0; 146 | for (i = 0; i < width * height * 4; i += 4) { 147 | gray[gray_index++] = buffer[i]; 148 | } 149 | 150 | end = Date.now(); 151 | 152 | // Draw WebGL texture to canvas 153 | var imgData = ctx.createImageData(width, height); 154 | for (var i = 0; i < buffer.length; i += 4) { 155 | imgData.data[i] = buffer[i]; //red 156 | imgData.data[i + 1] = buffer[i + 1]; //green 157 | imgData.data[i + 2] = buffer[i + 2]; //blue 158 | imgData.data[i + 3] = buffer[i + 3]; //alpha 159 | } 160 | ctx.putImageData(imgData, 0, 0); 161 | } 162 | else { 163 | ctx2d.drawImage(videoElement, 0, 0, width, height); 164 | buffer = ctx2d.getImageData(0, 0, width, height).data; 165 | // end = window.performance.now(); 166 | end = Date.now() 167 | 168 | // Draw video frame to canvas 169 | ctx.drawImage(videoElement, 0, 0); 170 | } 171 | 172 | if (isWebGL) { 173 | console.log("%c WebGL buffer time cost: " + (end - start), 'color: green; font-weight: bold;'); 174 | } 175 | else 176 | console.log("Canvas buffer time cost: " + (end - start)); 177 | 178 | // total += (end - start); 179 | // count += 1; 180 | // if (count == 31) { 181 | // if (isWebGL) { 182 | // console.log("%c WebGL buffer time cost: " + total / 30, 'color: green; font-weight: bold;'); 183 | // } 184 | // else 185 | // console.log("Canvas buffer time cost: " + total / 30); 186 | // count = 1; 187 | // total = 0; 188 | // } 189 | 190 | // read barcode 191 | // let decoding_start = window.performance.now(); 192 | let decoding_start = Date.now(); 193 | 194 | if (isWebGL) { 195 | // console.time("Grayscale Image"); 196 | barcodereader 197 | .decodeBuffer( 198 | gray, 199 | width, 200 | height, 201 | width, 202 | Dynamsoft.DBR.EnumImagePixelFormat.IPF_GrayScaled 203 | ) 204 | .then((results) => { 205 | // console.timeEnd("Grayscale Image"); 206 | if (!isWebGL) return; 207 | 208 | // let decoding_end = window.performance.now(); 209 | let decoding_end = Date.now(); 210 | console.log("%c Grayscale image Decoding time cost: " + (decoding_end - decoding_start), 'color: green; font-weight: bold;'); 211 | console.log(""); 212 | 213 | decoding_total += (decoding_end - decoding_start); 214 | decoding_count += 1; 215 | if (decoding_count == 31) { 216 | // console.log("%c Average Decoding time cost: " + decoding_total / 30, 'color: green; font-weight: bold;'); 217 | decoding_count = 1; 218 | decoding_total = 0; 219 | } 220 | showResults(results); 221 | }); 222 | } 223 | else { 224 | // console.time("Color Image"); 225 | barcodereader 226 | .decodeBuffer( 227 | buffer, 228 | width, 229 | height, 230 | width * 4, 231 | Dynamsoft.DBR.EnumImagePixelFormat.IPF_ARGB_8888 232 | ) 233 | .then((results) => { 234 | // console.timeEnd("Color Image"); 235 | if (isWebGL) return; 236 | 237 | // let decoding_end = window.performance.now(); 238 | let decoding_end = Date.now(); 239 | console.log("Color image decoding time cost: " + (decoding_end - decoding_start)); 240 | console.log(""); 241 | 242 | decoding_total += (decoding_end - decoding_start); 243 | decoding_count += 1; 244 | if (decoding_count == 31) { 245 | // console.log("Average Decoding time cost: " + decoding_total / 30); 246 | decoding_count = 1; 247 | decoding_total = 0; 248 | } 249 | showResults(results); 250 | }); 251 | } 252 | 253 | } 254 | 255 | console.time('devices'); 256 | navigator.mediaDevices.enumerateDevices().then(gotDevices).then(getStream).catch(handleError); 257 | 258 | videoSelect.onchange = getStream; 259 | 260 | function gotDevices(deviceInfos) { 261 | for (var i = deviceInfos.length - 1; i >= 0; --i) { 262 | var deviceInfo = deviceInfos[i]; 263 | var option = document.createElement('option'); 264 | option.value = deviceInfo.deviceId; 265 | if (deviceInfo.kind === 'videoinput') { 266 | option.text = deviceInfo.label || 'camera ' + (videoSelect.length + 1); 267 | videoSelect.appendChild(option); 268 | } else { 269 | console.log('Found one other kind of source/device: ', deviceInfo); 270 | } 271 | } 272 | } 273 | 274 | function getStream() { 275 | if (window.stream) { 276 | window.stream.getTracks().forEach(function (track) { 277 | track.stop(); 278 | }); 279 | } 280 | 281 | var constraints = { 282 | video: { 283 | deviceId: videoSelect.value, 284 | width: { min: 640 }, 285 | height: { min: 480 }, 286 | } 287 | }; 288 | 289 | navigator.mediaDevices.getUserMedia(constraints).then(gotStream).catch(handleError); 290 | } 291 | 292 | function gotStream(stream) { 293 | window.stream = stream; 294 | videoElement.srcObject = stream; 295 | videoElement.addEventListener("loadedmetadata", function (e) { 296 | width = this.videoWidth; 297 | height = this.videoHeight; 298 | console.log(width, height); 299 | canvas.width = width; 300 | canvas.height = height; 301 | canvasWebGL.width = width; 302 | canvasWebGL.height = height; 303 | canvas2d.width = width; 304 | canvas2d.height = height; 305 | overlay.width = width; 306 | overlay.height = height; 307 | 308 | }, false); 309 | } 310 | 311 | function handleError(error) { 312 | console.log('Error: ', error); 313 | } 314 | 315 | function showResults(results) { 316 | let context = clearOverlay(); 317 | 318 | let txts = []; 319 | try { 320 | let localization; 321 | if (results.length > 0) { 322 | for (var i = 0; i < results.length; ++i) { 323 | txts.push(results[i].barcodeText); 324 | localization = results[i].localizationResult; 325 | drawResult(context, localization, results[i].barcodeText); 326 | } 327 | barcode_result.textContent = txts.join(', '); 328 | } 329 | else { 330 | barcode_result.textContent = "No barcode found"; 331 | } 332 | 333 | scanBarcode(); 334 | } catch (e) { 335 | alert(e); 336 | } 337 | } 338 | 339 | /* 340 | * WebGL initialization 341 | * https://webglfundamentals.org/webgl/lessons/webgl-2d-drawimage.html 342 | * https://webglfundamentals.org/webgl/resources/m4.js 343 | * https://webglfundamentals.org/webgl/resources/webgl-utils.js 344 | */ 345 | 346 | // setup GLSL program 347 | var program = webglUtils.createProgramFromScripts(gl, ["drawImage-vertex-shader", "drawImage-fragment-shader"]); 348 | 349 | // look up where the vertex data needs to go. 350 | var positionLocation = gl.getAttribLocation(program, "a_position"); 351 | var texcoordLocation = gl.getAttribLocation(program, "a_texcoord"); 352 | 353 | // lookup uniforms 354 | var matrixLocation = gl.getUniformLocation(program, "u_matrix"); 355 | var textureLocation = gl.getUniformLocation(program, "u_texture"); 356 | 357 | // Create a buffer. 358 | var positionBuffer = gl.createBuffer(); 359 | gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 360 | 361 | // Put a unit quad in the buffer 362 | var positions = [ 363 | 0, 0, 364 | 0, 1, 365 | 1, 0, 366 | 1, 0, 367 | 0, 1, 368 | 1, 1, 369 | ]; 370 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); 371 | 372 | // Create a buffer for texture coords 373 | var texcoordBuffer = gl.createBuffer(); 374 | gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer); 375 | 376 | // Put texcoords in the buffer 377 | var texcoords = [ 378 | 0, 0, 379 | 0, 1, 380 | 1, 0, 381 | 1, 0, 382 | 0, 1, 383 | 1, 1, 384 | ]; 385 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoords), gl.STATIC_DRAW); 386 | 387 | // creates a texture info { width: w, height: h, texture: tex } 388 | // The texture will start with 1x1 pixels and be updated 389 | // when the image has loaded 390 | function loadImageAndCreateTextureInfo(videoElement) { 391 | var tex = gl.createTexture(); 392 | var textureInfo = { 393 | width: width, 394 | height: height, 395 | texture: tex, 396 | }; 397 | 398 | gl.bindTexture(gl.TEXTURE_2D, textureInfo.texture); 399 | gl.texImage2D( 400 | gl.TEXTURE_2D, 401 | 0, 402 | gl.RGBA, 403 | gl.RGBA, 404 | gl.UNSIGNED_BYTE, 405 | videoElement 406 | ); 407 | 408 | // let's assume all images are not a power of 2 409 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 410 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 411 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 412 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 413 | 414 | return textureInfo; 415 | } 416 | 417 | function draw(drawInfo) { 418 | // webglUtils.resizeCanvasToDisplaySize(gl.canvas); 419 | 420 | // Tell WebGL how to convert from clip space to pixels 421 | gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); 422 | 423 | gl.clear(gl.COLOR_BUFFER_BIT); 424 | 425 | drawImage( 426 | drawInfo.textureInfo.texture, 427 | drawInfo.textureInfo.width, 428 | drawInfo.textureInfo.height, 429 | drawInfo.x, 430 | drawInfo.y); 431 | } 432 | 433 | // Unlike images, textures do not have a width and height associated 434 | // with them so we'll pass in the width and height of the texture 435 | function drawImage(tex, texWidth, texHeight, dstX, dstY) { 436 | gl.bindTexture(gl.TEXTURE_2D, tex); 437 | // https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/pixelStorei 438 | gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); 439 | 440 | // Tell WebGL to use our shader program pair 441 | gl.useProgram(program); 442 | 443 | // Setup the attributes to pull data from our buffers 444 | gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 445 | gl.enableVertexAttribArray(positionLocation); 446 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 447 | gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer); 448 | gl.enableVertexAttribArray(texcoordLocation); 449 | gl.vertexAttribPointer(texcoordLocation, 2, gl.FLOAT, false, 0, 0); 450 | 451 | // this matrix will convert from pixels to clip space 452 | var matrix = m4.orthographic(0, gl.canvas.width, gl.canvas.height, 0, -1, 1); 453 | 454 | // this matrix will translate our quad to dstX, dstY 455 | matrix = m4.translate(matrix, dstX, dstY, 0); 456 | 457 | // this matrix will scale our 1 unit quad 458 | // from 1 unit to texWidth, texHeight units 459 | matrix = m4.scale(matrix, texWidth, texHeight, 1); 460 | 461 | // Set the matrix. 462 | gl.uniformMatrix4fv(matrixLocation, false, matrix); 463 | 464 | // Tell the shader to get the texture from texture unit 0 465 | gl.uniform1i(textureLocation, 0); 466 | 467 | // draw the quad (2 triangles, 6 vertices) 468 | gl.drawArrays(gl.TRIANGLES, 0, 6); 469 | } -------------------------------------------------------------------------------- /examples/9.x/wrapper-test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dynamsoft JavaScript Barcode Scanner 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | 24 | 26 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /examples/aadhaar_card/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | Results:
9 |
10 |
11 | 12 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /examples/barcode_mrz_document/README.md: -------------------------------------------------------------------------------- 1 | # Scan Barcode, Document and Machine-readable Zone (MRZ) in JavaScript 2 | The sample demonstrates how to use Dynamsoft Capture Vision to scan **1D/2D barcodes**, **document** and **machine-readable zone (MRZ)** within a web browser. 3 | 4 | https://github.com/user-attachments/assets/e205a602-b838-46fa-ac8e-45a009e64ae0 5 | 6 | ## Prerequisites 7 | - Obtain a [30-day free trial license](https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform) for Dynamsoft Capture Vision. 8 | 9 | ## Demo 10 | https://yushulx.me/javascript-barcode-qr-code-scanner/examples/barcode_mrz_document 11 | 12 | ## Blog 13 | - [How to Build a Web App to Scan Barcode, Document, and MRZ with JavaScript APIs](https://www.dynamsoft.com/codepool/javascript-scan-barcode-mrz-document.html) 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/barcode_mrz_document/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yushulx/javascript-barcode-qr-code-scanner/d11a6439fc2f877b450a15646ece21686c1b8462/examples/barcode_mrz_document/default.png -------------------------------------------------------------------------------- /examples/barcode_mrz_document/full.json: -------------------------------------------------------------------------------- 1 | { 2 | "CaptureVisionModelOptions": [ 3 | { 4 | "ModelArgs": { 5 | "CharSet": { 6 | "ExcludeChars": [ 7 | "O", 8 | "Q", 9 | "I" 10 | ] 11 | } 12 | }, 13 | "Name": "VINCharRecognition" 14 | }, 15 | { 16 | "Name": "MRZCharRecognition", 17 | "DirectoryPath": "", 18 | "MaxModelInstances": 4 19 | }, 20 | { 21 | "Name": "MRZTextLineRecognition", 22 | "DirectoryPath": "", 23 | "MaxModelInstances": 1 24 | } 25 | ], 26 | "CaptureVisionTemplates": [ 27 | { 28 | "ImageROIProcessingNameArray": [ 29 | "roi-read-vin-text" 30 | ], 31 | "Name": "ReadVINText" 32 | }, 33 | { 34 | "ImageROIProcessingNameArray": [ 35 | "roi-mrz" 36 | ], 37 | "Name": "ReadMRZ", 38 | "SemanticProcessingNameArray": [ 39 | "sp-mrz" 40 | ], 41 | "Timeout": 1000000 42 | } 43 | ], 44 | "CodeParserTaskSettingOptions": [ 45 | { 46 | "CodeSpecifications": [ 47 | "MRTD_TD3_PASSPORT", 48 | "MRTD_TD2_VISA", 49 | "MRTD_TD3_VISA", 50 | "MRTD_TD1_ID", 51 | "MRTD_TD2_ID" 52 | ], 53 | "Name": "dcp-mrz" 54 | } 55 | ], 56 | "ImageParameterOptions": [ 57 | { 58 | "ApplicableStages": [ 59 | { 60 | "Stage": "SST_INPUT_COLOR_IMAGE" 61 | }, 62 | { 63 | "Stage": "SST_SCALE_IMAGE" 64 | }, 65 | { 66 | "Stage": "SST_CONVERT_TO_GRAYSCALE" 67 | }, 68 | { 69 | "GrayscaleTransformationModes": [ 70 | { 71 | "Mode": "GTM_ORIGINAL" 72 | }, 73 | { 74 | "Mode": "GTM_INVERTED" 75 | } 76 | ], 77 | "Stage": "SST_TRANSFORM_GRAYSCALE" 78 | }, 79 | { 80 | "Stage": "SST_ENHANCE_GRAYSCALE" 81 | }, 82 | { 83 | "Stage": "SST_BINARIZE_IMAGE" 84 | }, 85 | { 86 | "Stage": "SST_DETECT_TEXTURE" 87 | }, 88 | { 89 | "Stage": "SST_REMOVE_TEXTURE_FROM_GRAYSCALE" 90 | }, 91 | { 92 | "Stage": "SST_BINARIZE_TEXTURE_REMOVED_GRAYSCALE" 93 | }, 94 | { 95 | "Stage": "SST_FIND_CONTOURS" 96 | }, 97 | { 98 | "Stage": "SST_DETECT_SHORTLINES" 99 | }, 100 | { 101 | "Stage": "SST_ASSEMBLE_LINES" 102 | }, 103 | { 104 | "Stage": "SST_DETECT_TEXT_ZONES", 105 | "TextDetectionMode": { 106 | "CharHeightRange": [ 107 | 5, 108 | 1000, 109 | 1 110 | ], 111 | "Direction": "HORIZONTAL", 112 | "Mode": "TTDM_LINE", 113 | "Sensitivity": 7 114 | } 115 | }, 116 | { 117 | "Stage": "SST_REMOVE_TEXT_ZONES_FROM_BINARY" 118 | } 119 | ], 120 | "Name": "ip_recognize_text" 121 | }, 122 | { 123 | "ApplicableStages": [ 124 | { 125 | "Stage": "SST_INPUT_COLOR_IMAGE" 126 | }, 127 | { 128 | "Stage": "SST_SCALE_IMAGE" 129 | }, 130 | { 131 | "Stage": "SST_CONVERT_TO_GRAYSCALE" 132 | }, 133 | { 134 | "Stage": "SST_TRANSFORM_GRAYSCALE" 135 | }, 136 | { 137 | "Stage": "SST_ENHANCE_GRAYSCALE" 138 | }, 139 | { 140 | "BinarizationModes": [ 141 | { 142 | "EnableFillBinaryVacancy": 0, 143 | "Mode": "BM_LOCAL_BLOCK", 144 | "ThresholdCompensation": 21 145 | } 146 | ], 147 | "Stage": "SST_BINARIZE_IMAGE" 148 | }, 149 | { 150 | "Stage": "SST_DETECT_TEXTURE", 151 | "TextureDetectionModes": [ 152 | { 153 | "Mode": "TDM_GENERAL_WIDTH_CONCENTRATION", 154 | "Sensitivity": 8 155 | } 156 | ] 157 | }, 158 | { 159 | "Stage": "SST_REMOVE_TEXTURE_FROM_GRAYSCALE" 160 | }, 161 | { 162 | "Stage": "SST_BINARIZE_TEXTURE_REMOVED_GRAYSCALE" 163 | }, 164 | { 165 | "Stage": "SST_FIND_CONTOURS" 166 | }, 167 | { 168 | "Stage": "SST_DETECT_SHORTLINES" 169 | }, 170 | { 171 | "Stage": "SST_ASSEMBLE_LINES" 172 | }, 173 | { 174 | "Stage": "SST_DETECT_TEXT_ZONES", 175 | "TextDetectionMode": { 176 | "CharHeightRange": [ 177 | 5, 178 | 1000, 179 | 1 180 | ], 181 | "Direction": "HORIZONTAL", 182 | "Mode": "TTDM_LINE", 183 | "Sensitivity": 7 184 | } 185 | }, 186 | { 187 | "Stage": "SST_REMOVE_TEXT_ZONES_FROM_BINARY" 188 | } 189 | ], 190 | "Name": "ip-mrz" 191 | } 192 | ], 193 | "LabelRecognizerTaskSettingOptions": [ 194 | { 195 | "Name": "task-read-vin-text", 196 | "SectionArray": [ 197 | { 198 | "ImageParameterName": "ip_recognize_text", 199 | "Section": "ST_REGION_PREDETECTION", 200 | "StageArray": [ 201 | { 202 | "Stage": "SST_PREDETECT_REGIONS" 203 | } 204 | ] 205 | }, 206 | { 207 | "ImageParameterName": "ip_recognize_text", 208 | "Section": "ST_TEXT_LINE_LOCALIZATION", 209 | "StageArray": [ 210 | { 211 | "Stage": "SST_LOCALIZE_TEXT_LINES" 212 | } 213 | ] 214 | }, 215 | { 216 | "ImageParameterName": "ip_recognize_text", 217 | "Section": "ST_TEXT_LINE_RECOGNITION", 218 | "StageArray": [ 219 | { 220 | "Stage": "SST_RECOGNIZE_RAW_TEXT_LINES" 221 | }, 222 | { 223 | "Stage": "SST_ASSEMBLE_TEXT_LINES" 224 | } 225 | ] 226 | } 227 | ], 228 | "TextLineSpecificationNameArray": [ 229 | "tls_vin_text" 230 | ] 231 | }, 232 | { 233 | "Name": "task-mrz", 234 | "SectionArray": [ 235 | { 236 | "ImageParameterName": "ip-mrz", 237 | "Section": "ST_REGION_PREDETECTION", 238 | "StageArray": [ 239 | { 240 | "Stage": "SST_PREDETECT_REGIONS" 241 | } 242 | ] 243 | }, 244 | { 245 | "ImageParameterName": "ip-mrz", 246 | "Section": "ST_TEXT_LINE_LOCALIZATION", 247 | "StageArray": [ 248 | { 249 | "Stage": "SST_LOCALIZE_TEXT_LINES" 250 | } 251 | ] 252 | }, 253 | { 254 | "ImageParameterName": "ip-mrz", 255 | "Section": "ST_TEXT_LINE_RECOGNITION", 256 | "StageArray": [ 257 | { 258 | "ConfusableCharactersPath": "ConfusableChars.data", 259 | "Stage": "SST_RECOGNIZE_RAW_TEXT_LINES" 260 | }, 261 | { 262 | "Stage": "SST_ASSEMBLE_TEXT_LINES" 263 | } 264 | ] 265 | } 266 | ], 267 | "TextLineSpecificationNameArray": [ 268 | "tls-mrz-passport", 269 | "tls-mrz-visa-td3", 270 | "tls-mrz-id-td1", 271 | "tls-mrz-id-td2", 272 | "tls-mrz-visa-td2" 273 | ] 274 | } 275 | ], 276 | "SemanticProcessingOptions": [ 277 | { 278 | "Name": "sp-mrz", 279 | "ReferenceObjectFilter": { 280 | "ReferenceTargetROIDefNameArray": [ 281 | "roi-mrz" 282 | ] 283 | }, 284 | "TaskSettingNameArray": [ 285 | "dcp-mrz" 286 | ] 287 | } 288 | ], 289 | "TargetROIDefOptions": [ 290 | { 291 | "Name": "roi-read-vin-text", 292 | "TaskSettingNameArray": [ 293 | "task-read-vin-text" 294 | ] 295 | }, 296 | { 297 | "Name": "roi-mrz", 298 | "TaskSettingNameArray": [ 299 | "task-mrz" 300 | ] 301 | } 302 | ], 303 | "TextLineSpecificationOptions": [ 304 | { 305 | "CharHeightRange": [ 306 | 5, 307 | 1000, 308 | 1 309 | ], 310 | "CharacterModelName": "VINCharRecognition", 311 | "ConcatSeparator": "\\n", 312 | "Name": "tls_vin_text", 313 | "StringLengthRange": [ 314 | 17, 315 | 17 316 | ], 317 | "StringRegExPattern": "[0-9A-HJ-NPR-Z]{9}[1-9A-HJ-NPR-TV-Y][0-9A-HJ-NPR-Z]{2}[0-9]{5}", 318 | "TextLinesCount": 1 319 | }, 320 | { 321 | "BaseTextLineSpecificationName": "tls-base", 322 | "ConcatResults": 1, 323 | "ConcatSeparator": "\\n", 324 | "Name": "tls-mrz-passport", 325 | "StringLengthRange": [ 326 | 44, 327 | 44 328 | ], 329 | "SubGroups": [ 330 | { 331 | "BaseTextLineSpecificationName": "tls-base", 332 | "StringLengthRange": [ 333 | 44, 334 | 44 335 | ], 336 | "StringRegExPattern": "(P[A-Z<][A-Z<]{3}[A-Z<]{39}){(44)}" 337 | }, 338 | { 339 | "BaseTextLineSpecificationName": "tls-base", 340 | "StringLengthRange": [ 341 | 44, 342 | 44 343 | ], 344 | "StringRegExPattern": "([A-Z0-9<]{9}[0-9][A-Z<]{3}[0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z0-9<]{14}[0-9<][0-9]){(44)}" 345 | } 346 | ] 347 | }, 348 | { 349 | "BaseTextLineSpecificationName": "tls-base", 350 | "ConcatResults": 1, 351 | "ConcatSeparator": "\\n", 352 | "Name": "tls-mrz-visa-td3", 353 | "StringLengthRange": [ 354 | 44, 355 | 44 356 | ], 357 | "SubGroups": [ 358 | { 359 | "BaseTextLineSpecificationName": "tls-base", 360 | "StringLengthRange": [ 361 | 44, 362 | 44 363 | ], 364 | "StringRegExPattern": "(V[A-Z<][A-Z<]{3}[A-Z<]{39}){(44)}" 365 | }, 366 | { 367 | "BaseTextLineSpecificationName": "tls-base", 368 | "StringLengthRange": [ 369 | 44, 370 | 44 371 | ], 372 | "StringRegExPattern": "([A-Z0-9<]{9}[0-9][A-Z<]{3}[0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z0-9<]{14}[A-Z0-9<]{2}){(44)}" 373 | } 374 | ] 375 | }, 376 | { 377 | "BaseTextLineSpecificationName": "tls-base", 378 | "ConcatResults": 1, 379 | "ConcatSeparator": "\\n", 380 | "Name": "tls-mrz-visa-td2", 381 | "StringLengthRange": [ 382 | 36, 383 | 36 384 | ], 385 | "SubGroups": [ 386 | { 387 | "BaseTextLineSpecificationName": "tls-base", 388 | "StringLengthRange": [ 389 | 36, 390 | 36 391 | ], 392 | "StringRegExPattern": "(V[A-Z<][A-Z<]{3}[A-Z<]{31}){(36)}" 393 | }, 394 | { 395 | "BaseTextLineSpecificationName": "tls-base", 396 | "StringLengthRange": [ 397 | 36, 398 | 36 399 | ], 400 | "StringRegExPattern": "([A-Z0-9<]{9}[0-9][A-Z<]{3}[0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z0-9<]{8}){(36)}" 401 | } 402 | ] 403 | }, 404 | { 405 | "BaseTextLineSpecificationName": "tls-base", 406 | "ConcatResults": 1, 407 | "ConcatSeparator": "\\n", 408 | "Name": "tls-mrz-id-td2", 409 | "StringLengthRange": [ 410 | 36, 411 | 36 412 | ], 413 | "SubGroups": [ 414 | { 415 | "BaseTextLineSpecificationName": "tls-base", 416 | "StringLengthRange": [ 417 | 36, 418 | 36 419 | ], 420 | "StringRegExPattern": "([ACI][A-Z<][A-Z<]{3}[A-Z<]{31}){(36)}" 421 | }, 422 | { 423 | "BaseTextLineSpecificationName": "tls-base", 424 | "StringLengthRange": [ 425 | 36, 426 | 36 427 | ], 428 | "StringRegExPattern": "([A-Z0-9<]{9}[0-9][A-Z<]{3}[0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z0-9<]{8}){(36)}" 429 | } 430 | ] 431 | }, 432 | { 433 | "BaseTextLineSpecificationName": "tls-base", 434 | "ConcatResults": 1, 435 | "ConcatSeparator": "\\n", 436 | "Name": "tls-mrz-id-td1", 437 | "StringLengthRange": [ 438 | 30, 439 | 30 440 | ], 441 | "SubGroups": [ 442 | { 443 | "BaseTextLineSpecificationName": "tls-base", 444 | "StringLengthRange": [ 445 | 30, 446 | 30 447 | ], 448 | "StringRegExPattern": "([ACI][A-Z<][A-Z<]{3}[A-Z0-9<]{9}[0-9][A-Z0-9<]{15}){(30)}" 449 | }, 450 | { 451 | "BaseTextLineSpecificationName": "tls-base", 452 | "StringLengthRange": [ 453 | 30, 454 | 30 455 | ], 456 | "StringRegExPattern": "([0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z<]{3}[A-Z0-9<]{11}[0-9]){(30)}" 457 | }, 458 | { 459 | "BaseTextLineSpecificationName": "tls-base", 460 | "StringLengthRange": [ 461 | 30, 462 | 30 463 | ], 464 | "StringRegExPattern": "([A-Z<]{30}){(30)}" 465 | } 466 | ] 467 | }, 468 | { 469 | "BinarizationModes": [ 470 | { 471 | "BlockSizeX": 30, 472 | "BlockSizeY": 30, 473 | "EnableFillBinaryVacancy": 0, 474 | "Mode": "BM_LOCAL_BLOCK", 475 | "ThresholdCompensation": 15 476 | } 477 | ], 478 | "CharHeightRange": [ 479 | 5, 480 | 1000, 481 | 1 482 | ], 483 | "CharacterModelName": "MRZCharRecognition", 484 | "TextLineRecModelName": "MRZTextLineRecognition", 485 | "ConfusableCharactersCorrection": { 486 | "ConfusableCharacters": [ 487 | [ 488 | "0", 489 | "O" 490 | ], 491 | [ 492 | "1", 493 | "I" 494 | ], 495 | [ 496 | "5", 497 | "S" 498 | ] 499 | ], 500 | "FontNameArray": [ 501 | "OCR_B" 502 | ] 503 | }, 504 | "Name": "tls-base" 505 | } 506 | ] 507 | } -------------------------------------------------------------------------------- /examples/barcode_mrz_document/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Dynamsoft Vision SDKs 11 | 12 | 13 | 14 |

Scan Barcode, Document and Machine-readable Zone (MRZ)

15 |
16 |
17 |
18 | 19 | 20 |
21 |
22 |
23 | 28 | 31 | 32 |
33 |
34 | 35 |
36 |
37 | 41 | 42 |
43 | 47 | 51 | 55 |
56 |
57 |
58 |
59 | 60 | 61 |
62 |
63 | 64 |
65 | 66 |
67 |
68 | 69 | 70 |
71 |
72 | 73 |
74 |
75 | 76 |
77 |
78 | 79 |
80 |
81 | 82 |
83 |
84 | 85 |
86 | 87 | 88 |
89 |
90 | 92 | 93 | 94 |
95 |
96 |
97 | 98 |
99 |
100 | 101 |
102 |
103 | 104 |
105 |
106 | 107 | 108 |
109 |
110 | 111 | 112 | 113 |
114 |
115 | 116 | 117 |
118 |
119 | 120 |
121 |
122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /examples/barcode_mrz_document/styles.css: -------------------------------------------------------------------------------- 1 | .row { 2 | display: flex; 3 | justify-content: space-between; 4 | margin: 10px auto; 5 | align-items: center; 6 | } 7 | 8 | .container { 9 | max-width: 720px; 10 | margin: 20px auto; 11 | padding: 20px; 12 | border: 1px solid #ddd; 13 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 14 | } 15 | 16 | .loading-indicator { 17 | position: absolute; 18 | top: 0; 19 | left: 0; 20 | width: 100%; 21 | height: 100%; 22 | background-color: rgba(0, 0, 0, 0.5); 23 | z-index: 1000; 24 | display: none; 25 | align-items: center; 26 | justify-content: center; 27 | } 28 | 29 | .spinner { 30 | width: 50px; 31 | height: 50px; 32 | border: 5px solid #fff; 33 | border-radius: 50%; 34 | animation: spin 1s linear infinite; 35 | background: linear-gradient(to right, #FF0000 0%, #FF8000 17%, #FFFF00 33%, #00FF00 50%, #00FFFF 67%, #0080FF 83%, #0000FF 100%); 36 | } 37 | 38 | @keyframes spin { 39 | from { 40 | transform: rotate(0deg); 41 | } 42 | 43 | to { 44 | transform: rotate(360deg); 45 | } 46 | } 47 | 48 | .filler { 49 | flex-grow: 1; 50 | } 51 | 52 | #imageGrid { 53 | width: 720px; 54 | height: 720px; 55 | margin: auto; 56 | display: grid; 57 | grid-template-columns: repeat(2, 1fr); 58 | gap: 50px; 59 | } 60 | 61 | .editor { 62 | display: flex; 63 | margin: 10px auto; 64 | align-items: center; 65 | } 66 | 67 | #videoview { 68 | position: relative; 69 | width: 100%; 70 | height: 40vh; 71 | } 72 | 73 | #videoContainer { 74 | position: relative; 75 | width: 100%; 76 | height: 100%; 77 | z-index: 1 78 | } 79 | 80 | #imageGrid { 81 | width: 720px; 82 | height: 720px; 83 | margin: auto; 84 | display: grid; 85 | grid-template-columns: repeat(2, 1fr); 86 | gap: 50px; 87 | } 88 | 89 | #camera_container { 90 | display: none; 91 | } 92 | 93 | h1 { 94 | text-align: center; 95 | } 96 | 97 | .imageview { 98 | max-width: 720px; 99 | max-height: 720px; 100 | width: 720px; 101 | height: 720px; 102 | border: 1px solid #ddd; 103 | background-color: #eaeaea; 104 | position: relative; 105 | } 106 | 107 | .imageview img { 108 | display: block; 109 | width: 100%; 110 | height: 100%; 111 | object-fit: contain 112 | } 113 | 114 | #sources { 115 | width: 200px; 116 | } 117 | 118 | #dropdown { 119 | width: 200px; 120 | } 121 | 122 | textarea { 123 | width: 680px; 124 | height: 100px; 125 | margin: 10px auto; 126 | padding: 20px; 127 | border: 1px solid #ddd; 128 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 129 | } 130 | 131 | button { 132 | padding: 4px; 133 | margin: 4px; 134 | border: none; 135 | background-color: #007BFF; 136 | color: #fff; 137 | cursor: pointer; 138 | border-radius: 5px; 139 | } 140 | 141 | #drop_area { 142 | border: 2px dashed #ccc; 143 | border-radius: 5px; 144 | padding: 50px; 145 | text-align: center; 146 | margin: 20px; 147 | } 148 | 149 | #drop_area:hover { 150 | background-color: #f8f8f8; 151 | } 152 | 153 | .overlay { 154 | position: absolute; 155 | top: 0; 156 | left: 0; 157 | width: 100%; 158 | height: 100%; 159 | object-fit: contain 160 | } 161 | 162 | #document_editor { 163 | display: none; 164 | } 165 | 166 | #rectify_view { 167 | display: none; 168 | } 169 | 170 | #camera_view { 171 | width: 100%; 172 | height: 100%; 173 | object-fit: contain 174 | } -------------------------------------------------------------------------------- /examples/barcode_mrz_document/utils.js: -------------------------------------------------------------------------------- 1 | function showMessage(text) { 2 | var messageBox = document.getElementById('message-box'); 3 | var messageText = document.getElementById('message-text'); 4 | messageText.textContent = text; 5 | messageBox.classList.add('show', 'slide-in'); 6 | setTimeout(function () { 7 | messageBox.classList.remove('slide-in'); 8 | messageBox.classList.add('slide-out'); 9 | setTimeout(function () { 10 | messageBox.classList.remove('show', 'slide-out'); 11 | }, 500); 12 | }, 3000); 13 | } -------------------------------------------------------------------------------- /examples/barcode_ocr_text/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Dynamsoft Capture Vision Example 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 | 18 |
19 | 20 |
21 | 24 |
25 | 27 | 28 |
29 |
30 | 31 |
32 |
33 | 34 |
35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/barcode_ocr_text/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, sans-serif; 3 | margin: 0 auto; 4 | } 5 | 6 | textarea { 7 | width: 99%; 8 | min-height: 8vh; 9 | font-size: 1em; 10 | overflow: auto; 11 | } 12 | 13 | .loading-indicator { 14 | position: absolute; 15 | top: 0; 16 | left: 0; 17 | width: 100%; 18 | height: 100%; 19 | background-color: rgba(0, 0, 0, 0.5); 20 | z-index: 1000; 21 | display: none; 22 | align-items: center; 23 | justify-content: center; 24 | display: none; 25 | } 26 | 27 | .spinner { 28 | width: 50px; 29 | height: 50px; 30 | border: 5px solid #fff; 31 | border-radius: 50%; 32 | animation: spin 1s linear infinite; 33 | background: linear-gradient(to right, #FF0000 0%, #FF8000 17%, #FFFF00 33%, #00FF00 50%, #00FFFF 67%, #0080FF 83%, #0000FF 100%); 34 | } 35 | 36 | @keyframes spin { 37 | from { 38 | transform: rotate(0deg); 39 | } 40 | 41 | to { 42 | transform: rotate(360deg); 43 | } 44 | } 45 | 46 | .container { 47 | max-width: 640px; 48 | margin: 20px auto; 49 | padding: 20px; 50 | border: 1px solid #ddd; 51 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 52 | display: none; 53 | } 54 | 55 | h1 { 56 | text-align: center; 57 | } 58 | 59 | .connection { 60 | max-width: 640px; 61 | margin: 10px auto; 62 | padding: 20px; 63 | border: 1px solid #ddd; 64 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 65 | } 66 | 67 | input { 68 | width: 300px; 69 | } 70 | 71 | .filler { 72 | flex-grow: 1; 73 | } -------------------------------------------------------------------------------- /examples/barcode_ocr_text/main.js: -------------------------------------------------------------------------------- 1 | let activateButton = document.getElementById("activate-button"); 2 | let loadingIndicator = document.getElementById("loading-indicator"); 3 | let container = document.getElementById("container"); 4 | 5 | activateButton.onclick = async () => { 6 | loadingIndicator.style.display = "flex"; 7 | let inputText = document.getElementById("inputText").value; 8 | let text = inputText.trim(); 9 | let placeHolder = document.getElementById("inputText").placeholder; 10 | let license = text.length === 0 ? placeHolder : text; 11 | 12 | try { 13 | Dynamsoft.License.LicenseManager.initLicense(license); 14 | Dynamsoft.Core.CoreModule.loadWasm(["cvr", "dbr", "dlr",]); 15 | await Dynamsoft.CVR.CaptureVisionRouter.appendModelBuffer("LetterCharRecognition"); 16 | let router = await Dynamsoft.CVR.CaptureVisionRouter.createInstance(); 17 | 18 | let view = await Dynamsoft.DCE.CameraView.createInstance(); 19 | let cameraEnhancer = await Dynamsoft.DCE.CameraEnhancer.createInstance(view); 20 | 21 | document.querySelector("#cameraViewContainer").append(view.getUIElement()); 22 | router.setInput(cameraEnhancer); 23 | 24 | const resultsContainer = document.querySelector("#results"); 25 | const resultReceiver = new Dynamsoft.CVR.CapturedResultReceiver(); 26 | 27 | resultReceiver.onCapturedResultReceived = (result) => { 28 | if (result.items.length == 0) { 29 | resultsContainer.textContent = ''; 30 | } 31 | } 32 | 33 | resultReceiver.onDecodedBarcodesReceived = (result) => { 34 | 35 | if (result.barcodeResultItems.length > 0) { 36 | for (let item of result.barcodeResultItems) { 37 | resultsContainer.textContent += `Barcode Type: ${item.formatString}, Value: ${item.text}\n\n`; 38 | } 39 | } 40 | } 41 | 42 | resultReceiver.onRecognizedTextLinesReceived = (result) => { 43 | 44 | if (result.textLineResultItems.length > 0) { 45 | for (let item of result.textLineResultItems) { 46 | resultsContainer.textContent += `Text: ${item.text}\n`; 47 | } 48 | } 49 | }; 50 | router.addResultReceiver(resultReceiver); 51 | 52 | let filter = new Dynamsoft.Utility.MultiFrameResultCrossFilter(); 53 | filter.enableResultCrossVerification(Dynamsoft.Core.EnumCapturedResultItemType.CRIT_BARCODE | Dynamsoft.Core.EnumCapturedResultItemType.CRIT_TEXT_LINE, true); 54 | filter.enableResultDeduplication(Dynamsoft.Core.EnumCapturedResultItemType.CRIT_BARCODE | Dynamsoft.Core.EnumCapturedResultItemType.CRIT_TEXT_LINE, true); 55 | await router.addResultFilter(filter); 56 | await router.initSettings("./template.json"); 57 | 58 | await cameraEnhancer.open(); 59 | await router.startCapturing("ReadBarcode&AccompanyText"); 60 | loadingIndicator.style.display = "none"; 61 | container.style.display = "block"; 62 | } 63 | catch (ex) { 64 | alert(ex.message); 65 | loadingIndicator.style.display = "none"; 66 | } 67 | } 68 | 69 | 70 | -------------------------------------------------------------------------------- /examples/camera_only/README.md: -------------------------------------------------------------------------------- 1 | ## Accessing Front and Rear Cameras from Web Browsers 2 | 3 | This sample demonstrates how to use [Dynamsoft Camera Enhancer](https://www.dynamsoft.com/camera-enhancer/docs/programming/javascript/user-guide/?ver=latest) to access cameras from web browsers with just a few lines of code. 4 | 5 | ![iOS web browser camera access](https://www.dynamsoft.com/codepool/img/2022/02/ios-web-browser-camera-access.jpg) 6 | 7 | ## Online Demo 8 | https://yushulx.me/javascript-barcode-qr-code-scanner/examples/9.x/camera_only 9 | 10 | ## API Reference 11 | https://www.dynamsoft.com/camera-enhancer/docs/programming/javascript/api-reference/?ver=latest 12 | 13 | ## Blog 14 | [How to Implement Camera Access from Web Browsers in 5 Minutes](https://www.dynamsoft.com/codepool/web-browser-javascript-camera-access.html) 15 | -------------------------------------------------------------------------------- /examples/camera_only/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello Camera 6 | 7 | 8 | 9 | 10 | 11 |
12 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/mrz-vin-scanner/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript MRZ/VIN Scanner 2 | The sample demonstrates how to use **Dynamsoft Capture Vision** to scan **MRZ (Machine Readable Zone)** and **VIN (Vehicle Identification Number)** within a web browser. 3 | 4 | https://github.com/user-attachments/assets/e536e594-935e-4a31-9e3d-30ca4f929005 5 | 6 | ## Prerequisites 7 | - A valid [Trial License Key](https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform) for Dynamsoft Capture Vision. 8 | 9 | ## Online Demo 10 | https://yushulx.me/javascript-barcode-qr-code-scanner/examples/mrz-vin-scanner 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/mrz-vin-scanner/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yushulx/javascript-barcode-qr-code-scanner/d11a6439fc2f877b450a15646ece21686c1b8462/examples/mrz-vin-scanner/default.png -------------------------------------------------------------------------------- /examples/mrz-vin-scanner/full.json: -------------------------------------------------------------------------------- 1 | { 2 | "CaptureVisionModelOptions": [ 3 | { 4 | "ModelArgs": { 5 | "CharSet": { 6 | "ExcludeChars": [ 7 | "O", 8 | "Q", 9 | "I" 10 | ] 11 | } 12 | }, 13 | "Name": "VINCharRecognition" 14 | }, 15 | { 16 | "Name": "MRZCharRecognition", 17 | "DirectoryPath": "", 18 | "MaxModelInstances": 4 19 | }, 20 | { 21 | "Name": "MRZTextLineRecognition", 22 | "DirectoryPath": "", 23 | "MaxModelInstances": 1 24 | } 25 | ], 26 | "CaptureVisionTemplates": [ 27 | { 28 | "ImageROIProcessingNameArray": [ 29 | "roi-read-vin-text" 30 | ], 31 | "Name": "ReadVINText" 32 | }, 33 | { 34 | "ImageROIProcessingNameArray": [ 35 | "roi-mrz" 36 | ], 37 | "Name": "ReadMRZ", 38 | "SemanticProcessingNameArray": [ 39 | "sp-mrz" 40 | ], 41 | "Timeout": 1000000 42 | } 43 | ], 44 | "CodeParserTaskSettingOptions": [ 45 | { 46 | "CodeSpecifications": [ 47 | "MRTD_TD3_PASSPORT", 48 | "MRTD_TD2_VISA", 49 | "MRTD_TD3_VISA", 50 | "MRTD_TD1_ID", 51 | "MRTD_TD2_ID" 52 | ], 53 | "Name": "dcp-mrz" 54 | } 55 | ], 56 | "ImageParameterOptions": [ 57 | { 58 | "ApplicableStages": [ 59 | { 60 | "Stage": "SST_INPUT_COLOR_IMAGE" 61 | }, 62 | { 63 | "Stage": "SST_SCALE_IMAGE" 64 | }, 65 | { 66 | "Stage": "SST_CONVERT_TO_GRAYSCALE" 67 | }, 68 | { 69 | "GrayscaleTransformationModes": [ 70 | { 71 | "Mode": "GTM_ORIGINAL" 72 | }, 73 | { 74 | "Mode": "GTM_INVERTED" 75 | } 76 | ], 77 | "Stage": "SST_TRANSFORM_GRAYSCALE" 78 | }, 79 | { 80 | "Stage": "SST_ENHANCE_GRAYSCALE" 81 | }, 82 | { 83 | "Stage": "SST_BINARIZE_IMAGE" 84 | }, 85 | { 86 | "Stage": "SST_DETECT_TEXTURE" 87 | }, 88 | { 89 | "Stage": "SST_REMOVE_TEXTURE_FROM_GRAYSCALE" 90 | }, 91 | { 92 | "Stage": "SST_BINARIZE_TEXTURE_REMOVED_GRAYSCALE" 93 | }, 94 | { 95 | "Stage": "SST_FIND_CONTOURS" 96 | }, 97 | { 98 | "Stage": "SST_DETECT_SHORTLINES" 99 | }, 100 | { 101 | "Stage": "SST_ASSEMBLE_LINES" 102 | }, 103 | { 104 | "Stage": "SST_DETECT_TEXT_ZONES", 105 | "TextDetectionMode": { 106 | "CharHeightRange": [ 107 | 5, 108 | 1000, 109 | 1 110 | ], 111 | "Direction": "HORIZONTAL", 112 | "Mode": "TTDM_LINE", 113 | "Sensitivity": 7 114 | } 115 | }, 116 | { 117 | "Stage": "SST_REMOVE_TEXT_ZONES_FROM_BINARY" 118 | } 119 | ], 120 | "Name": "ip_recognize_text" 121 | }, 122 | { 123 | "ApplicableStages": [ 124 | { 125 | "Stage": "SST_INPUT_COLOR_IMAGE" 126 | }, 127 | { 128 | "Stage": "SST_SCALE_IMAGE" 129 | }, 130 | { 131 | "Stage": "SST_CONVERT_TO_GRAYSCALE" 132 | }, 133 | { 134 | "Stage": "SST_TRANSFORM_GRAYSCALE" 135 | }, 136 | { 137 | "Stage": "SST_ENHANCE_GRAYSCALE" 138 | }, 139 | { 140 | "BinarizationModes": [ 141 | { 142 | "EnableFillBinaryVacancy": 0, 143 | "Mode": "BM_LOCAL_BLOCK", 144 | "ThresholdCompensation": 21 145 | } 146 | ], 147 | "Stage": "SST_BINARIZE_IMAGE" 148 | }, 149 | { 150 | "Stage": "SST_DETECT_TEXTURE", 151 | "TextureDetectionModes": [ 152 | { 153 | "Mode": "TDM_GENERAL_WIDTH_CONCENTRATION", 154 | "Sensitivity": 8 155 | } 156 | ] 157 | }, 158 | { 159 | "Stage": "SST_REMOVE_TEXTURE_FROM_GRAYSCALE" 160 | }, 161 | { 162 | "Stage": "SST_BINARIZE_TEXTURE_REMOVED_GRAYSCALE" 163 | }, 164 | { 165 | "Stage": "SST_FIND_CONTOURS" 166 | }, 167 | { 168 | "Stage": "SST_DETECT_SHORTLINES" 169 | }, 170 | { 171 | "Stage": "SST_ASSEMBLE_LINES" 172 | }, 173 | { 174 | "Stage": "SST_DETECT_TEXT_ZONES", 175 | "TextDetectionMode": { 176 | "CharHeightRange": [ 177 | 5, 178 | 1000, 179 | 1 180 | ], 181 | "Direction": "HORIZONTAL", 182 | "Mode": "TTDM_LINE", 183 | "Sensitivity": 7 184 | } 185 | }, 186 | { 187 | "Stage": "SST_REMOVE_TEXT_ZONES_FROM_BINARY" 188 | } 189 | ], 190 | "Name": "ip-mrz" 191 | } 192 | ], 193 | "LabelRecognizerTaskSettingOptions": [ 194 | { 195 | "Name": "task-read-vin-text", 196 | "SectionArray": [ 197 | { 198 | "ImageParameterName": "ip_recognize_text", 199 | "Section": "ST_REGION_PREDETECTION", 200 | "StageArray": [ 201 | { 202 | "Stage": "SST_PREDETECT_REGIONS" 203 | } 204 | ] 205 | }, 206 | { 207 | "ImageParameterName": "ip_recognize_text", 208 | "Section": "ST_TEXT_LINE_LOCALIZATION", 209 | "StageArray": [ 210 | { 211 | "Stage": "SST_LOCALIZE_TEXT_LINES" 212 | } 213 | ] 214 | }, 215 | { 216 | "ImageParameterName": "ip_recognize_text", 217 | "Section": "ST_TEXT_LINE_RECOGNITION", 218 | "StageArray": [ 219 | { 220 | "Stage": "SST_RECOGNIZE_RAW_TEXT_LINES" 221 | }, 222 | { 223 | "Stage": "SST_ASSEMBLE_TEXT_LINES" 224 | } 225 | ] 226 | } 227 | ], 228 | "TextLineSpecificationNameArray": [ 229 | "tls_vin_text" 230 | ] 231 | }, 232 | { 233 | "Name": "task-mrz", 234 | "SectionArray": [ 235 | { 236 | "ImageParameterName": "ip-mrz", 237 | "Section": "ST_REGION_PREDETECTION", 238 | "StageArray": [ 239 | { 240 | "Stage": "SST_PREDETECT_REGIONS" 241 | } 242 | ] 243 | }, 244 | { 245 | "ImageParameterName": "ip-mrz", 246 | "Section": "ST_TEXT_LINE_LOCALIZATION", 247 | "StageArray": [ 248 | { 249 | "Stage": "SST_LOCALIZE_TEXT_LINES" 250 | } 251 | ] 252 | }, 253 | { 254 | "ImageParameterName": "ip-mrz", 255 | "Section": "ST_TEXT_LINE_RECOGNITION", 256 | "StageArray": [ 257 | { 258 | "ConfusableCharactersPath": "ConfusableChars.data", 259 | "Stage": "SST_RECOGNIZE_RAW_TEXT_LINES" 260 | }, 261 | { 262 | "Stage": "SST_ASSEMBLE_TEXT_LINES" 263 | } 264 | ] 265 | } 266 | ], 267 | "TextLineSpecificationNameArray": [ 268 | "tls-mrz-passport", 269 | "tls-mrz-visa-td3", 270 | "tls-mrz-id-td1", 271 | "tls-mrz-id-td2", 272 | "tls-mrz-visa-td2" 273 | ] 274 | } 275 | ], 276 | "SemanticProcessingOptions": [ 277 | { 278 | "Name": "sp-mrz", 279 | "ReferenceObjectFilter": { 280 | "ReferenceTargetROIDefNameArray": [ 281 | "roi-mrz" 282 | ] 283 | }, 284 | "TaskSettingNameArray": [ 285 | "dcp-mrz" 286 | ] 287 | } 288 | ], 289 | "TargetROIDefOptions": [ 290 | { 291 | "Name": "roi-read-vin-text", 292 | "TaskSettingNameArray": [ 293 | "task-read-vin-text" 294 | ] 295 | }, 296 | { 297 | "Name": "roi-mrz", 298 | "TaskSettingNameArray": [ 299 | "task-mrz" 300 | ] 301 | } 302 | ], 303 | "TextLineSpecificationOptions": [ 304 | { 305 | "CharHeightRange": [ 306 | 5, 307 | 1000, 308 | 1 309 | ], 310 | "CharacterModelName": "VINCharRecognition", 311 | "ConcatSeparator": "\\n", 312 | "Name": "tls_vin_text", 313 | "StringLengthRange": [ 314 | 17, 315 | 17 316 | ], 317 | "StringRegExPattern": "[0-9A-HJ-NPR-Z]{9}[1-9A-HJ-NPR-TV-Y][0-9A-HJ-NPR-Z]{2}[0-9]{5}", 318 | "TextLinesCount": 1 319 | }, 320 | { 321 | "BaseTextLineSpecificationName": "tls-base", 322 | "ConcatResults": 1, 323 | "ConcatSeparator": "\\n", 324 | "Name": "tls-mrz-passport", 325 | "StringLengthRange": [ 326 | 44, 327 | 44 328 | ], 329 | "SubGroups": [ 330 | { 331 | "BaseTextLineSpecificationName": "tls-base", 332 | "StringLengthRange": [ 333 | 44, 334 | 44 335 | ], 336 | "StringRegExPattern": "(P[A-Z<][A-Z<]{3}[A-Z<]{39}){(44)}" 337 | }, 338 | { 339 | "BaseTextLineSpecificationName": "tls-base", 340 | "StringLengthRange": [ 341 | 44, 342 | 44 343 | ], 344 | "StringRegExPattern": "([A-Z0-9<]{9}[0-9][A-Z<]{3}[0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z0-9<]{14}[0-9<][0-9]){(44)}" 345 | } 346 | ] 347 | }, 348 | { 349 | "BaseTextLineSpecificationName": "tls-base", 350 | "ConcatResults": 1, 351 | "ConcatSeparator": "\\n", 352 | "Name": "tls-mrz-visa-td3", 353 | "StringLengthRange": [ 354 | 44, 355 | 44 356 | ], 357 | "SubGroups": [ 358 | { 359 | "BaseTextLineSpecificationName": "tls-base", 360 | "StringLengthRange": [ 361 | 44, 362 | 44 363 | ], 364 | "StringRegExPattern": "(V[A-Z<][A-Z<]{3}[A-Z<]{39}){(44)}" 365 | }, 366 | { 367 | "BaseTextLineSpecificationName": "tls-base", 368 | "StringLengthRange": [ 369 | 44, 370 | 44 371 | ], 372 | "StringRegExPattern": "([A-Z0-9<]{9}[0-9][A-Z<]{3}[0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z0-9<]{14}[A-Z0-9<]{2}){(44)}" 373 | } 374 | ] 375 | }, 376 | { 377 | "BaseTextLineSpecificationName": "tls-base", 378 | "ConcatResults": 1, 379 | "ConcatSeparator": "\\n", 380 | "Name": "tls-mrz-visa-td2", 381 | "StringLengthRange": [ 382 | 36, 383 | 36 384 | ], 385 | "SubGroups": [ 386 | { 387 | "BaseTextLineSpecificationName": "tls-base", 388 | "StringLengthRange": [ 389 | 36, 390 | 36 391 | ], 392 | "StringRegExPattern": "(V[A-Z<][A-Z<]{3}[A-Z<]{31}){(36)}" 393 | }, 394 | { 395 | "BaseTextLineSpecificationName": "tls-base", 396 | "StringLengthRange": [ 397 | 36, 398 | 36 399 | ], 400 | "StringRegExPattern": "([A-Z0-9<]{9}[0-9][A-Z<]{3}[0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z0-9<]{8}){(36)}" 401 | } 402 | ] 403 | }, 404 | { 405 | "BaseTextLineSpecificationName": "tls-base", 406 | "ConcatResults": 1, 407 | "ConcatSeparator": "\\n", 408 | "Name": "tls-mrz-id-td2", 409 | "StringLengthRange": [ 410 | 36, 411 | 36 412 | ], 413 | "SubGroups": [ 414 | { 415 | "BaseTextLineSpecificationName": "tls-base", 416 | "StringLengthRange": [ 417 | 36, 418 | 36 419 | ], 420 | "StringRegExPattern": "([ACI][A-Z<][A-Z<]{3}[A-Z<]{31}){(36)}" 421 | }, 422 | { 423 | "BaseTextLineSpecificationName": "tls-base", 424 | "StringLengthRange": [ 425 | 36, 426 | 36 427 | ], 428 | "StringRegExPattern": "([A-Z0-9<]{9}[0-9][A-Z<]{3}[0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z0-9<]{8}){(36)}" 429 | } 430 | ] 431 | }, 432 | { 433 | "BaseTextLineSpecificationName": "tls-base", 434 | "ConcatResults": 1, 435 | "ConcatSeparator": "\\n", 436 | "Name": "tls-mrz-id-td1", 437 | "StringLengthRange": [ 438 | 30, 439 | 30 440 | ], 441 | "SubGroups": [ 442 | { 443 | "BaseTextLineSpecificationName": "tls-base", 444 | "StringLengthRange": [ 445 | 30, 446 | 30 447 | ], 448 | "StringRegExPattern": "([ACI][A-Z<][A-Z<]{3}[A-Z0-9<]{9}[0-9][A-Z0-9<]{15}){(30)}" 449 | }, 450 | { 451 | "BaseTextLineSpecificationName": "tls-base", 452 | "StringLengthRange": [ 453 | 30, 454 | 30 455 | ], 456 | "StringRegExPattern": "([0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z<]{3}[A-Z0-9<]{11}[0-9]){(30)}" 457 | }, 458 | { 459 | "BaseTextLineSpecificationName": "tls-base", 460 | "StringLengthRange": [ 461 | 30, 462 | 30 463 | ], 464 | "StringRegExPattern": "([A-Z<]{30}){(30)}" 465 | } 466 | ] 467 | }, 468 | { 469 | "BinarizationModes": [ 470 | { 471 | "BlockSizeX": 30, 472 | "BlockSizeY": 30, 473 | "EnableFillBinaryVacancy": 0, 474 | "Mode": "BM_LOCAL_BLOCK", 475 | "ThresholdCompensation": 15 476 | } 477 | ], 478 | "CharHeightRange": [ 479 | 5, 480 | 1000, 481 | 1 482 | ], 483 | "CharacterModelName": "MRZCharRecognition", 484 | "TextLineRecModelName": "MRZTextLineRecognition", 485 | "ConfusableCharactersCorrection": { 486 | "ConfusableCharacters": [ 487 | [ 488 | "0", 489 | "O" 490 | ], 491 | [ 492 | "1", 493 | "I" 494 | ], 495 | [ 496 | "5", 497 | "S" 498 | ] 499 | ], 500 | "FontNameArray": [ 501 | "OCR_B" 502 | ] 503 | }, 504 | "Name": "tls-base" 505 | } 506 | ] 507 | } -------------------------------------------------------------------------------- /examples/mrz-vin-scanner/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Dynamsoft Capture Vision SDKs 10 | 11 | 12 | 13 |

MRZ/VIN Scanner

14 |
15 |
16 |
17 | 18 | 19 |
20 |
21 |
22 | 27 | 30 | 31 |
32 |
33 | 34 |
35 |
36 | 40 |
41 | 45 | 49 |
50 |
51 |
52 |
53 | 54 | 55 |
56 |
57 | 58 |
59 | 60 |
61 |
62 | 63 | 64 |
65 |
66 | 67 |
68 |
69 | 70 |
71 |
72 | 73 |
74 | 75 | 76 |
77 |
78 | 80 | 81 |
82 |
83 |
84 | 85 |
86 |
87 | 88 |
89 |
90 | 91 |
92 |
93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /examples/mrz-vin-scanner/mrz.json: -------------------------------------------------------------------------------- 1 | { 2 | "CaptureVisionTemplates": [ 3 | { 4 | "Name": "ReadMRZ", 5 | "OutputOriginalImage": 0, 6 | "ImageROIProcessingNameArray": [ 7 | "roi-mrz" 8 | ], 9 | "SemanticProcessingNameArray": [ 10 | "sp-mrz" 11 | ], 12 | "Timeout": 1000000 13 | } 14 | ], 15 | "TargetROIDefOptions": [ 16 | { 17 | "Name": "roi-mrz", 18 | "TaskSettingNameArray": [ 19 | "task-mrz" 20 | ] 21 | } 22 | ], 23 | "TextLineSpecificationOptions": [ 24 | { 25 | "Name": "tls-mrz-passport", 26 | "BaseTextLineSpecificationName": "tls-base", 27 | "StringLengthRange": [ 28 | 44, 29 | 44 30 | ], 31 | "OutputResults": 1, 32 | "ExpectedGroupsCount": 1, 33 | "ConcatResults": 1, 34 | "ConcatSeparator": "\\n", 35 | "SubGroups": [ 36 | { 37 | "StringRegExPattern": "(P[A-Z<][A-Z<]{3}[A-Z<]{39}){(44)}", 38 | "StringLengthRange": [ 39 | 44, 40 | 44 41 | ], 42 | "BaseTextLineSpecificationName": "tls-base" 43 | }, 44 | { 45 | "StringRegExPattern": "([A-Z0-9<]{9}[0-9][A-Z<]{3}[0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z0-9<]{14}[0-9<][0-9]){(44)}", 46 | "StringLengthRange": [ 47 | 44, 48 | 44 49 | ], 50 | "BaseTextLineSpecificationName": "tls-base" 51 | } 52 | ] 53 | }, 54 | { 55 | "Name": "tls-mrz-visa-td3", 56 | "BaseTextLineSpecificationName": "tls-base", 57 | "StringLengthRange": [ 58 | 44, 59 | 44 60 | ], 61 | "OutputResults": 1, 62 | "ExpectedGroupsCount": 1, 63 | "ConcatResults": 1, 64 | "ConcatSeparator": "\\n", 65 | "SubGroups": [ 66 | { 67 | "StringRegExPattern": "(V[A-Z<][A-Z<]{3}[A-Z<]{39}){(44)}", 68 | "StringLengthRange": [ 69 | 44, 70 | 44 71 | ], 72 | "BaseTextLineSpecificationName": "tls-base" 73 | }, 74 | { 75 | "StringRegExPattern": "([A-Z0-9<]{9}[0-9][A-Z<]{3}[0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z0-9<]{14}[A-Z0-9<]{2}){(44)}", 76 | "StringLengthRange": [ 77 | 44, 78 | 44 79 | ], 80 | "BaseTextLineSpecificationName": "tls-base" 81 | } 82 | ] 83 | }, 84 | { 85 | "Name": "tls-mrz-visa-td2", 86 | "BaseTextLineSpecificationName": "tls-base", 87 | "StringLengthRange": [ 88 | 36, 89 | 36 90 | ], 91 | "OutputResults": 1, 92 | "ExpectedGroupsCount": 1, 93 | "ConcatResults": 1, 94 | "ConcatSeparator": "\\n", 95 | "SubGroups": [ 96 | { 97 | "StringRegExPattern": "(V[A-Z<][A-Z<]{3}[A-Z<]{31}){(36)}", 98 | "StringLengthRange": [ 99 | 36, 100 | 36 101 | ], 102 | "BaseTextLineSpecificationName": "tls-base" 103 | }, 104 | { 105 | "StringRegExPattern": "([A-Z0-9<]{9}[0-9][A-Z<]{3}[0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z0-9<]{8}){(36)}", 106 | "StringLengthRange": [ 107 | 36, 108 | 36 109 | ], 110 | "BaseTextLineSpecificationName": "tls-base" 111 | } 112 | ] 113 | }, 114 | { 115 | "Name": "tls-mrz-id-td2", 116 | "BaseTextLineSpecificationName": "tls-base", 117 | "StringLengthRange": [ 118 | 36, 119 | 36 120 | ], 121 | "OutputResults": 1, 122 | "ExpectedGroupsCount": 1, 123 | "ConcatResults": 1, 124 | "ConcatSeparator": "\\n", 125 | "SubGroups": [ 126 | { 127 | "StringRegExPattern": "([ACI][A-Z<][A-Z<]{3}[A-Z<]{31}){(36)}", 128 | "StringLengthRange": [ 129 | 36, 130 | 36 131 | ], 132 | "BaseTextLineSpecificationName": "tls-base" 133 | }, 134 | { 135 | "StringRegExPattern": "([A-Z0-9<]{9}[0-9][A-Z<]{3}[0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z0-9<]{8}){(36)}", 136 | "StringLengthRange": [ 137 | 36, 138 | 36 139 | ], 140 | "BaseTextLineSpecificationName": "tls-base" 141 | } 142 | ] 143 | }, 144 | { 145 | "Name": "tls-mrz-id-td1", 146 | "BaseTextLineSpecificationName": "tls-base", 147 | "StringLengthRange": [ 148 | 30, 149 | 30 150 | ], 151 | "OutputResults": 1, 152 | "ExpectedGroupsCount": 1, 153 | "ConcatResults": 1, 154 | "ConcatSeparator": "\\n", 155 | "SubGroups": [ 156 | { 157 | "StringRegExPattern": "([ACI][A-Z<][A-Z<]{3}[A-Z0-9<]{9}[0-9][A-Z0-9<]{15}){(30)}", 158 | "StringLengthRange": [ 159 | 30, 160 | 30 161 | ], 162 | "BaseTextLineSpecificationName": "tls-base" 163 | }, 164 | { 165 | "StringRegExPattern": "([0-9]{2}[(01-12)][(01-31)][0-9][MF<][0-9]{2}[(01-12)][(01-31)][0-9][A-Z<]{3}[A-Z0-9<]{11}[0-9]){(30)}", 166 | "StringLengthRange": [ 167 | 30, 168 | 30 169 | ], 170 | "BaseTextLineSpecificationName": "tls-base" 171 | }, 172 | { 173 | "StringRegExPattern": "([A-Z<]{30}){(30)}", 174 | "StringLengthRange": [ 175 | 30, 176 | 30 177 | ], 178 | "BaseTextLineSpecificationName": "tls-base" 179 | } 180 | ] 181 | }, 182 | { 183 | "Name": "tls-base", 184 | "CharacterModelName": "MRZ", 185 | "CharHeightRange": [ 186 | 5, 187 | 1000, 188 | 1 189 | ], 190 | "BinarizationModes": [ 191 | { 192 | "BlockSizeX": 30, 193 | "BlockSizeY": 30, 194 | "Mode": "BM_LOCAL_BLOCK", 195 | "EnableFillBinaryVacancy": 0, 196 | "ThresholdCompensation": 15 197 | } 198 | ], 199 | "ConfusableCharactersCorrection": { 200 | "ConfusableCharacters": [ 201 | [ 202 | "0", 203 | "O" 204 | ], 205 | [ 206 | "1", 207 | "I" 208 | ], 209 | [ 210 | "5", 211 | "S" 212 | ] 213 | ], 214 | "FontNameArray": [ 215 | "OCR_B" 216 | ] 217 | } 218 | } 219 | ], 220 | "LabelRecognizerTaskSettingOptions": [ 221 | { 222 | "Name": "task-mrz", 223 | "ConfusableCharactersPath": "ConfusableChars.data", 224 | "TextLineSpecificationNameArray": [ 225 | "tls-mrz-passport", 226 | "tls-mrz-visa-td3", 227 | "tls-mrz-id-td1", 228 | "tls-mrz-id-td2", 229 | "tls-mrz-visa-td2" 230 | ], 231 | "SectionImageParameterArray": [ 232 | { 233 | "Section": "ST_REGION_PREDETECTION", 234 | "ImageParameterName": "ip-mrz" 235 | }, 236 | { 237 | "Section": "ST_TEXT_LINE_LOCALIZATION", 238 | "ImageParameterName": "ip-mrz" 239 | }, 240 | { 241 | "Section": "ST_TEXT_LINE_RECOGNITION", 242 | "ImageParameterName": "ip-mrz" 243 | } 244 | ] 245 | } 246 | ], 247 | "CharacterModelOptions": [ 248 | { 249 | "DirectoryPath": "", 250 | "Name": "MRZ" 251 | } 252 | ], 253 | "ImageParameterOptions": [ 254 | { 255 | "Name": "ip-mrz", 256 | "TextureDetectionModes": [ 257 | { 258 | "Mode": "TDM_GENERAL_WIDTH_CONCENTRATION", 259 | "Sensitivity": 8 260 | } 261 | ], 262 | "BinarizationModes": [ 263 | { 264 | "EnableFillBinaryVacancy": 0, 265 | "ThresholdCompensation": 21, 266 | "Mode": "BM_LOCAL_BLOCK" 267 | } 268 | ], 269 | "TextDetectionMode": { 270 | "Mode": "TTDM_LINE", 271 | "CharHeightRange": [ 272 | 5, 273 | 1000, 274 | 1 275 | ], 276 | "Direction": "HORIZONTAL", 277 | "Sensitivity": 7 278 | } 279 | } 280 | ], 281 | "SemanticProcessingOptions": [ 282 | { 283 | "Name": "sp-mrz", 284 | "ReferenceObjectFilter": { 285 | "ReferenceTargetROIDefNameArray": [ 286 | "roi-mrz" 287 | ] 288 | }, 289 | "TaskSettingNameArray": [ 290 | "dcp-mrz" 291 | ] 292 | } 293 | ], 294 | "CodeParserTaskSettingOptions": [ 295 | { 296 | "Name": "dcp-mrz", 297 | "CodeSpecifications": [ 298 | "MRTD_TD3_PASSPORT", 299 | "MRTD_TD2_VISA", 300 | "MRTD_TD3_VISA", 301 | "MRTD_TD1_ID", 302 | "MRTD_TD2_ID" 303 | ] 304 | } 305 | ] 306 | } -------------------------------------------------------------------------------- /examples/mrz-vin-scanner/styles.css: -------------------------------------------------------------------------------- 1 | .row { 2 | display: flex; 3 | justify-content: space-between; 4 | margin: 10px auto; 5 | align-items: center; 6 | } 7 | 8 | .container { 9 | max-width: 720px; 10 | margin: 20px auto; 11 | padding: 20px; 12 | border: 1px solid #ddd; 13 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 14 | } 15 | 16 | .loading-indicator { 17 | position: absolute; 18 | top: 0; 19 | left: 0; 20 | width: 100%; 21 | height: 100%; 22 | background-color: rgba(0, 0, 0, 0.5); 23 | z-index: 1000; 24 | display: none; 25 | align-items: center; 26 | justify-content: center; 27 | } 28 | 29 | .spinner { 30 | width: 50px; 31 | height: 50px; 32 | border: 5px solid #fff; 33 | border-radius: 50%; 34 | animation: spin 1s linear infinite; 35 | background: linear-gradient(to right, #FF0000 0%, #FF8000 17%, #FFFF00 33%, #00FF00 50%, #00FFFF 67%, #0080FF 83%, #0000FF 100%); 36 | } 37 | 38 | @keyframes spin { 39 | from { 40 | transform: rotate(0deg); 41 | } 42 | 43 | to { 44 | transform: rotate(360deg); 45 | } 46 | } 47 | 48 | .filler { 49 | flex-grow: 1; 50 | } 51 | 52 | #imageGrid { 53 | width: 720px; 54 | height: 720px; 55 | margin: auto; 56 | display: grid; 57 | grid-template-columns: repeat(2, 1fr); 58 | gap: 50px; 59 | } 60 | 61 | .editor { 62 | display: flex; 63 | margin: 10px auto; 64 | align-items: center; 65 | } 66 | 67 | #videoview { 68 | position: relative; 69 | width: 100%; 70 | height: 40vh; 71 | } 72 | 73 | #videoContainer { 74 | position: relative; 75 | width: 100%; 76 | height: 100%; 77 | z-index: 1 78 | } 79 | 80 | #imageGrid { 81 | width: 720px; 82 | height: 720px; 83 | margin: auto; 84 | display: grid; 85 | grid-template-columns: repeat(2, 1fr); 86 | gap: 50px; 87 | } 88 | 89 | #camera_container { 90 | display: none; 91 | } 92 | 93 | h1 { 94 | text-align: center; 95 | } 96 | 97 | .imageview { 98 | max-width: 720px; 99 | max-height: 720px; 100 | width: 720px; 101 | height: 720px; 102 | border: 1px solid #ddd; 103 | background-color: #eaeaea; 104 | position: relative; 105 | } 106 | 107 | .imageview img { 108 | display: block; 109 | width: 100%; 110 | height: 100%; 111 | object-fit: contain 112 | } 113 | 114 | #sources { 115 | width: 200px; 116 | } 117 | 118 | #dropdown { 119 | width: 200px; 120 | } 121 | 122 | textarea { 123 | width: 680px; 124 | height: 100px; 125 | margin: 10px auto; 126 | padding: 20px; 127 | border: 1px solid #ddd; 128 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 129 | } 130 | 131 | button { 132 | padding: 4px; 133 | margin: 4px; 134 | border: none; 135 | background-color: #007BFF; 136 | color: #fff; 137 | cursor: pointer; 138 | border-radius: 5px; 139 | } 140 | 141 | #drop_area { 142 | border: 2px dashed #ccc; 143 | border-radius: 5px; 144 | padding: 50px; 145 | text-align: center; 146 | margin: 20px; 147 | } 148 | 149 | #drop_area:hover { 150 | background-color: #f8f8f8; 151 | } 152 | 153 | .overlay { 154 | position: absolute; 155 | top: 0; 156 | left: 0; 157 | width: 100%; 158 | height: 100%; 159 | object-fit: contain 160 | } 161 | 162 | #document_editor { 163 | display: none; 164 | } 165 | 166 | #rectify_view { 167 | display: none; 168 | } 169 | 170 | #camera_view { 171 | width: 100%; 172 | height: 100%; 173 | object-fit: contain 174 | } -------------------------------------------------------------------------------- /examples/mrz-vin-scanner/vin.json: -------------------------------------------------------------------------------- 1 | { 2 | "CaptureVisionTemplates": [ 3 | { 4 | "Name": "ReadVINText", 5 | "ImageROIProcessingNameArray": [ 6 | "roi-read-vin-text" 7 | ], 8 | "ImageSource": "", 9 | "MaxParallelTasks": 4, 10 | "MinImageCaptureInterval": 0, 11 | "OutputOriginalImage": 0, 12 | "Timeout": 10000 13 | } 14 | ], 15 | "TargetROIDefOptions": [ 16 | { 17 | "Name": "roi-read-vin-text", 18 | "TaskSettingNameArray": [ 19 | "task-read-vin-text" 20 | ] 21 | } 22 | ], 23 | "CharacterModelOptions": [ 24 | { 25 | "CharSet": { 26 | "ExcludeChars": [ 27 | "O", 28 | "Q", 29 | "I" 30 | ] 31 | }, 32 | "DirectoryPath": "", 33 | "Name": "VIN" 34 | } 35 | ], 36 | "ImageParameterOptions": [ 37 | { 38 | "BaseImageParameterName": "", 39 | "BinarizationModes": [ 40 | { 41 | "BinarizationThreshold": -1, 42 | "BlockSizeX": 0, 43 | "BlockSizeY": 0, 44 | "EnableFillBinaryVacancy": 1, 45 | "GrayscaleEnhancementModesIndex": -1, 46 | "Mode": "BM_LOCAL_BLOCK", 47 | "MorphOperation": "Close", 48 | "MorphOperationKernelSizeX": -1, 49 | "MorphOperationKernelSizeY": -1, 50 | "MorphShape": "Rectangle", 51 | "ThresholdCompensation": 10 52 | } 53 | ], 54 | "ColourConversionModes": [ 55 | { 56 | "BlueChannelWeight": -1, 57 | "GreenChannelWeight": -1, 58 | "Mode": "CICM_GENERAL", 59 | "RedChannelWeight": -1, 60 | "ReferChannel": "H_CHANNEL" 61 | } 62 | ], 63 | "GrayscaleEnhancementModes": [ 64 | { 65 | "Mode": "GEM_GENERAL", 66 | "Sensitivity": -1, 67 | "SharpenBlockSizeX": -1, 68 | "SharpenBlockSizeY": -1, 69 | "SmoothBlockSizeX": -1, 70 | "SmoothBlockSizeY": -1 71 | } 72 | ], 73 | "GrayscaleTransformationModes": [ 74 | { 75 | "Mode": "GTM_ORIGINAL" 76 | }, 77 | { 78 | "Mode": "GTM_INVERTED" 79 | } 80 | ], 81 | "IfEraseTextZone": 0, 82 | "Name": "ip_recognize_text", 83 | "RegionPredetectionModes": [ 84 | { 85 | "AspectRatioRange": "[]", 86 | "FindAccurateBoundary": 0, 87 | "ForeAndBackgroundColours": "[]", 88 | "HeightRange": "[]", 89 | "ImageParameterName": "", 90 | "MeasuredByPercentage": 1, 91 | "MinImageDimension": 262144, 92 | "Mode": "RPM_GENERAL", 93 | "RelativeRegions": "[]", 94 | "Sensitivity": 1, 95 | "SpatialIndexBlockSize": 5, 96 | "WidthRange": "[]" 97 | } 98 | ], 99 | "ScaleDownThreshold": 2300, 100 | "ScaleUpModes": [ 101 | { 102 | "AcuteAngleWithXThreshold": -1, 103 | "LetterHeightThreshold": 0, 104 | "Mode": "SUM_AUTO", 105 | "ModuleSizeThreshold": 0, 106 | "TargetLetterHeight": 0, 107 | "TargetModuleSize": 0 108 | } 109 | ], 110 | "TextDetectionMode": { 111 | "CharHeightRange": [ 112 | 5, 113 | 1000, 114 | 1 115 | ], 116 | "Direction": "HORIZONTAL", 117 | "MaxSpacingInALine": -1, 118 | "Mode": "TTDM_LINE", 119 | "Sensitivity": 7, 120 | "StringLengthRange": null 121 | }, 122 | "TextureDetectionModes": [ 123 | { 124 | "Mode": "TDM_GENERAL_WIDTH_CONCENTRATION", 125 | "Sensitivity": 5 126 | } 127 | ] 128 | } 129 | ], 130 | "LabelRecognizerTaskSettingOptions": [ 131 | { 132 | "Name": "task-read-vin-text", 133 | "TextLineSpecificationNameArray": [ 134 | "tls_vin_text" 135 | ], 136 | "SectionImageParameterArray": [ 137 | { 138 | "ContinueWhenPartialResultsGenerated": 1, 139 | "ImageParameterName": "ip_recognize_text", 140 | "Section": "ST_REGION_PREDETECTION" 141 | }, 142 | { 143 | "ContinueWhenPartialResultsGenerated": 1, 144 | "ImageParameterName": "ip_recognize_text", 145 | "Section": "ST_TEXT_LINE_LOCALIZATION" 146 | }, 147 | { 148 | "ContinueWhenPartialResultsGenerated": 1, 149 | "ImageParameterName": "ip_recognize_text", 150 | "Section": "ST_TEXT_LINE_RECOGNITION" 151 | } 152 | ] 153 | } 154 | ], 155 | "TextLineSpecificationOptions": [ 156 | { 157 | "BinarizationModes": [ 158 | { 159 | "BinarizationThreshold": -1, 160 | "BlockSizeX": 11, 161 | "BlockSizeY": 11, 162 | "EnableFillBinaryVacancy": 1, 163 | "GrayscaleEnhancementModesIndex": -1, 164 | "Mode": "BM_LOCAL_BLOCK", 165 | "MorphOperation": "Erode", 166 | "MorphOperationKernelSizeX": -1, 167 | "MorphOperationKernelSizeY": -1, 168 | "MorphShape": "Rectangle", 169 | "ThresholdCompensation": 10 170 | } 171 | ], 172 | "CharHeightRange": [ 173 | 5, 174 | 1000, 175 | 1 176 | ], 177 | "CharacterModelName": "VIN", 178 | "CharacterNormalizationModes": [ 179 | { 180 | "Mode": "CNM_AUTO", 181 | "MorphArgument": "3", 182 | "MorphOperation": "Close" 183 | } 184 | ], 185 | "ConcatResults": 0, 186 | "ConcatSeparator": "\\n", 187 | "ConcatStringLengthRange": [ 188 | 3, 189 | 200 190 | ], 191 | "ExpectedGroupsCount": 1, 192 | "GrayscaleEnhancementModes": [ 193 | { 194 | "Mode": "GEM_GENERAL", 195 | "Sensitivity": -1, 196 | "SharpenBlockSizeX": -1, 197 | "SharpenBlockSizeY": -1, 198 | "SmoothBlockSizeX": -1, 199 | "SmoothBlockSizeY": -1 200 | } 201 | ], 202 | "Name": "tls_vin_text", 203 | "OutputResults": 1, 204 | "StringLengthRange": [ 205 | 17, 206 | 17 207 | ], 208 | "StringRegExPattern": "[0-9A-HJ-NPR-Z]{9}[1-9A-HJ-NPR-TV-Y][0-9A-HJ-NPR-Z]{2}[0-9]{5}", 209 | "SubGroups": null, 210 | "TextLinesCount": 1 211 | } 212 | ] 213 | } -------------------------------------------------------------------------------- /examples/mrz_scanner_rtu/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript MRZ Scanner – HTML5 & JavaScript Web SDK Example 2 | 3 | This project demonstrates how to create a **web-based Machine Readable Zone (MRZ) scanner** using **HTML5** and **JavaScript**, leveraging the **Dynamsoft MRZ Scanner SDK**. It supports scanning MRZ from **passports**, **ID cards**, and **visa documents** via **camera** or by uploading image and **PDF** files. 4 | 5 | https://github.com/user-attachments/assets/2a7b70e8-8cc6-4563-8925-8a1f7800b093 6 | 7 | ## Prerequisites 8 | - **License Key**: Please obtain a license key from [Dynamsoft Website](https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform). 9 | - **Dynamsoft MRZ Scanner**: Read and scan MRZ from passport, ID card, and visa documents. 10 | 11 | ```html 12 | 13 | ``` 14 | 15 | - **Dynamsoft Document Viewer**: Convert PDF files to JPEG images in web browser. 16 | 17 | ```html 18 | 19 | ``` 20 | 21 | ## Online Demo 22 | https://yushulx.me/javascript-barcode-qr-code-scanner/examples/mrz_scanner_rtu/ 23 | 24 | ## Features 25 | - Real-time MRZ scanning using webcam 26 | - Upload and scan MRZ from: 27 | - Image files (PNG, JPEG) 28 | - PDF documents 29 | - Displays parsed MRZ result in structured format 30 | -------------------------------------------------------------------------------- /examples/mrz_scanner_rtu/helloworld.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dynamsoft MRZ Scanner - Hello World 8 | 9 | 10 | 11 | 12 |

Dynamsoft MRZ Scanner

13 | 14 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/mrz_scanner_rtu/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dynamsoft MRZ Scanner - Hello World 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 | 18 |

Dynamsoft MRZ Scanner

19 |
20 | 25 | 27 | 28 |
29 |
30 | 31 | 32 |
33 |
34 |
35 |
36 |
37 | 38 | 39 | 40 | 234 | 235 | 236 | -------------------------------------------------------------------------------- /examples/mrz_scanner_rtu/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | justify-content: top; 6 | height: 100vh; 7 | margin: 0; 8 | font-family: Arial, sans-serif; 9 | overflow-y: auto; 10 | height: 100%; 11 | } 12 | 13 | .controls { 14 | display: flex; 15 | gap: 10px; 16 | align-items: center; 17 | justify-content: center; 18 | margin-bottom: 20px; 19 | width: 100%; 20 | max-width: 600px; 21 | } 22 | 23 | #scan { 24 | padding: 10px 20px; 25 | font-size: 16px; 26 | flex: 1; 27 | min-width: 120px; 28 | } 29 | 30 | #file { 31 | flex: 1; 32 | min-width: 120px; 33 | padding: 10px; 34 | font-size: 16px; 35 | border: 1px solid #ccc; 36 | background-color: #fff; 37 | cursor: pointer; 38 | } 39 | 40 | #divScanner { 41 | border: 1px solid #ccc; 42 | transition: all 0.3s ease; 43 | } 44 | 45 | #container { 46 | width: 100%; 47 | height: 100%; 48 | } 49 | 50 | #result { 51 | height: 150px; 52 | margin-top: 20px; 53 | border: 1px solid #ccc; 54 | font-size: 14px; 55 | resize: vertical; 56 | } 57 | 58 | .license-row { 59 | display: flex; 60 | flex-direction: row; 61 | align-items: center; 62 | justify-content: center; 63 | gap: 10px; 64 | flex-wrap: wrap; 65 | margin-bottom: 20px; 66 | width: 100%; 67 | max-width: 800px; 68 | text-align: center; 69 | } 70 | 71 | .license-row label { 72 | font-size: 14px; 73 | white-space: nowrap; 74 | } 75 | 76 | .license-row input[type="text"] { 77 | flex: 1; 78 | min-width: 200px; 79 | padding: 8px; 80 | font-size: 14px; 81 | } 82 | 83 | .loading-indicator { 84 | position: absolute; 85 | top: 0; 86 | left: 0; 87 | width: 100%; 88 | height: 100%; 89 | background-color: rgba(0, 0, 0, 0.5); 90 | z-index: 1000; 91 | display: none; 92 | align-items: center; 93 | justify-content: center; 94 | } 95 | 96 | .spinner { 97 | width: 50px; 98 | height: 50px; 99 | border: 5px solid #fff; 100 | border-radius: 50%; 101 | animation: spin 1s linear infinite; 102 | background: linear-gradient(to right, #FF0000 0%, #FF8000 17%, #FFFF00 33%, #00FF00 50%, #00FFFF 67%, #0080FF 83%, #0000FF 100%); 103 | } 104 | 105 | @keyframes spin { 106 | from { 107 | transform: rotate(0deg); 108 | } 109 | 110 | to { 111 | transform: rotate(360deg); 112 | } 113 | } 114 | 115 | #imageContainer { 116 | display: none; 117 | width: 100%; 118 | text-align: center; 119 | margin-top: 20px; 120 | overflow: hidden; 121 | max-height: 40vh; 122 | } 123 | 124 | #imageContainer canvas { 125 | max-width: 100%; 126 | max-height: 40vh; 127 | height: auto; 128 | width: auto; 129 | display: inline-block; 130 | object-fit: contain; 131 | } --------------------------------------------------------------------------------