Disclaimer: The information in this article & source code are published in accordance with the final [V1] bits of the .NET Framework
Abstract
This sample shows how to use Windows XP Windows Image Acquisition (WIA) Scripting with .NET and C#. It is useful for integrating with scanners, digital cameras, webcams and still-video.
Note, this article doesn't save you from reading the detailed WIA documentation!
WIA
WIA is a standardized Win32 API for acquiring digital images from devices that are primarily used to capture still images, and for managing these devices. WIA was introduced with Windows Millennium and updated for Windows XP. Today, most digital imaging devices are supported on XP by built-in or manufacturer provided WIA drivers.
The API is exposed as COM interfaces, in two flavors:
- WIA custom interfaces - mainly for C++ programmers.
- WIA Scripting Model - designed for scripting languagues and it provides a type library.
A seamless and low-effort integration with .NET is (currently) only possible with WIA Scripting.
WIA Scripting
The WIA Scripting Model is described in the WIA Scripting reference on MSDN Platform SDK. The typical steps needed to acquire an image are as follows:
- Create the
WIA Manager
COM object.
- With the help of the
WIA manager
, let the user select an imaging device (scanner/camera/...).
- The selected device gets accessible as a new
WIA root device item
(another COM object).
- With this device item, we present a GUI dialog to the user for picking up pictures.
- These pictures get accessible as a collection of
WIA image items
.
- Finally, we can transfer each of these image items e.g. to disk files!
With pseudo code this looks as simple as:
manager = new Wia
root = manager.Create
collection = root.GetItemsFromUI
collection[0..n].Transfer
WIA provides its own common dialogs to select a device:
and e.g. dialogs specific to a scanner device, ... or specific to a photo camera device:
Note, some tasks are also possible without user (GUI) interaction. One such method is Item.TakePicture
but you should check the documentation for a complete list.
The WIA Scripting Model organizes all known items (devices, folders, pictures,...) in a hierarchical structure, e.g.: WIA Camera Tree. An advanced application can recursively enumerate this tree using the Item.Children
property:
root e.g. Camera Device
+root.Children
item1
item2 e.g. Folder
+item2.Children
item21 e.g. Picture1
item22 e.g. Picture2
Code
To use WIA Scripting in your Visual Studio .NET project, add a reference to the component "Microsoft Windows Image Acquisition 1.01 Type Library" (wiascr.dll)
Without VS.NET, you will have to use the TLBIMP tool.
Now you can add the WIA Scripting namespace at the top of your C# code file:
using System.IO;
using System.Runtime.InteropServices;
using WIALib;
This imported library namespace provides mapping of the WIA Scripting types to .NET wrapper classes:
Wia
=> WiaClass
DeviceInfo
=> DeviceInfoClass
Item
=> ItemClass
Item.Children
=> CollectionClass
and now you can write code like this simplified sample to acquire pictures:
wiaManager = new WiaClass();
object selectUsingUI = System.Reflection.Missing.Value;
wiaRoot = (ItemClass) wiaManager.Create(
ref selectUsingUI );
wiaPics = wiaRoot.GetItemsFromUI( WiaFlag.SingleImage,
WiaIntent.ImageTypeColor ) as CollectionClass;
foreach( object wiaObj in wiaPics )
{
wiaItem = (ItemClass) Marshal.CreateWrapperOfType(
wiaObj, typeof(ItemClass) );
imageFileName = Path.GetTempFileName();
wiaItem.Transfer( imageFileName, false );
}
For more information on COM interop and WIA debugging read these two articles:
Asynchronous Transfer and Events
Some devices, especially photo-cameras on serial COM ports, are slow! So it will take many seconds to transfer pictures. WIA Scripting solves this issue with an asynchronous flag when using Item.Transfer
:
wiaItem.Transfer( imageFileName, true );
To notify the application about the completed transfer and more, the WIA manager exposes three events:
OnTransferComplete
- file transfer completed
OnDeviceDisconnected
- a device was e.g. unplugged
OnDeviceConnected
- a new device was connected
These events nicely map on to the .NET event/delegate model, so we add a handler function like so:
private _IWiaEvents_OnTransferCompleteEventHandler
wiaEvtTransfer;
...
wiaEvtTransfer = new _IWiaEvents_OnTransferCompleteEventHandler(
this.wia_OnTransferComplete );
wiaManager.OnTransferComplete += wiaEvtTransfer;
...
public void wia_OnTransferComplete(
WIALib.Item item, string path )
{
...
}
Video
For web cams or other video devices, WIA on Windows XP has a great new feature: live video stream overlay! It uses DirectShow
to draw the overlay on the graphics card. The IWiaVideo interface can be accessed by importing another COM type library: "WiaVideo 1.0 Type Library" (wiavideo.dll). Unfortunately, the embedded TLB has a bug for methods passing a window handle. I used ILDASM to get the IL code of the interop assembly, then I changed all incorrect occurances of 'valuetype _RemotableHandle&
' to 'native int
', then finally compiled back to an assembly with ILASM. This repaired DLL is included in the download as WIAVIDEOLib.dll.
The code to show a real-time and live video stream in a window could be as simple as these two steps:
wiaVideo = new WiaVideoClass();
wiaVideo.CreateVideoByWiaDevID(
wiaDeviceID, window.Handle, 0, 1 );
and to take a snapshot jpeg image from the current video stream is possible with one single method:
string jpgFile;
wiaVideo.TakePicture( out jpgFile );
Check the included video sample for more!
Samples
Full source code with Visual Studio .NET projects are provided for these samples:
- WiaEasyImage very simple application to access WIA scanners and cameras.
- WiaEasyVideo application only using WIA video devices, does show live video stream overlay.
- WiaScriptSample advanced application using most of WIA Scripting functions.
Limitations
- Again, for Windows XP only! if you need .NET imaging for older systems, try this TWAIN sample
- Windows ME has an older version of WIA, but you can't use the same code/type-lib from these samples for that version.
- WIA devices must be fully detected and configured by Windows.
- As far as I know, WIA needs your app to have the [STAThread] attribute on the Main() method used to launch your application.
Item.Thumbnail
was left out as it uses an undocumented Asynchronous Pluggable Protocol (APP) and has bugs.
- Code was only tested with an Olympus digi-cam, an Epson scanner, a Logitech QuickCam, and a Sony DV CamCorder.