Open a ticket
Chat with us

TWTwainJS - JavaScript Examples

Different examples how to use TWTwainJS from JavaScript

Requirements for executing these examples

These examples are written for modern browsers, which support ES6 modules. ES5 version of our library also exists if needed.

Let's assume you have this structure:
demo/index.js - the place where you want to put examples
demo/index.html
src/TWTwainJS.js
src/TWTwainJSCapabilities.js

in index.html

in index.js at the top:

import TWTwainJS, { TWJSConnectionStatus, TWEvent, ScanSettings, TWScanFinishedStatus, PdfProtection, PdfDocumentSecurityLevel, ScannedFileSettings, TWDownloadMode, twConvertBinaryStringToUint8Array } from "../src/TWTwainJS.js"; import { CapName, CapEnum } from "../src/TWTwainJSCapabilities.js";

Create a TWTwainJS instance and connect to the local Twain client TW

TWTwainJS instance has its name as identification, company name, and key for licensing.

connectToClient method creates a socket connection by asking the local TWTwain client to provide an available port in the range of fromPort-toPort.

Every change of socket connection status triggers the event TWEvent.SOCKET_CONNECTION_STATUS_CHANGED.
The most important one is information when the status is connected because, at that moment, it is possible to execute Twain commands (like getAvailableDevices or scan) on the local Twain client.

In all the following examples, we will assume that the twTwainJS instance is created and has successfully connected to the client.

const twTwainJS = new TWTwainJS("twain1", "TWDemoCompany", "TWDemoKey"); let fromPort = 55454; // you can define the initial port let toPort = 55457; // max value could be 65535 twTwainJS.connectToClient(fromPort, toPort).then((result) => { console.log("connectToClient promise:", result); if (result.status === TWJSConnectionStatus.CONNECTED) { console.log("connectToClient promise with status connected", result); } }) .catch((error) => { console.log("connectToClient promise error:", error);      }); // event is triggered if you don't want to use promise for some reason window.addEventListener(TWEvent.SOCKET_CONNECTION_STATUS_CHANGED, function (e) { console.log(TWEvent.SOCKET_CONNECTION_STATUS_CHANGED + "[" + e.detail.twTwainJSInstance.name + "]", e.detail); if (e.detail.status === TWJSConnectionStatus.CONNECTED) { console.log("connected"); } });

Get All Available Scanner devices

twTwainJS.getAvailableDevices().then(result => { console.log("Default device:", result.defaultDeviceName, "Devices:", result.devicesName); }).catch(error => { console.log("getAvailableDevices error", error); }); // event is triggered if you don't want to use promise for some reason window.addEventListener(TWEvent.DEVICE_LIST_RETRIEVED, function (e) { console.log(TWEvent.DEVICE_LIST_RETRIEVED + "[" + e.detail.twTwainJSInstance.name + "]", e.detail); console.log("Default device:", e.detail.defaultDeviceName, "Devices:", e.detail.devicesName) });     

Get device info (supported capabilities and current capability values)

To perform a scan, retrieving device info through the getDeviceInfo call isn't necessary to perform. Still, it is helpful if, before scanning, we want to know the device's current settings and its supported capabilities.

Returned deviceInfo result has the following properties:
currentSettings
supportedCapabilities
deviceName

let deviceName = "your scanner device name"; // deviceName = TWDeviceName.SELECT_FROM_UI; // shows UI to the client to select a device // deviceName = TWDeviceName.DEFAULT; // "" - it uses current client default device // if true, returned currentSettings will be empty. Using that option can be useful if we don't care about currentSettings // and we want to have some performance gains (reading currentSettings isn't fast) const ignoreCurrentValues = false; twTwainJS.getDeviceInfo(deviceName, ignoreCurrentValues).then(result => { let deviceInfo = result.deviceInfo; console.log("Device info object", result.deviceInfo); console.log("Current settings", deviceInfo.currentSettings); let supportedCapabilities = deviceInfo.supportedCapabilities; console.log("All Supported capabilities", supportedCapabilities.capabilities); }).catch(error => { console.log("getDeviceInfo error", error); }); // event is triggered if you don't want to use promise for some reason window.addEventListener(TWEvent.DEVICE_INFO_RETRIEVED, function (e) { console.log(TWEvent.DEVICE_INFO_RETRIEVED + "[" + e.detail.twTwainJSInstance.name + "]", e.detail); // e.detail.deviceInfo.supportedCapabilities // e.detail.deviceInfo.currentSettings // e.detail.deviceInfo.deviceName });

Read supported capability properties (e.g. X_RESOLUTION)

// we assume that you already retrieved deviceInfo in previous steps let supportedCapabilities = deviceInfo.supportedCapabilities; let currentSettings = deviceInfo.currentSettings; // CapName contains all TWAIN standard properties let capName = CapName.X_RESOLUTION; if (supportedCapabilities.hasCapability(capName)) { const cap = supportedCapabilities.getCapability(capName); console.log("Supported values:", cap.values, "Is read only:", cap.isReadOnly, "Type:", cap.type, "IsEnum", cap.isEnum, "Is multi value", cap.isMultiVal); console.log("current value", deviceInfo.currentSettings[capName]); } // also are available methods: console.log("Is it read only?", supportedCapabilities.isReadOnly(capName)); console.log("Is supported value?", supportedCapabilities.isSupportedValue(capName, 100));

Get current settings

Current settings are sent after the call of getDeviceInfo, and in most use cases, it is enough to use the value of the setting present at the moment of that call.

const currentSettings = deviceInfo.currentSettings; console.log("Current settings example. FEEDER_LOADED=" + currentSettings.feederLoaded); // or console.log("Current settings example. FEEDER_LOADED=" + currentSettings[CapName.FEEDER_LOADED]);

But it is also possible to ask what are current settings in separate calls and just for specific settings.
That could be useful if you want to be sure that the current settings retrieved are the up to date or if you want to get current settings for the device different from the last call of getDeviceInfo.
You can define one or many capability names at the same time.
Every capability available in CapName can retrieve its current value if the device supports that capability.

const capNames = [CapName.SUPPORTED_SIZES, CapName.X_RESOLUTION, CapName.IXFER_MECH, CapName.DUPLEX_ENABLED, CapName.FEEDER_ENABLED, CapName.XFER_COUNT, CapName.THRESHOLD, CapName.CONTRAST, CapName.BRIGHTNESS, CapName.ROTATION]; twTwainJS.getCurrentSettings(capNames, "your device name") .then((result) => { console.log("getCurrentSettings promise", result); //result.supportedSizes, result.feederEnabled,... or //result[CapName.SUPPORTED_SIZE], result[CapName.FEEDER_ENABLED] }) .catch((error) => { console.log("getCurrentSettings promise error", error); }); // event is also triggered window.addEventListener(TWEvent.CURRENT_SETTINGS_RECEIVED, function (e) { console.log(TWEvent.CURRENT_SETTINGS_RECEIVED + "[" + e.detail.twTwainJSInstance.name + "]", e.detail); //e.detail.currentSettings.supportedSizes, e.detail.currentSettings.feederEnabled, ... or //e.detail.currentSettings[CapName.SUPPORTED_SIZE], e.detail.currentSettings[CapName.FEEDER_ENABLED] }

Scan

scan method uses ScanSettings to perform scanning.
ScanSettings has following properties:
scanFormatType
showUI
closeUIAfterAcquire
imageQuality %. It has effect only for PDF and JPG.
pdfProtection
tiffCompression
deviceName
Device name can be:

let deviceName = "your device name"; // deviceName = TWDeviceName.DEFAULT; // it will use current default device // deviceName = TWDeviceName.SELECT_FROM_UI; // it will show UI to select one of available devices

supportedCapabilities optional. if empty there will not be checked if the cap setting is valid.

ScanSettings has very important method setCap, for setting TWAIN capability value.
If supportedCapabilities is set, it will be used to check if the provided value can be set to that property.
You can use any of available standard TWAIN properties. CapName has a list of all available TWAIN property names.
Example of setCap

scanSettings.setCap(CapName.FEEDER_ENABLED, true); scanSettings.setCap(CapName.SUPPORTED_SIZES, CapEnum.SupportedSizes.A4);

Scan operation triggers two types of event:
1. TWEvent.PAGE_SCANNED after every page scanned and has in event detail:
scanResult
deviceName
twTwainJSInstance

2. TWEvent.SCAN_FINISHED_SUCCESS after scan has finished completely and has in event detail:
scanResult
deviceName
twTwainJSInstance
scanFinishedStatus: TWScanFinishedStatus.SUCCESS, TWScanFinishedStatus.ERROR or TWScanFinishedStatus.CANCELLED

scanResult has following properties:
images: an array of base64 encoded scanned page images. For pdf and tiff it will be jpeg.
scanFormatType: jpeg, bmp, png, pdf or tiff
deviceName
tiffFile: the base64 encoded tiff file. Only available when a scan has finished and if scanFormatType is tiff.
pdfFile: the base64 encoded pdf file. when scan has finished and if scanFormatType is pdf.

scanResult has the following methods:
pageCount()
getImageDataAsUint8Array(pageNumber): returns byte[] which can be used to save to file or to upload somewhere.
getImageDataSrc(pageNumber) returns the image data source URL for a selected page number. Useful for displaying in canvas.

Example 1: Scan as JPEG, use feeder, set page size as A4, and display every page in canvas

let supportedCapabilities = undefined; // option: to call before getDeviceInfo and use its properties for scanSettings: // deviceName = deviceInfo.deviceName; // supportedCapabilities = deviceInfo.supportedCapabilities.capabilities; let scanSettings = new ScanSettings(deviceName, supportedCapabilities); scanSettings.showUI = true; scanSettings.closeUIAfterAcquire = true; // other supported types are: BMP, TIFF, PDF, PNG scanSettings.scanFormatType = CapEnum.TWScanFormatType.JPEG; scanSettings.imageQuality = 90; scanSettings.setCap(CapName.FEEDER_ENABLED, true); scanSettings.setCap(CapName.SUPPORTED_SIZES, CapEnum.SupportedSizes.A4); twTwainJS.scan(scanSettings) .then((result) => { console.log("scan result", result);    if (result.scanFinishedStatus === TWScanFinishedStatus.SUCCESS) { console.log("scan finished with success"); } }) .catch((error) => { console.log("scan error", error); }); window.addEventListener(TWEvent.SCAN_FINISHED_SUCCESS, function (e) { console.log(TWEvent.SCAN_FINISHED_SUCCESS + "[" + e.detail.twTwainJSInstance.name + "]", e.detail);  });

Display the single page in canvas:
if scanFormatType is pdf or tiff, jpeg is used for single page image, otherwise, single image format is the same as scanFormatType

window.addEventListener(TWEvent.PAGE_SCANNED, function (e) { console.log(TWEvent.PAGE_SCANNED + "[" + e.detail.twTwainJSInstance.name + "]", e.detail); let scanResult = e.detail.scanResult;  const pageNumber = scanResult.pageCount(); console.log("Current number of scanned pages:", pageNumber); let canvas = document.createElement("canvas");  canvas.id = "twCanvas" + pageNumber; let ctx = canvas.getContext("2d");  let image = new Image(); image.onload = function() { canvas.width = image.width; canvas.height = image.height; ctx.drawImage(image, 0, 0, image.width, image.height); } image.src = scanResult.getImageDataSrc(pageNumber); document.body.appendChild(canvas); });

Example 2: Scan as Tiff.
It will generate a multi-page tiff file compressed with LZW compression.

let deviceName = "your device name"; let scanSettings = new ScanSettings(deviceName); scanSettings.scanFormatType = CapEnum.TWScanFormatType.TIFF; scanSettings.tiffCompression = CapEnum.TiffCompression.LZW; twTwainJS.scan(scanSettings) .then((result) => { console.log("scan result", result); if (result.scanFinishedStatus === TWScanFinishedStatus.SUCCESS) { console.log("scan success"); } }) .catch((error) => { console.log("scan error", error); });

Example 3: Scan as PDF
Generated PDF contains scanned pages with JPG images.
This example shows how to protect PDF document, but that is optional.

let deviceName = "your device name"; let scanSettings = new ScanSettings(deviceName); scanSettings.scanFormatType = CapEnum.TWScanFormatType.PDF; scanSettings.imageQuality = 90; let pdfProtect = new PdfProtection(); pdfProtect.ownerPassword = "owner password"; pdfProtect.userPassword = "user password"; //these values are default ones //another options are: NONE and ENCRYPTED_40BIT pdfProtect.securityLevel = PdfDocumentSecurityLevel.ENCRYPTED_128BIT; pdfProtect.permitAccessibilityExtractContent = true; pdfProtect.permitAnnotations = true; pdfProtect.permitExtractContent = true; pdfProtect.permitFormsFill = true; pdfProtect.permitFullQualityPrint = true; pdfProtect.permitModifyDocument = true; pdfProtect.permitPrint = true; scanSettings.pdfProtection = pdfProtect; twTwainJS.scan(scanSettings) .then((result) => { console.log("scan result", result); if (result.scanFinishedStatus === TWScanFinishedStatus.SUCCESS) { console.log("scan success"); } }) .catch((error) => { console.log("scan error", error); });

Download file(s) from the last scan

Using the downloadFile method, you can download pages that have already been scanned even though the scan still needs to finish completely.
Setting a file name is mandatory, and based on the file name extension is, determined format type of the file.

downloadFile has two parameters:
downloadMode: TWDownloadMode.STANDARD or TWDownloadMode.LOCAL
scannedFileSettings

ScannedFileSettings has the following properties:
fileName: test.tiff, some.pdf, etc. Supported are: pdf, tiff, jpg, bmp, png.
pages: if empty it will return all pages.
isMultiPageFile: valid only for pdf and tiff. If true, it will return all pages in single file.
pdfProtection: optional pdfProtection settings for pdf file
imageQuality: in %, it has effect only for jpeg and pdf
tiffCompression: one of the available tiff compressions for tiff file

The returned result has the following properties:
fileContent: array of retrieved files (if only one page or multi-page file it will have only one retrieved file)
fileName: scannedFileSettings.fileName
isMultiPageFile: scannedFileSettings.isMultiPageFile
pages: scannedFileSettings.pages

warning: warning message if some page numbers weren't correct

downloadMode: scannedFileSettings.downloadMode twTwainJSInstance: twTwainJSInstance, which has executed getFile

Example 1: Download pages 1-3 as a single multi-page PDF using standard browser download mode where the user can choose its download location.
We assume that you have already called the scan method and scanned 3 pages.

let scannedFileSettings = new ScannedFileSettings(); scannedFileSettings.fileName = "test.pdf"; scannedFileSettings.pages = "1-3"; scannedFileSettings.isMultiPageFile = true; // if last scan operation has set pdfProtection and here pdfProtetion isn't set, last scan pdfProtection will be // used, otherwise PDF will not be protected // scannedFileSettings.pdfProtection = new PdfProtection(); twTwainJS.downloadFile(TWDownloadMode.STANDARD, scannedFileSettings) .then((result) => { console.log("file downloaded.", result); }) .catch((error) => { console.log("file download error", error); }); // event is triggered if you don't want to use promise for some reason window.addEventListener(TWEvent.FILE_DOWNLOADED, function (e) { console.log(TWEvent.FILE_DOWNLOADED + "[" + e.detail.twTwainJSInstance.name + "]", e.detail); });

Example 2: Download pages 3, 2, 2 as 3 jpeg files using local download mode.
Local download mode means that files will be saved in the location defined in TWTwainClient settings.

let scannedFileSettings = new ScannedFileSettings(); scannedFileSettings.pages = "3,2,2"; scannedFileSettings.isMultiPageFile = false; scannedFileSettings.fileName = "test.jpg"; scannedFileSettings.imageQuality = 80; twTwainJS.downloadFile(TWDownloadMode.LOCAL, scannedFileSettings) .then((result) => { console.log("file downloaded.", result); }) .catch((error) => { console.log("file download error", error); });

Example 3: Download pages 1-2, 3, 1 as one single multi-page tiff file using LZW compression

let scannedFileSettings = new ScannedFileSettings(); scannedFileSettings.pages = "1-2,3,1"; scannedFileSettings.isMultiPageFile = true; scannedFileSettings.fileName = "test.tiff"; scannedFileSettings.tiffCompression = CapEnum.TiffCompression.LZW; twTwainJS.downloadFile(TWDownloadMode.LOCAL, scannedFileSettings) .then((result) => { console.log("file downloaded.", result); }) .catch((error) => { console.log("file download error", error); });

Get scanned pages as file(s) (for example to upload them to some URL)

getFile method retrieves scanned pages.
It accepts ScannedFileSettings as a parameter. The same parameter type is also used in downloadFile.

Result of getFile method call is an object with the following properties:
fileContent: array of retrieved files (if only one page or multi-page file, it will have only one retrieved file)
fileName: scannedFileSettings.fileName
isMultiPageFile scannedFileSettings.isMultiPageFile
pages: scannedFileSettings.pages
warning: warning message if some page numbers weren't correct

twTwainJSInstance: twTwainJSInstance, which has executed getFile

Also, TWEvent.FILE_RETRIEVED is triggered where event.detail has the same properties as the promise result of getFile.

Example: Get multiple jpeg documents with pages 1-3.
We assume you have already called the scan method and scanned 3 pages.

let scannedFileSettings = new ScannedFileSettings(); scannedFileSettings.fileName = "test.jpg"; scannedFileSettings.pages = "1-3"; scannedFileSettings.isMultiPageFile = false; scannedFileSettings.imageQuality = 80; twTwainJS.getFile(scannedFileSettings) .then((result) => { // you can use fileContent for upload to some web server URL - axios example let apiUrl = "https://your-web-site/upload-file"; for (let i = 0; i < result.fileContent.length; i++) { let formData = new FormData(); let content = twConvertBinaryStringToUint8Array(result.fileContent[i]); let fileName = result.fileContent.length > 1 ? i + "_" + scannedFileSettings.fileName : scannedFileSettings.fileName; const blob = new Blob(content, { type: "application/octet-stream" }); let file = new File([blob], fileName, { type: "application/octet-stream" }); formData.append("uploadFile", file); axios.post(apiUrl, formData, { headers: { "Content-Type": "multipart/form-data" } }) .then((response) => { console.log("Axios post upload. Success!", response); }) .catch(function (error) { console.log("Axios post upload. Error!", error);      });   } })  .catch((error) => { console.log("getFile error", error); }); // event TWEvent.FILE_RETRIEVED is trigger if you don't want to use a promise window.addEventListener(TWEvent.FILE_RETRIEVED, function (e) { console.log(TWEvent.FILE_RETRIEVED + "[" + e.detail.twTwainJSInstance.name + "]", e.detail);  });

Catching errors

Errors could be caught in two ways
1. directly in .catch from the promise call
2. by catching one of the available error events: TWEvent.SCAN_FINISHED_ERROR for scanning error or TWEvent.TW_ERROR for every other possible error

window.addEventListener(TWEvent.TW_ERROR, function (e) { console.log(TWEvent.TW_ERROR + "[" + e.detail.twTwainJSInstance.name + "]", e.detail); // e.detail.error });

Back to the top
Copyright © 2024 Terminalworks. All Rights Reserved