Scan a document with Windows Image Acquisition

  • .NET

Windows Image Acquisition (WIA) was introduced with Windows 2000. This platform is intended to allow access to scanner and webcam devices without having to worry about the details of interfacing with them. In addition WIA included GUIs to help us use these devices from our code (script, COM, .NET via COM). Here is a diagram showing the architecture of WIA:

To use WIA from C# code, you must add the Microsoft Windows Image Acquisition Library v2.0 COM reference:

And add the corresponding using:

using WIA;

To start scanning a document, we use the CommonDialog class. This class is used to display the different screens provided by WIA. To scan a document, use its ShowAcquireImage method:

var dlg = new WIA.CommonDialog();
ImageFile image = dlg.ShowAcquireImage(
    DeviceType: WiaDeviceType.ScannerDeviceType,
    Intent: WiaImageIntent.ColorIntent,
    Bias: WiaImageBias.MinimizeSize,
    FormatID: ImageFormat.Jpeg.Guid.ToString("B"),
    AlwaysSelectDevice: true,
    UseCommonUI: true,
    CancelError: false);

Here is the description of the arguments:

  • ScannerDeviceType: Desired device type (scanner, camera, webcam)
  • Intent: Scanner Profile (color, black and white or text)
  • Bias: Quality
  • Format: Format of the desired image
  • AlwaysSelectDevice: Displays or not the device selection window
  • UseCommonUI: displays or not the UI
  • CancelError: throws an exception or not when the user cancels the scan

This method displays the following screens:

The ShowAcquireImage method returns an object of type ImageFile. This object is used to manipulate the result of the scan. For example, you can directly save the image to a file:

string path = @"demo.jpg";
if (image != null)
{
    image.SaveFile(path);
}

But often the result of scanning is heavy (several MB), so it is useful to apply a small compression before saving the file. For that we start by recovering the contents of the scanned image in the form of an array of bytes then we use the Encoder of the .NET framework to compress the image:

Vector vector = image.FileData;
if (vector != null)
{
    byte[] bytes = vector.get_BinaryData() as byte[];
    if (bytes != null)
    {
        using (var ms = new MemoryStream(bytes))
        {
            using (Bitmap bitmap = new Bitmap(ms))
            {
                ImageCodecInfo codecInfo = ImageCodecInfo.GetImageDecoders().First(codec => codec.FormatID == ImageFormat.Jpeg.Guid);
                Encoder encoder = Encoder.Quality;
                EncoderParameters parameters = new EncoderParameters(1);
                EncoderParameter qualityParameter = new EncoderParameter(encoder, 80L); // quality 80%
                parameters.Param[0] = qualityParameter;
                bitmap.Save(path, codecInfo, parameters);
            }
        }
    }
}

In a few lines of code and using Windows Image Acquisition, we can offer a graphical interface to the user to scan a document whatever its scanner.

Do you have a question or a suggestion about this post? Contact me on Twitter or by email!

Follow me:
Enjoy this blog?Buy Me A CoffeeDonate with PayPal