Share via


Quickstart: Scanning (HTML)

You can scan from your Windows Store app or desktop app built in Windows 8.1.

For your app to scan, you must enumerate the available scanners so your app can communicate with the devices, and then choose the type of scanning you want. How your app scans depends on the available scanners.

Watch this video for a quick overview on how to add scanning from your app.

Prerequisites

  • You must be familiar with HTML, JavaScript, and Windows.
  • You must have Microsoft Visual Studio 2013 installed.
  • You must be connected to a scanner.
  • You must have an app that you want to scan from. If you don't have your own app, you can download the Scan Sample app and use that.Note  The examples here are found in the Scan Sample app.  

Open your app's source code for editing

This procedure describes how to open the ScanRuntimeAPI app from the Scan Sample app. If you are using your own app, open it in Visual Studio 2013 and skip to the next step.

  1. Open the Scan Sample app and download the JavaScript example to your computer.
  2. In Visual Studio 2013, click File > Open Project and navigate to the folder that contains the solution file of the sample app that you downloaded in the previous step.
  3. Select the ScanRuntimeAPI solution file, and click Open.

Enumerate available scanners

Default scanners are not automatically available. You must perform this step in order for your app to communicate with the scanner. In this example, the scanner device enumeration is done using the Windows.Devices.Enumeration namespace. For more info, see Enumerating commonly used devices.

  1. Create a function in your .js file for enumerating scanners and add this code to start and stop enumerating scanners.

            scannerWatcher = Windows.Devices.Enumeration.DeviceInformation.createWatcher(Windows.Devices.Enumeration.DeviceClass.imageScanner);
    
            // Register to know when devices are added or removed, and when the enumeration ends
            scannerWatcher.addEventListener("added", onScannerAdded);
            scannerWatcher.addEventListener("removed", onScannerRemoved);
            scannerWatcher.addEventListener("enumerationcompleted", onScannerEnumerationComplete);
        }
    

    To start the watcher, call scannerWatcher.start(); To stop the watcher, call scannerWatcher.stop();

  2. Create an event handler for when a scanner is added.

        function onScannerAdded(deviceInfo) {
            WinJS.log && WinJS.log("Scanner with device id " + deviceInfo.Id + " has been added", "sample", "info");
    
            // Search the scanner list for a scanner with a matching device id
            var matchEntry = ScannerListEntry.findInList(deviceInfo.id);
    
            // If we found a match then mark it as verified and return
            if (matchEntry !== null) {
                matchEntry.data.matched = true;
                return;
            }
            addToList(deviceInfo);
        }
    

Scan

This step shows you how to simply let your app scan. You can choose from any of these scenarios. For each of these scenarios, you must first create a function that data binds file names to the list view, like this.

    function scanToFolder(deviceId, folder) {
        // Get the scanner object for this device id
        Windows.Devices.Scanners.ImageScanner.fromIdAsync(deviceId).then(function (myScanner) {

Create an event handler for registering start and end scans.

            Utils.id("startScenario").addEventListener("click", startScenario, false);
            Utils.id("endScenario").addEventListener("click", endScenario, false);
  1. Just scan

    In this scenario, your app relies on the Windows.Devices.Scanners namespace to select a default scanner and scans from that source without changing any scan settings. The possible scanners are auto, flatbed, or feeder. This type of scan will most likely produce a successful scan operation, even if it scans from the wrong source, like flatbed instead of feeder.

    Note  This approach doesn't work when the scanner can scan with both a flatbed and a feeder. If the user places the document to scan in the feeder, the scanner will scan from the flatbed instead. If the user tries to scan from an empty feeder, the scan job won't produce any scanned files.

     

                if (scenarioRunning) {
                    WinJS.log && WinJS.log("Scanning.", "sample", "status");
                    // Scan API call to start scanning
    
                    return scanningPromise = myScanner.scanFilesToFolderAsync(Windows.Devices.Scanners.ImageScannerScanSource.default, folder);
                } else {
                    // Scenario has already been canceled; return nullptr so no further action is possible 
                    return WinJS.Promise.then(null);
                }
            }).done(function (result) {
                scenarioRunning = false;
                updateStartAndEndScenarioButtons();
                // Check for result to prevent showing results in case of cancellation
                if (result) {
                    if (result.scannedFiles.size > 0) {
                        displayResults(result.scannedFiles);
    
  2. Auto-configured scan

    You can set your app to use the device's Auto-Configured Scanning to scan with the most optimal scan settings. With this option, the device itself can determine the best scan settings, like color mode and scan resolution, based on the content being scanned. The device selects the scan settings at run time for each new scan job.

    Note  Not all scanners support this feature, so the app must check if the scanner supports this feature before using this setting.

     

                if (scenarioRunning) {
                    if (myScanner.isScanSourceSupported(Windows.Devices.Scanners.ImageScannerScanSource.autoConfigured)) {
                        WinJS.log && WinJS.log("Scanning.", "sample", "status");
                        // Scan API call to start scanning
                        return scanningPromise = myScanner.scanFilesToFolderAsync(Windows.Devices.Scanners.ImageScannerScanSource.autoConfigured, folder);
                    } else {
                        WinJS.log && WinJS.log("The selected scanner does not support Device Auto-Configured Scanning.", "sample", "error");
                        return WinJS.Promise.then(null);
                    }
                } else {
                    // Scenario has already been canceled; return nullptr so no further action is possible 
                    return WinJS.Promise.then(null);
                }
            }).done(function (result) {
                scenarioRunning = false;
                updateStartAndEndScenarioButtons();
                // Check for result to prevent showing results in case of cancellation and Device Auto-Configured not supported.
                if (result) {
                    if (result.scannedFiles.size > 0) {
                        displayResults(result.scannedFiles);
    
  3. Flatbed scan

    To scan from a flatbed scanner, the app scans one image to a Windows Device Independent Bitmap (DIB) format using a RandomAccessStream.

    You can add code to preview the scan before scanning to a folder, like this.

                    if (myScanner.isPreviewSupported(Windows.Devices.Scanners.ImageScannerScanSource.flatbed)) {
                        WinJS.log && WinJS.log("Scanning.", "sample", "status");
                        // Scan API call to get preview from the flatbed
                        return myScanner.scanPreviewToStreamAsync
                            (Windows.Devices.Scanners.ImageScannerScanSource.flatbed, stream);
                    } else {
                        WinJS.log && WinJS.log("The selected scanner does not support preview from Flatbed.",
                            "sample", "status");
                        return WinJS.Promise.then(null);
                    }
                } else {
                    WinJS.log && WinJS.log("The selected scanner does not report to be equipped with a Flatbed.", 
                        "sample", "status");
                    return WinJS.Promise.then(null);
                }
    
            }).done(function (result) {
    

    Now add code to display the preview to the screen.

        function displayResult(stream) {
            var image = document.getElementById("displayImage");
            var blob = window.MSApp.createBlobFromRandomAccessStream("image/bmp", stream);
            var url = window.URL.createObjectURL(blob);
            WinJS.log && WinJS.log("Preview scanning is complete. Below is the preview image.", "sample", "status");
            image.src = url;
        }
    

    Then, add code for actual scanning, like this.

                if (scenarioRunning) {
                    if (myScanner.isScanSourceSupported(Windows.Devices.Scanners.ImageScannerScanSource.flatbed)) {
                        // Set the scan file format to Device Independent Bitmap (DIB)
                        myScanner.flatbedConfiguration.format = Windows.Devices.Scanners.ImageScannerFormat.deviceIndependentBitmap;                    
                        WinJS.log && WinJS.log("Scanning.", "sample", "status");
    
                        // Scan API call to start scanning from the Flatbed source of the scanner.
                        return scanningPromise = myScanner.scanFilesToFolderAsync(Windows.Devices.Scanners.ImageScannerScanSource.flatbed, folder);
                    } else {
                        WinJS.log && WinJS.log("The selected scanner does not report to be equipped with a Flatbed.", "sample", "error");
                        return WinJS.Promise.then(null);
                    }
                } else {
                    // Scenario has already been canceled; return nullptr so no further action is possible 
                    return WinJS.Promise.then(null);
                }
            }).done(function (result) {
                scenarioRunning = false;
                updateStartAndEndScenarioButtons();
                // Check for result to prevent showing results in case of cancellation and scanner not equipped with flatbed source.
                if (result) {
                    if (result.scannedFiles.size > 0) {
                        displayResults(result.scannedFiles);
    
  4. Feeder scan

    Feeder scanners can scan all pages loaded in the feeder. In this example, the app checks if the scanner supports PNG file format, grayscale and duplex mode. If the scanner supports any of these modes, it will apply them. If not, it will apply the defaults, which are DIB file format, grayscale, and non-duplex.

                if (scenarioRunning) {
                    if (myScanner.isScanSourceSupported(Windows.Devices.Scanners.ImageScannerScanSource.feeder)) {
                        // Update Feeder Configuration
                        // Set the scan file format to PNG, if available, if not to DIB
                        if (myScanner.feederConfiguration.isFormatSupported(Windows.Devices.Scanners.ImageScannerFormat.png)) {
                            myScanner.feederConfiguration.format = Windows.Devices.Scanners.ImageScannerFormat.png;
                        } else {
                            myScanner.feederConfiguration.format = Windows.Devices.Scanners.ImageScannerFormat.deviceIndependentBitmap;
                        }
    
                        // Set the color mode to Grayscale, if available
                        if (myScanner.feederConfiguration.isColorModeSupported(Windows.Devices.Scanners.ImageScannerColorMode.grayscale)) {
                            myScanner.feederConfiguration.colorMode = Windows.Devices.Scanners.ImageScannerColorMode.grayscale;
                        }
    
                        // Set feeder to scan duplex
                        myScanner.feederConfiguration.duplex = myScanner.feederConfiguration.canScanDuplex;
    
                        // Set MaxNumberOfPages to zero to scan all the pages that are present in the feeder
                        myScanner.feederConfiguration.maxNumberOfPages = 0;
    
                        WinJS.log && WinJS.log("Scanning.", "sample", "status");
    
                        // Scan API call to start scanning from the Feeder source of the scanner.
                        return scanningPromise = myScanner.scanFilesToFolderAsync(Windows.Devices.Scanners.ImageScannerScanSource.feeder, folder);
                    } else {
                        WinJS.log && WinJS.log("The selected scanner does not report to be equipped with a Feeder.", "sample", "error");
                        return WinJS.Promise.then(null);
                    }
                } else {
                    // Scenario has already been canceled; return nullptr so no further action is possible 
                    return WinJS.Promise.then(null);
                }
            }).done(function (result) {
                scenarioRunning = false;
                updateStartAndEndScenarioButtons();
                // Check for result to prevent showing results in case of cancellation and scanner not equipped with feeder source.
                if (result) {
                    if (result.scannedFiles.size > 0) {
                        displayResults(result.scannedFiles);
    

Cancel scanning

You can let users cancel the scan job midway through a scan, like this.

    function endScenario() {
        if (scenarioRunning) {
            scanningPromise.cancel();
            resetDisplay();
        }
    }

App capability declaration (optional)

Users can scan to any folder dynamically using the FolderPicker class, but you must declare the Pictures Library capability in the manifest to allow users to scan to that folder.

For more info on app capability, see App capability declarations.

Summary

In this page, you added the capability to scan from your app using JavaScript and HTML. To add scanning to your app using C#/C++ and XAML, see Scan from your app (Windows Store apps C#/C++ and XAML). Next, you might want to add printing to your app. For more info, see Printing.

Windows.Devices.Scanners namespace

Auto-Configured Scanning