posts - 94, comments - 121, trackbacks - 82

My Links

News

View Anthony Trudeau's profile on LinkedIn

Add to Technorati Favorites

Article Categories

Archives

Post Categories

Image Galleries

Other Links

Using WIA for scanning

I was playing around this morning with scanning images and put together an adapter class that uses the Windows automation library (WIAAUT.DLL) which is part of the WIA automation SDK -- WIA means Windows Image Acquisition.

Here are the imports I used for the code file:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using WIA;

I created a simple enumeration for some of the more common errors that I expected.

public enum WiaScannerError : uint
{
     LibraryNotInstalled = 0x80040154,
     OutputFileExists = 0x80070050,
     ScannerNotAvailable = 0x80210015,
     OperationCancelled = 0x80210064
}

Instead of throwing a COMException I created a special exception class that provides an error code from the aforementioned enumeration.

[Serializable]
public class WiaOperationException :
Exception
{
     private WiaScannerError _errorCode;

     public WiaOperationException(WiaScannerError errorCode)
          : base()
     {
          ErrorCode = errorCode;
     }

     public WiaOperationException(string message, WiaScannerError errorCode)
          : base(message)
     {
          ErrorCode = errorCode;
     }

     public WiaOperationException(string message, Exception innerException)
          : base(message, innerException)
     {
          COMException comException = innerException as COMException;

          if (comException != null)
               ErrorCode = (WiaScannerError)comException.ErrorCode;
     }

     public WiaOperationException(string message, Exception innerException, WiaScannerError errorCode)
          : base(message, innerException)
     {
          ErrorCode = errorCode;
     }

     public WiaOperationException(System.Runtime.Serialization.SerializationInfo info, 
          System.Runtime.Serialization.StreamingContext context)
               : base(info, context)
     {
          info.AddValue("ErrorCode", (uint)_errorCode);
     }

     public WiaScannerError ErrorCode
     {
          get { return _errorCode; }
          protected set { _errorCode = value; }
     }

     public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context)
     {
          base.GetObjectData(info, context);
          ErrorCode = (WiaScannerError)info.GetUInt32("ErrorCode");
     }
}

The actual class I created is just for scanners, but you can adapt it to any device that supports WIA.  I've pulled out comments and removed some extra stuff like providing a friendly message for errors for the sake of brevity.

public sealed class WiaScannerAdapter : IDisposable
{
     private CommonDialogClass _wiaManager;
     private bool _disposed;
// indicates if Dispose has been called

 
    public WiaScannerAdapter()
     {
     }

     ~WiaScannerAdapter()
     {
          Dispose(false);
     }

     private CommonDialogClass WiaManager
     {
          get { return _wiaManager; }
          set { _wiaManager = value; }
     }

     [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
     public Image ScanImage(ImageFormat outputFormat, string fileName)
     {
          if (outputFormat == null)
               throw new ArgumentNullException("outputFormat");

          FileIOPermission filePerm =
               new FileIOPermission(FileIOPermissionAccess.AllAccess, fileName));
          filePerm.Demand();

          ImageFile imageObject = null;

         
try
         
{
               if (WiaManager == null)
                    WiaManager = new CommonDialogClass();

               imageObject =
                    WiaManager.ShowAcquireImage(WiaDeviceType.ScannerDeviceType,
                         WiaImageIntent.ColorIntent, WiaImageBias.MinimizeSize, 
                         outputFormat.Guid.ToString("B"), false, true, true);

               imageObject.SaveFile(fileName);
               return Image.FromFile(fileName);
          }
          catch (COMException ex)
          {
               string message = “Error scanning image“;
               throw new WiaOperationException(message, ex);
          }
         
finally
         
{
               if (imageObject != null)
                    Marshal.ReleaseComObject(imageObject);
          }
     }

     public void Dispose()
     {
          Dispose(true);
          GC.SuppressFinalize(this);
     }

     private void Dispose(bool disposing)
     {
          if (!_disposed)
          {
               if (disposing)
               {
                   
// no managed resources to cleanup
               
}

             
// cleanup unmanaged resources
             
if (_wiaManager != null)
                   Marshal.ReleaseComObject(_wiaManager);

              _disposed = true;
          }
     }
}

Calling the adapter is really easy.  Here's an example that puts the image into a picturebox:

using (WiaScannerAdapter adapter = new WiaScannerAdapter())
{
    
try
    
{
          Image image = adapter.ScanImage(ImageFormat.Bmp, @"c:\temp\test.bmp");
          pictureBox1.Image = image;
     }
     catch (WiaOperationException ex)
     {
          MessageBox.Show(ex.Message + “ Error Code: “ + ex.ErrorCode);
     }
}

Print | posted on Saturday, July 29, 2006 10:33 AM | Filed Under [ .NET ]

Feedback

Gravatar

# re: Using WIA for scanning

Hi,
I try to take photo from my QuickCam using WIA, but i don't succeed to set the default size of capture ...

Do you know an issue to do it ?
Regards
8/11/2006 8:43 AM | shinji_rem
Gravatar

# re: Using WIA for scanning

Quickcam's WIA support is quite frankly terrible. Even in a normal application such as mspaint it won't go above its minimum resolution.
9/25/2006 5:22 AM | Pug
Gravatar

# re: Using WIA for scanning

hi tony-

since i'm just getting started in both C# and WIA 2.0, would you please provide a more complete example of getting a scanned image from scanner to picturebox using your adapter?
from initializing the device, all the way through to viewing the image on-screen?

thanks ever so much.

-kevon
4/17/2007 8:04 AM | Kevon Ward
Gravatar

# re: Using WIA for scanning

What didn't work or wasn't complete about it? That's all you should have to do. Anything else is going to depend on your application, frameworks, UIs, etc. that you use.
4/17/2007 10:36 AM | Anthony Trudeau
Gravatar

# re: Using WIA for scanning


Hi,

How can I use the code sample inside Microsoft Access 2003.

I want to scan images from my scanner and sometimes from a digital camera into an Access form.


Thanks.
5/28/2007 7:27 AM | Ahmad Wali Zahid
Gravatar

# re: Using WIA for scanning

i get this library not installed error message, pls wat brings about it and wat can i do
9/24/2007 11:03 AM | AK
Gravatar

# re: Using WIA for scanning

Gracias... este ejemplo esta muy facil de enterder... me funciono a la perfeccion
10/9/2007 7:13 PM | Jorge
Gravatar

# re: Using WIA for scanning

Any idea how to register a WIA Event to receive a call-back when a picture is taken on a camera? It appears only 3 events are exposed by interop - camera connect, disconnect, and transfer completed.

Thanks.
10/30/2007 10:07 AM | Ron Redmer
Gravatar

# re: Using WIA for scanning

More information... in the ActiveX world, you would register these events this way:

'Register event for picture taken
wia.RegisterEvent wiaEventDeviceConnected, "*" 'Register event for camera connected
wia.RegisterEvent wiaEventDeviceDisconnected, "*" 'Register event for camera disconnected
wia.RegisterEvent wiaEventItemCreated, wiaAnyDeviceID


I'm not sure how to register the wiaEventItemCreated event in .NET...

Thanks!
10/30/2007 10:17 AM | Ron Redmer
Gravatar

# re: Using WIA for scanning

Use the Miscellaneous.wiaAnyDeviceID for the handle and then add an event handler for the OnEvent method of the DeviceManager.

I haven't tested this, but I think it'll work.
10/30/2007 10:53 AM | Anthony Trudeau
Gravatar

# re: Using WIA for scanning in MS Access

I also like to know if you have example for MS Access. I am writing small application where each record can have image, which can be scanned from scanner in a click of a button without going thru many other interfaces.

many thanks in advance.

Jay
1/15/2008 10:28 AM | Jay
Gravatar

# re: Using WIA for scanning

I don't have an example that uses any flavor of VB or VBA.
1/15/2008 10:38 AM | Anthony Trudeau
Gravatar

# re: Using WIA for scanning

i am looking for vb6 sample code using wia to capture and save imge file wid adf. I couldnt install MODI with office2003 as it install only MDIVWCTL.oca file which i couldnt access as component. Pls help some one as i need to capture msome multiple documents scanning.Kumar
9/26/2008 3:54 AM | kumar
Gravatar

# re: Using WIA for scanning

i want to duplex scanning using WIA can u help me

Regrads,

Vijay
9/22/2009 1:25 PM | vijay powar
Gravatar

# re: Using WIA for scanning

Hi,
Can u describe how to add this wia api to C# code?
11/3/2009 9:59 AM | Riasat Abir
Gravatar

# re: Using WIA for scanning

Query for "WIA automation SDK" on Bing to get a download link. Download it and then install it. Then add a reference to it from the COM tab which will create an Interop assembly which you then use like any .NET assembly.
11/3/2009 10:09 AM | Anthony Trudeau
Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification:
 

Powered by: