Windows Image Acquisition (WIA)

May 15, 2011

Introduction

A couple of years ago, in December 2006, I had to write a program that was able to instruct a scanner to scan a document and save the result to an image file. Back then, I had to write it using Delphi 6. After some research (or Googling) I came accross the Windows Image Acquisition platform.

The WIA platform enables you to interact with imaging hardware such as scanners, webcams, printers…etc. allowing you to talk to hardware from different manufacturers. Wondering if this platform is still supported on Windows 7 I decided to find out. Let’s see if we can scan some documents.

Table Of Contents

WIA 2.0 & Windows 7

WIA 1.0 was introduced in Windows Me (Mistake Edition) and XP. WIA 2.0 was released with Windows Vista and is mainly targeted towards scanners. Check out the Windows Portable Devices (WPD) API for dealing with digital camers and digital video devices.

So WIA 2.0 was introduced with Vista, but is it still supported in Windows 7? For this post I hooked up a HP Scanjet 4670 scanner, but any WIA-compatible scanner will do.

HP Scanjet 4670

Top of page

System Devices

Let’s start by listing all the WIA-compatible devices connected to our PC. Start up Visual Studio 2010 and create a new blank solution named WIA. Add a new Windows Forms application called ScanIt to it.

Solution Explorer

To access WIA 2.0, you’ll need to add a reference to the COM library “Microsoft Windows Image Acquisition Library v2.0”.

WIA 2.0 COM Reference

Go ahead and add the reference. Afterwards select the reference and set the property Embed Interop Types to false.

WIA Reference

Next I added a listbox (“Devices”) and a button (“ListDevices”) to the main form.

Main Form Design

In the button’s Click event handler I added the following code:

private void ListDevices_Click(object sender, EventArgs e)
{
    // Clear the ListBox.
    Devices.Items.Clear();

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

    // Loop through the list of devices and add the name to the listbox
    for (int i = 1; i <= deviceManager.DeviceInfos.Count; i++)
    {
        var deviceName = deviceManager.DeviceInfos[i].Properties["Name"].get_Value().ToString();
        Devices.Items.Add(deviceName);
    }
}

Remark: Note that in the code I treat the DeviceInfos array as a 1-based array instead of a zero-based array! If you treat it as a zero-based array you’ll get a COM exception (“Exception from HRESULT: 0x8021006B”).

Com Exception

Hit F5 to run the application and click the button to list all the WIA-compatible devices.

WIA Compatible Devices

Top of page

Scanners

For this post we’re only interested in scanners, not all the devices. We need to figure out which device is a scanner and which is not. Luckily this information is provided by the WIA platform. The DeviceInfo instance contains a Type property which retrieves the type of the Windows Image Acquisition (WIA) hardware device.

The possible values for the Type property are:

  • Digital Camera
  • Scanner
  • Streaming Video
  • Default

Add a new class type called Scanner to the application and add the following code it:

public class Scanner
{
    private readonly DeviceInfo _deviceInfo;

    public Scanner(DeviceInfo deviceInfo)
    {
        this._deviceInfo = deviceInfo;
    }

    public void Scan()
    {
        // Connect to the device and instruct it to scan
    }

    public override string ToString()
    {
        return this._deviceInfo.Properties["Name"].get_Value();
    }
}

Now adjust the code of the ListDevices button’s Click event handler as follows:

private void ListDevices_Click(object sender, EventArgs e)
{
    // Clear the ListBox.
    Devices.Items.Clear();

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

    // Loop through the list of devices and add the name to the listbox
    for (int i = 1; i <= deviceManager.DeviceInfos.Count; i++)
    {
        //Add the device to the list if it is a scanner
        if (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType)
        {
            continue;
        }

        Devices.Items.Add(new Scanner(deviceManager.DeviceInfos[i]));
    }
}

Before adding a device to the list we check if it is in fact a scanner. If not, we skip it. Next we wrap the DeviceInfo instance in an instance of the Scanner class and add it to the list.

Top of page

Scanning

Once we’ve determined which scanners are linked to the computer we can instruct them to scan an image. Add a scan button to the main form and add the following code to it’s Click event handler.

private void Scan_Click(object sender, EventArgs e)
{
    // Scanner selected?
    var device = Devices.SelectedItem as Scanner;
    if (device == null)
    {
        MessageBox.Show("Please select a device.", "Warning",
                        MessageBoxButtons.OK, MessageBoxIcon.Warning);
        return;
    }

    // Scan
    var image = device.Scan();

    // Save the image
    var path = @"c:\scan.jpeg";
    if (File.Exists(path))
    {
        File.Delete(path);
    }
    image.SaveFile(path);
}

This code checks if you selected a scanner in the ListBox, then instructs the selected scanner to scan an image and saves it to the root of the C-drive.

Scan It Application

The implementation for the Scan method of the Scanner class is quite simple:

public ImageFile Scan()
{
    // Connect to the device
    var device = this._deviceInfo.Connect();

    // Start the scan
    var item = device.Items[1];
    var imageFile = (ImageFile) item.Transfer(FormatID.wiaFormatJPEG);

    // Return the imageFile
    return imageFile;
}

A connection to the device is established by calling the Connect method of the DeviceInfo instance. This method returns an instance of the Device class. Next the image is scanned by calling the Transfer method on the first item found in the Device’s Items array property. You can specify the desired format (JPEG, GIF, PNG…) when calling the Transfer method. Just make sure your scanner supports the selected format.

Using the WIA platform you can also control the settings of your scanner (DPI, grayscale…etc.), but I’ll leave that to the reader as an exercise. You can find the source code for this article on the download page of this blog.

Top of page

Advertisements

30 Responses to “Windows Image Acquisition (WIA)”

  1. Tyler Says:

    //I think the following bug fix would be good:

    if (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType)
    {
    continue; //return;
    }

  2. Ansuya Says:

    Hello Sir
    var deviceName = deviceManager.DeviceInfos[i].Properties[“Name”].get_Value().ToString();

    I have some problem in properties.

  3. cronous Says:

    //Add the device to the list if it is a scanner
    if (deviceManager.DeviceInfos[i].Type == WiaDeviceType.ScannerDeviceType)
    {
    Devices.Items.Add(new Scanner(deviceManager.DeviceInfos[i]));
    }

    • Christophe Says:

      I guess that also works. I just skipped those devices that weren’t a scanner and added the rest (the scanners). 😉

  4. cronous Says:

    Hi,
    Could you please, give me for the guideline for controlling the settings of scanner DPI, grayscale

  5. Christophe Says:

    Cronous,

    Check out the following SO question:

    http://stackoverflow.com/questions/956158/wia-through-web-browser-asp-net

    If you are interested in using WIA through a browser.

  6. LOAS Says:

    Thank you, thank you, thank you! You helped me past a bunch of stuff that would have tripped me up. You rock.

  7. kunal Says:

    hi this application works very well for selecting device only (i.e. camera) but doesnot scan the entire image and save it as desired path (i hv nikon camera and i wish to select it and scan its image and save it in sql database ) is it possible. how it can happen

    pls reply me soon i m waiting for ur response

    • Christophe Says:

      I only tested this with the scanner I mentioned in the post. Did not test this with digital cameras. I don’t have a Nikon camera, so it’s kind of hard for me to test what’s going on on your side.

      Do you receive an exception when you scan the image?

      • kunal Says:

        it don’t able to scan with nikon camera no any further action will done when i try to scan it but when we try to scan it with a hp laserjet scanner then how i save image in project folder as well as in database as blob with same image name

        pls reply me soon i m waiting for ur response

  8. kunal Says:

    and how i set the scanner properites that is image to grayscale and fit to width and height only.

  9. kunal Says:

    As u coding in your project of wia for saving image that is in C drive and the code are // Save the image
    var path = @”c:\scan.jpeg”;
    if (File.Exists(path))
    {
    File.Delete(path);
    }
    image.SaveFile(path);
    }

    if i try to save in project folder then how i save it with IMAGE NAME containing text of textbox1 that is image name is same as text in textbox1
    waiting for ur response and hearty thanks to ur all reply.

    • Christophe Says:

      One way would be to create a method with the following signature:

      public void SaveFile(string fileName, ImageFile image)
      {
      // Save the file here
      image.SaveFile(fileName);
      }

      Let’s assume this method is part of a class called Scanner. You can then call it as follows.

      var scanner = new Scanner();
      var image = scanner.Scan();
      scanner.Save(textBox1.Text, image);

      Hope it helps. This is pretty basic and has little to do with the actual article. I suggest asking such questions on a forum like StackOverflow.com.

      Hope it helps.

  10. kunal Says:

    Thanks a lot u really help me. My ongoing project was stop at this moment. but u help me and my project comes to near about deadline Thanks a lot

  11. Pradeep Says:

    How can we call this windows application from the webpage while passing a id string for saving the scanned image.
    and back in the webpage fetch the image and upload it to server…

  12. chandrasekhar Says:

    Hi,
    I want to scan the documents in c# .please help me ……….

  13. chandrasekhar Says:

    Hello sir,

    I am getting the following error …..

    Exception from HRESULT: 0x80210006 (COM exception was unhandled

    Please help me……

  14. yasir Says:

    Hi i want to ask a question that is when ui us the below code i get the deviceManager.DeviceInfos.Count as 0 so loop do not continue.Although i have used a WIa compatible webcam the code works fine in windows XP but when i run the code in windoows server 2008 R2 or Windows 7 with the same web cam the count returned is zero.. so please help me. what’s the problem causing that, any idea.

    var deviceManager = new DeviceManager();
    for (int i = 1; i <= deviceManager.DeviceInfos.Count; i++)
    {
    var deviceName = deviceManager.DeviceInfos[i].Properties["Name"].get_Value().ToString();
    Devices.Items.Add(deviceName);
    }


  15. Dear All
    Where can I download wia dll file? I can only find WIAAutSDK which does not have the libraries for this example.

  16. Raghavendra Says:

    Hi Sir,

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

    // Loop through the list of devices and add the name to the listbox
    for (int i = 1; i <= deviceManager.DeviceInfos.Count; i++)
    {
    Under this code no devices are loaded. Please help me out sir

  17. wisam Says:

    Hi Sir,
    How can I use scanner wizard dialog instead of direct scanning to image???

  18. ddanone Says:

    Thanks Christophe, this has been really useful for me.

  19. Jani Majerič Says:

    Hello,

    I am making an app with wia for scanning documents and images, the problem I have is when I try to set the page size. Every time I try i get the following exception:

    An unhandled exception of type ‘System.Runtime.InteropServices.COMException’ occurred in DigiKnjiga.exe

    Additional information: Exception from HRESULT: 0x80210067

    This exception is thrown when I call this line of code:

    Device.Items[1].Properties[“3097”].set_Value(0);

    which should set the page size to an A4 format.

    Do you have any idea what could be the problem in this case.

    Thank you in advance.

    P.S.: the full code for the scan event can be found here:

    http://social.msdn.microsoft.com/Forums/vstudio/en-US/d3b03392-e9a8-431c-bfda-0098b28fcc14/wia-setting-up-page-size-does-not-work?forum=wpf

    or on stackoverflow:

    http://stackoverflow.com/questions/24940291/wia-setting-up-page-size-does-not-work

    where I have already asked the question but have gotten no real solutions to the problem.

  20. Dhanshri Says:

    Thank you for code…. It helps me a lot…. But there are 2 errors please help me..

    var image = device.Scan();
    at above line error is “Cannot assign void to an implicitly-typed local variable”

    var device = this._deviceInfo.Connect();
    at above line error is ‘WIA.Form1’ does not contain a definition for ‘_deviceInfo’ and no extension method ‘_deviceInfo’ accepting a first argument of type ‘WIA.Form1’ could be found (are you missing a using directive or an assembly reference?)

    please rply asap


Comments are closed.

%d bloggers like this: