How to Build Angular Document Scanner with Dynamsoft Web Capture SDK

Angular Development Environment

npm install -g @angular/cli

ng --version

Angular CLI: 13.3.7
Node: 16.13.1
Package Manager: npm 8.1.2
OS: win32 x64

Angular: 13.3.10
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router

Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1303.7
@angular-devkit/build-angular 13.3.7
@angular-devkit/core 13.3.7
@angular-devkit/schematics 13.3.7
@angular/cli 13.3.7
@schematics/angular 13.3.7
ng-packagr 13.3.1
rxjs 7.5.5
typescript 4.6.4

Creating Angular Document Scanner App Step by Step

We scaffold a new Angular project via ng new command and install Dynamsoft Web Capture SDK in terminal:

ng new angular-document-scanner
cd angular-document-scanner
npm i mobile-web-capture
"build": 
{
"builder": "@angular-devkit/build-angular:browser",
"options": {
...
"assets": [
"src/favicon.ico",
"src/assets",
{
"glob": "**/*",
"input": "./node_modules/mobile-web-capture/dist",
"output": "assets/dynamic-web-twain"
}
...
],
},
...
},
ng generate component document-scanner
  • An HTMLSelectElement for selecting the camera sources. For desktop browsers, all USB cameras are listed. For mobile browsers, all front-facing and back-facing cameras are listed.
  • A button used to trigger document scanning and a button used to download the scanned document.
  • An HTMLDivElement set as the container for storing the scanned and processed document images.
<div class="document-scanner">
<h1>Angular Document Scanner</h1>
<div>
<label for="videoSource">Video source: </label>
<select id="videoSource"></select>
<p></p>
<button id="scanButton" (click)="scanDocument()">Scan Document</button> <button id="scanButton" (click)="downloadDocument()">Download Document</button>
</div>

<h3>Document Container</h3>
<div id="dwtcontrolContainer"></div>

</div>
  1. Import the SDK module from mobile-web-capture package.
import Dynamsoft from 'mobile-web-capture';
import { WebTwain } from 'mobile-web-capture/dist/types/WebTwain';
dwtObject: WebTwain | undefined;
videoSelect: HTMLSelectElement | undefined;
sourceDict: any = {};

ngOnInit(): void {
this.videoSelect = document.querySelector('select#videoSource') as HTMLSelectElement;
Dynamsoft.DWT.ProductKey = "LICENSE-KEY";
Dynamsoft.DWT.ResourcesPath = 'assets/dynamic-web-twain';
Dynamsoft.DWT.Containers = [{ ContainerId: 'dwtcontrolContainer' }];
Dynamsoft.DWT.UseLocalService = false;
Dynamsoft.DWT.Load();
Dynamsoft.DWT.RegisterEvent('OnWebTwainReady', () => { this.onReady(); });
}
  • Apply for a 30-day trial license and thereafter update the LICENSE-KEY.
  • Set the resource path assets/dynamic-web-twain as we configure above in angular.json file.
onReady() {
this.dwtObject = Dynamsoft.DWT.GetWebTwain('dwtcontrolContainer');
this.updateCameraList();
}

updateCameraList() {
if (this.videoSelect && this.dwtObject) {
this.videoSelect.options.length = 0;
this.dwtObject.Addon.Camera.getSourceList().then((list) => {
for (var i = 0; i < list.length; i++) {
var option = document.createElement('option');
option.text = list[i].label || list[i].deviceId;
if (list[i].label) {
this.sourceDict[list[i].label] = list[i].deviceId;
}
else {
this.sourceDict[list[i].deviceId] = list[i].deviceId;
}
if (this.videoSelect) this.videoSelect.options.add(option);
}

});
}
}
scanDocument() {
if (this.videoSelect) {
let index = this.videoSelect.selectedIndex;
if (index < 0) return;

var option = this.videoSelect.options[index];
if (this.dwtObject) {
this.dwtObject.Addon.Camera.selectSource(this.sourceDict[option.text]).then(camera => {
if (this.videoSelect) this.createCameraScanner(this.sourceDict[option.text]);
});
}

}

}

async createCameraScanner(deviceId: string): Promise<void> {
if (this.dwtObject) {
await this.dwtObject.Addon.Camera.closeVideo();
this.dwtObject.Addon.Camera.scanDocument({
scannerViewer: {
deviceId: deviceId,
fullScreen: true,
autoDetect: {
enableAutoDetect: true
},
continuousScan: {
visibility: false,
enableContinuousScan: false
}
}

}).then(
function () { console.log("OK"); },
function (error: any) { console.log(error.message); });
}

}
downloadDocument() {
if (this.dwtObject) {
this.dwtObject.SaveAsJPEG("document.jpg", this.dwtObject.CurrentImageIndexInBuffer);
}
}
ng serve --ssl

GitHub Page Deployment

One more thing is to deploy the Angular document scanner project to GitHub pages.

  1. Open angular.json file to increase the size budgets. The default budgets setting may cause the error: WARNING in budgets, maximum exceeded for initial.
"budgets": [
{
"type": "initial",
"maximumWarning": "2.5mb",
"maximumError": "5mb"
},
]
name: Build and Deploy
on:
push:
branches:
- main
jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: All things angular
uses: AhsanAyaz/angular-deploy-gh-pages-actions@v1.3.2
with:
github_access_token: $
build_configuration: production
base_href: /angular-document-scanner/
deploy_branch: gh-pages
angular_dist_build_folder: dist/angular-document-scanner

Source Code

https://github.com/yushulx/angular-document-scanner

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store