How to Scan Documents & Images from Javascript
Product JSPrintManager Published 05/15/2020 Updated 03/11/2022 Author Neodynamic
Overview
JSPrintManager enables any web page (written on top of any Web Platform including ASP.NET MVC/CORE, PHP, Django, Ruby On Rails (RoR), Express.js, Angular, React, Vue) to scan documents and images through any TWAIN/SANE compatible devices available at the client side by writing pure and simple Javascript code!
In this walkthrough, you'll learn how to scan documents and images from Javascript through any TWAIN/SANE client devices without displaying any system dialogs at all. You'll be able to specify the target scanner device, the resolution and output quality (dpi) and desired pixel mode (Grayscale or full Color) as well as the output image format (JPG/JPEG or PNG). This solution works with any popular browser like Chrome, Firefox, IE/Edge & Safari on Windows, Linux, Raspberry Pi and Mac systems!
Follow up these steps
-
Client System Requirements
- Windows: None!
- macOS/OSX: None!
- Linux: Scanner Access Now Easy (SANE) API
-
JSPrintManager Client App
Be sure you install in your dev machine JSPrintManager (JSPM) (Available for Windows, Linux, Raspberry Pi & Mac)
IMPORTANT: This small app must be installed on each client that will scan from your website!READ CAREFULLY - Windows 64-bit Clients
If you install the JSPrintManager client app in a Windows 64-bit edition through our universal installer or the one specific for Win64 and your scanner does not provide a 64-bit TWAIN driver or it supports the TWAIN 1.x specification only, then it's possible that no scanners will be detected! If this is your case, then do the following:
- Uninstall current JSPrintManager app for 64-bit
- Download and install JSPrintManager app for 32-bit instead. The JSPrintManager app for 32-bit will detect not only those missing TWAIN devices but also any other WIA devices that might be available in your system.
-
HTML & Script References
- Download JSPrintManager.js
- Copy all of these *.js files to the same folder where the next
index.html
page sample will be located in. - By using your favorite Web Development IDE or Text Editor, create a new HTML file naming it
index.html
Copy/paste the following code inside that html file:
<!DOCTYPE html> <html> <head> <title>JSPrintManager</title> <meta charset="utf-8" /> </head> <body> <div style="text-align:center"> <h1>Scan Docs and Images from Javascript</h1> <hr /> <label>Scanner:</label> <select id="scannerName"></select> <label>Resolution (DPI):</label> <input type="text" id="resolution" value="200" /> <label>Pixel Mode:</label> <select id="pixelMode"> <option>Grayscale</option> <option selected>Color</option> </select> <label>Image Format:</label> <select id="imageFormat"> <option selected>JPG</option> <option>PNG</option> </select> <hr /> <div> <button onclick="doScanning();">Scan Now...</button> </div> <br /> <img id="scanOutput" /> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.5/bluebird.min.js"></script> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script> <!--IMPORTANT: BE SURE YOU HONOR THIS JS LOAD ORDER--> <script src="JSPrintManager.js"></script> <script> var scannerDevices = null; var _this = this; //JSPrintManager WebSocket settings JSPM.JSPrintManager.auto_reconnect = true; JSPM.JSPrintManager.start(); JSPM.JSPrintManager.WS.onStatusChanged = function () { if (jspmWSStatus()) { //get scanners JSPM.JSPrintManager.getScanners().then(function (scannersList) { scannerDevices = scannersList; var options = ''; for (var i = 0; i < scannerDevices.length; i++) { options += '<option>' + scannerDevices[i] + '</option>'; } $('#scannerName').html(options); }); } }; //Check JSPM WebSocket status function jspmWSStatus() { if (JSPM.JSPrintManager.websocket_status == JSPM.WSStatus.Open) return true; else if (JSPM.JSPrintManager.websocket_status == JSPM.WSStatus.Closed) { console.warn('JSPrintManager (JSPM) is not installed or not running! Download JSPM Client App from https://neodynamic.com/downloads/jspm'); return false; } else if (JSPM.JSPrintManager.websocket_status == JSPM.WSStatus.Blocked) { alert('JSPM has blocked this website!'); return false; } } //Do scanning... function doScanning() { if (jspmWSStatus()) { //create ClientScanJob var csj = new JSPM.ClientScanJob(); //scanning settings csj.scannerName = $('#scannerName').val(); csj.pixelMode = JSPM.PixelMode[$('#pixelMode').val()]; csj.resolution = parseInt($('#resolution').val()); csj.imageFormat = JSPM.ScannerImageFormatOutput[$('#imageFormat').val()]; let _this = this; //get output image csj.onUpdate = (data, last) => { if (!(data instanceof Blob)) { console.info(data); return; } var imgBlob = new Blob([data]); if (imgBlob.size == 0) return; var data_type = 'image/jpg'; if (csj.imageFormat == JSPM.ScannerImageFormatOutput.PNG) data_type = 'image/png'; //create html image obj from scan output var img = URL.createObjectURL(imgBlob, { type: data_type }); //scale original image to be screen size friendly var imgScale = { width: Math.round(96.0 / csj.resolution * 100.0) + "%", height: 'auto' }; $('#scanOutput').css(imgScale); $('#scanOutput').attr("src", img); } csj.onError = function (data, is_critical) { console.error(data); }; //Send scan job to scanner! csj.sendToClient().then(data => console.info(data)); } } </script> </body> </html>
- That's it! Run your website and test it. Click on Scan Now... to start the scanning process without any system dialog.