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”), falsetruetrue);

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);
}
}

      Ref:

http://geekswithblogs.net/tonyt/archive/2006/07/29/86608.aspx

.NET Image Scanner

TWAIN

Windows Image Acquisition (WIA)