Creating a scanning application in C#

By FoxLearn 2/17/2025 7:43:02 AM   92
Creating a scanning application in C# typically involves using the Windows Image Acquisition (WIA) API, which provides a straightforward way to interact with imaging devices such as scanners and digital cameras.

WIA (also known as Windows Imaging Architecture) is a Microsoft API that allows communication between graphics software and imaging hardware, such as scanners, digital cameras, and video equipment.

Why WIA?

The WIA API simplifies device interaction for developers, manufacturers, and end users. It provides functionality such as:

  • Listing available image acquisition devices (scanners).
  • Managing multiple devices simultaneously.
  • Querying device properties in a standardized manner.
  • Acquiring data using high-performance transfer mechanisms.
  • Maintaining image properties across transfers.
  • Handling device status notifications and scan events.

Start by creating a new WinForms project in Visual Studio.

After that, you'll need to add the WIA COM component:

  1. In Visual Studio, right-click on your project in Solution Explorer.
  2. Select Add > Reference.
  3. In the opened window, select COM from the left-hand menu.
  4. Search for “Microsoft Windows Image Acquisition Library v2.0” and click OK.

Now, set the Embed Interop Types property of the WIA component to False:

  1. In Solution Explorer, select your project, then expand the References node.
  2. Find the WIA reference and in the Properties panel, set Embed Interop Types to False.

List Available Scanners

To list all connected scanners, you need to access the DeviceManager object from WIA.

var deviceManager = new DeviceManager();

for (int i = 1; i <= deviceManager.DeviceInfos.Count; i++)
{
    if (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType)
        continue;

    Console.WriteLine(deviceManager.DeviceInfos[i].Properties["Name"].get_Value());
}

Scanning and Saving Images

Once you have listed the available scanners, you can select one to connect to.

var deviceManager = new DeviceManager();
DeviceInfo firstScannerAvailable = null;

for (int i = 1; i <= deviceManager.DeviceInfos.Count; i++)
{
    if (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType)
        continue;

    firstScannerAvailable = deviceManager.DeviceInfos[i];
    break;
}

var device = firstScannerAvailable.Connect();
var scannerItem = device.Items[1];

var imageFile = (ImageFile)scannerItem.Transfer(FormatID.wiaFormatJPEG);
var path = @"C:\Users\<username>\Desktop\scan.jpeg";

if (File.Exists(path))
{
    File.Delete(path);
}

imageFile.SaveFile(path);

This code will connect to the first available scanner, scan the document, and save it as a JPEG on your desktop.

Adjust Scanner Properties

You can modify scanner settings such as resolution, brightness, contrast, and scan area before scanning.

private static void AdjustScannerSettings(IItem scannerItem, int resolutionDPI, int leftPixel, int topPixel, int widthPixels, int heightPixels, int brightness, int contrast, int colorMode)
{
    SetWIAProperty(scannerItem.Properties, "6147", resolutionDPI);
    SetWIAProperty(scannerItem.Properties, "6148", resolutionDPI);
    SetWIAProperty(scannerItem.Properties, "6149", leftPixel);
    SetWIAProperty(scannerItem.Properties, "6150", topPixel);
    SetWIAProperty(scannerItem.Properties, "6151", widthPixels);
    SetWIAProperty(scannerItem.Properties, "6152", heightPixels);
    SetWIAProperty(scannerItem.Properties, "6154", brightness);
    SetWIAProperty(scannerItem.Properties, "6155", contrast);
    SetWIAProperty(scannerItem.Properties, "6146", colorMode);
}

private static void SetWIAProperty(IProperties properties, object propName, object propValue)
{
    Property prop = properties.get_Item(ref propName);
    prop.set_Value(ref propValue);
}

To ensure the scan starts correctly, simply call the AdjustScannerSettings method before initializing the scanner.

// Create a DeviceManager instance
var deviceManager = new DeviceManager();

// Create an empty variable to store the scanner instance
DeviceInfo firstScannerAvailable = null;

// Loop through the list of devices to choose the first available
for (int i = 1; i <= deviceManager.DeviceInfos.Count; i++)
{
    // Skip the device if it's not a scanner
    if (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType)
        continue;

    firstScannerAvailable = deviceManager.DeviceInfos[i];

    break;
}

// Connect to the first available scanner
var device = firstScannerAvailable.Connect();

// Select the scanner
var scannerItem = device.Items[1];

int resolution = 150;
int width_pixel = 1250;
int height_pixel = 1700;
int color_mode = 1;
AdjustScannerSettings(scannerItem, resolution, 0, 0, width_pixel, height_pixel, 0, 0, color_mode);

// Retrieve a image in JPEG format and store it into a variable
var imageFile = (ImageFile)scannerItem.Transfer(FormatID.wiaFormatJPEG);

// Save the image in some path with filename
var path = @"C:\Users\<username>\Desktop\scan.jpeg";

if (File.Exists(path))
    File.Delete(path);

imageFile.SaveFile(path);

Exception Handling

WIA methods can throw exceptions. Handle these by wrapping your code in a try-catch block. Catch the COMException to identify specific error codes:

using System.Runtime.InteropServices;

try
{
    // WIA scanning code
}
catch (COMException e)
{
    uint errorCode = (uint)e.ErrorCode;

    if (errorCode == 0x80210006)
    {
        Console.WriteLine("Scanner is busy or not ready.");
    }
    else if (errorCode == 0x80210064)
    {
        Console.WriteLine("Scanning process was cancelled.");
    }
    // Add more error handling as necessary
}

Show Scanning Progress

To display scanning progress, you can use the ShowTransfer method from the CommonDialogClass:

using WIA;
using System.Runtime.InteropServices;

var dlg = new CommonDialogClass();
try
{
    object scanResult = dlg.ShowTransfer(scannerItem, WIA.FormatID.wiaFormatPNG, true);
    if (scanResult != null)
    {
        ImageFile image = (ImageFile)scanResult;
        // Process the image as needed
    }
}
catch (COMException e)
{
    Console.WriteLine(e.ToString());
    // Handle errors as previously shown
}

With the steps above, you can create a basic scanning application in C#.