Use WIA to retrieve images from scanner, digital camera or webcam using VB.NET and C#.

by admin on September 19, 2009

Get images from scanner, webcam or any other type of imaging device

Here’s the class that I wrote to extract images from various imaging devices via VB.NET and C#.

WIA (Windows Image Acquisition) supports the following types of devices:

  • Scanners
  • Digital Cameras
  • Webcams

The class correctly communicates with Windows Image Acquisition Library (WIALib), releases all COM objects used and allows you to select between single image or multiple images acquisition.

Downloadable package contains actual library that can be used with any of your projects and two demo projects (VB.NET and C#).

If you don’t want to download source code, you can copy it from the code box below.

WIA Wrapper Library, VB.NET Version

View Code VBNET
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports WIALib
Imports System.IO
 
Public Class ImageRetriever
 
    Public Function RetriveImages(ByVal selectionMode As ImageSelectionMode) As List(Of Bitmap)
 
        Dim comObjects As New List(Of Object)
 
        'Create WIA COM objects
 
        'Manager
        Dim manager As WiaClass = Nothing
        comObjects.Add(manager)
 
        'Devices collection
        Dim devices As CollectionClass = Nothing
        comObjects.Add(devices)
 
        'Root device
        Dim rootDevice As ItemClass = Nothing
        comObjects.Add(rootDevice)
 
        'Collection
        Dim pictures As CollectionClass = Nothing
        comObjects.Add(pictures)
 
        'Image
        Dim pictureItem As ItemClass = Nothing
        comObjects.Add(pictureItem)
 
        manager = New WiaClass()
 
        devices = TryCast(manager.Devices, CollectionClass)
 
        'Retrieve all devices
        If (devices Is Nothing) OrElse (devices.Count = 0) Then
            DisposeComObjects(comObjects)
            Throw New AcquisitionException("No devices found.")
        End If
 
        Dim UISelection As Object = System.Reflection.Missing.Value
 
        'WIA dialog, allows user to select a device
        rootDevice = DirectCast(manager.Create(UISelection), ItemClass)
 
        If rootDevice Is Nothing Then
            Throw New AcquisitionException("No device selected.")
        End If
 
        'WIA dialog, allows user to select a picture.
 
        Dim flag As WiaFlag = WiaFlag.SingleImage
        If selectionMode = ImageSelectionMode.Multiple Then flag = WiaFlag.UseCommonUI
 
        pictures = TryCast(rootDevice.GetItemsFromUI(flag, WiaIntent.ImageTypeColor), CollectionClass)
        If pictures Is Nothing Then
            DisposeComObjects(comObjects)
            Throw New AcquisitionException("No pictures selected.")
        End If
 
        Dim bitmapList As New List(Of Bitmap)
 
        For Each picture As Object In pictures
 
            Dim filePath As String = Path.GetTempFileName
            pictureItem = DirectCast(Marshal.CreateWrapperOfType(picture, GetType(ItemClass)), ItemClass)
            pictureItem.Transfer(filePath, False)
 
            bitmapList.Add(Image.FromFile(filePath))
 
            'Release COM object
            Marshal.ReleaseComObject(picture)
 
        Next
 
        Return bitmapList
 
        DisposeComObjects(comObjects)
 
    End Function
 
    Private Sub DisposeComObjects(ByVal objects As List(Of Object))
        For Each comObject In objects
            If comObject IsNot Nothing Then
                Marshal.ReleaseComObject(comObject)
            End If
        Next
    End Sub
 
End Class
 
Public Class AcquisitionException
    Inherits Exception
 
    Public Sub New(ByVal message As String)
        MyBase.New(message)
    End Sub
 
End Class
 
Public Enum ImageSelectionMode
    One = 0
    Multiple = 1
End Enum

WIA Wrapper Class, CSharp version

View Code CSHARP
 
using System.Drawing;
using System.Runtime.InteropServices;
using WIALib;
using System.IO;
 
 
public class ImageRetriever
{
 
 
    public List<Bitmap> RetriveImages(ImageSelectionMode selectionMode)
    {
 
        List<object> comObjects = new List<object>();
 
        //Create WIA COM objects
 
        //Manager
        WiaClass manager = null;
        comObjects.Add(manager);
 
        //Devices collection
        CollectionClass devices = null;
        comObjects.Add(devices);
 
        //Root device
        ItemClass rootDevice = null;
        comObjects.Add(rootDevice);
 
        //Collection
        CollectionClass pictures = null;
        comObjects.Add(pictures);
 
        //Image
        ItemClass pictureItem = null;
        comObjects.Add(pictureItem);
 
        manager = new WiaClass();
 
        devices = manager.Devices as CollectionClass;
 
 
        //Retrieve all devices
        if ((devices == null) || (devices.Count == 0)) {
            DisposeComObjects(comObjects);
            throw new AcquisitionException("No devices found.");
        }
 
 
        object UISelection = System.Reflection.Missing.Value;
 
 
        //WIA dialog, allows user to select a device
        rootDevice = (ItemClass)manager.Create(UISelection);
 
 
 
        if (rootDevice == null) {
            throw new AcquisitionException("No device selected.");
        }
 
        //WIA dialog, allows user to select a picture.
 
        WiaFlag flag = WiaFlag.SingleImage;
        if (selectionMode == ImageSelectionMode.Multiple) flag = WiaFlag.UseCommonUI; 
 
 
        pictures = rootDevice.GetItemsFromUI(flag, WiaIntent.ImageTypeColor) as CollectionClass;
        if (pictures == null) {
            DisposeComObjects(comObjects);
            throw new AcquisitionException("No pictures selected.");
        }
 
        List<Bitmap> bitmapList = new List<Bitmap>();
 
        foreach (object picture in pictures) {
 
            string filePath = Path.GetTempFileName;
            pictureItem = (ItemClass)Marshal.CreateWrapperOfType(picture, typeof(ItemClass));
            pictureItem.Transfer(filePath, false);
 
            bitmapList.Add(Image.FromFile(filePath));
 
            //Release COM object
 
            Marshal.ReleaseComObject(picture);
        }
 
 
        return bitmapList;
 
 
 
        DisposeComObjects(comObjects);
    }
 
    private void DisposeComObjects(List<object> objects)
    {
        foreach (var comObject in objects) {
            if (comObject != null) {
                Marshal.ReleaseComObject(comObject);
            }
        }
    }
 
}
 
 
public class AcquisitionException : Exception
{
 
    public AcquisitionException(string message) : base(message)
    {
    }
 
}
 
public enum ImageSelectionMode
{
    One = 0,
    Multiple = 1
}

Downloadable version

Download full package

{ 3 comments… read them below or add one }

MarkToo January 16, 2010 at 9:05 pm

Thanks - It actuall works!
I could not get the AVICap functions to recognise anything other than the base USB camera.
This sytem (WIA) allows all USB devices to be sourced and selected
Now the fun in trying to make it do what I want to do.
Thanks for the kick start
managed to get it working inVB express 2008 which is free from Microsoft.
After TurboPascal 7 this program is a real bugger to learn

bowsil January 27, 2010 at 4:07 am

Not so great /….. you are doing what mspaint does… can you bring the video and image in the same form instead of opening the default add with the camera… any how thanks for the post….

Ben April 22, 2010 at 11:04 am

Do you know of a way to scan from default scanner without any user intervention (without showing the dialog)?

Leave a Comment

Previous post: Strict VB.NET

Next post: Group Properties into Categories