Introduction
The development of windows imaging applications requires choosing an API to communicate with scanner s or cameras. The most used APIs are WIA and TWAIN.
The WIA (Windows Image Acquisition) platform enables imaging/graphics applications to interact with imaging hardware and standardizes the interaction between different applications and scanners. This allows those different applications to talk to and interact with those different scanners without requiring the application writers and scanner manufactures to customize their application or drivers for each application-device combination. (http://msdn.microsoft.com/en-us/library/ms630368(VS.85).aspx)
TWAIN is a standard software protocol and applications programming interface (API) that regulates communication between software applications and imaging devices such as scanners and digital cameras. (http://www.twain.org/)
Differences:
1. WIA uses a common dialog for all devices while TWAIN uses a dialog created by the device manufacturer. Practically speaking, this almost always means that the TWAIN dialog will provide more options and advanced control over the device.
2. TWAIN allows you to use custom capabilities that the device manufacturer has created even though they don't exist in the TWAIN specifications.
3. In general, when a device supports both Twain and WIA, TWAIN is better for scanners and WIA is better for acquiring images from cameras and video devices.
4. TWAIN has three transfer modes (Native, Memory, File) and WIA only has two (Memory, File).
5. Most TWAIN sources save the settings of the previous scan while WIA does not.
6. TWAIN supports options for each page when scanning in duplex mode but WIA uses the same settings for both sides.
Problem
Usually, older scanners (drivers) are build for TWAIN and does not supported by WIA platform, moreover newer devices which created under Microsoft standard does not supported by TWAIN API.
In order to build scanning application that will communicate with both types of devices I combined those APIs under a uniform interface which will provide the easy access to both type of devices.
ScannerAdapterBase
public abstract class ScannerAdapterBase{protected List<Image> m_ImagesList = null;protected ScannerDeviceData m_ScannerDeviceData = null;// Initializes the Adapterpublic abstract void InitAdapter(nessScanning control, IMessageFilter messageFilter, IntPtr handle);// Selects scanning device, and returns the indicator that the device selected// Returns the indicator that the device selectedpublic abstract bool SelectDevice();// Acquires images from scanning device and fills ImagesLispublic abstract void AcquireImages(bool showUI);…}
Factory Method
public static ScannerAdapterBase GetScannerAdapter(nessScanning control, IMessageFilter messageFilter, IntPtr handle){lock (locker){bool isTwainDeviceSelected = false;if (m_ScannerAdapterBase != null){return m_ScannerAdapterBase;}try{//Checks WIA Devicesm_ScannerAdapterBase = new WiaScannerAdapter();m_ScannerAdapterBase.InitAdapter(control, messageFilter, handle);isWiaDeviceSelected = m_ScannerAdapterBase.SelectDevice();if (isWiaDeviceSelected){return m_ScannerAdapterBase;}//Checks TWAIN Devicesm_ScannerAdapterBase = new TwainScannerAdapter();m_ScannerAdapterBase.InitAdapter(control, messageFilter, handle);isTwainDeviceSelected = m_ScannerAdapterBase.SelectDevice();if (isTwainDeviceSelected){return m_ScannerAdapterBase;}}catch (ScannerException ex){throw ex;}return null;}}
Wia Adapter AcquireImages method
public override void AcquireImages(bool showUI){CommonDialogClass wiaCommonDialog = new CommonDialogClass();//Select Deviceif (m_DeviceID == null){Device device = null;try{device = wiaCommonDialog.ShowSelectDevice(WiaDeviceType.ScannerDeviceType, false, false);if (device != null){m_DeviceID = device.DeviceID;FillDeviceData(device);}else{return;}}catch (COMException ex){if ((WiaScannerError)ex.ErrorCode == WiaScannerError.ScannerNotAvailable){return;}else{WiaScannerException se = BuildScannerException(device, ex);throw se;}}}//Create DeviceManagerDeviceManager manager = new DeviceManagerClass();Device WiaDev = null;foreach (DeviceInfo info in manager.DeviceInfos){if (info.DeviceID == m_DeviceID){WIA.Properties infoprop = null;infoprop = info.Properties;//connect to scannerWiaDev = info.Connect();break;}}//Get Scanning PropertiesWIA.Item scanningItem = null;WIA.Items items = null;if (showUI){items = wiaCommonDialog.ShowSelectItems(WiaDev, WiaImageIntent.TextIntent, WiaImageBias.MinimizeSize, false, true, false);}else{items = WiaDev.Items;}if (items != null && items.Count > 0){scanningItem = items[1] as WIA.Item;}WIA.ImageFile imgFile = null;WIA.Item item = null;//Prepare ImagesListif (m_ImagesList == null){m_ImagesList = new List<Image>;}//Start Scanwhile (HasMorePages(WiaDev)){item = scanningItem;try{//Scan ImageimgFile = (ImageFile)wiaCommonDialog.ShowTransfer(item, ImageFormat.Jpeg.Guid.ToString("B")/* wiaFormatJPEG*/, false);byte[] buffer = (byte[])imgFile.FileData.get_BinaryData();MemoryStream ms = new MemoryStream(buffer);m_ImagesList.Add(Image.FromStream(ms));imgFile = null;}catch (COMException ex){if ((WiaScannerError)ex.ErrorCode == WiaScannerError.PaperEmpty){break;}else{WiaScannerException se = BuildScannerException(WiaDev, ex);throw se;}}catch (Exception ex){WiaScannerException se = BuildScannerException(WiaDev, ex);throw se;}finally{item = null;}}}
Wia Adapter HasMorePages method
private bool HasMorePages(Device WiaDev){try{bool hasMorePages = false;//determine if there are any more pages waitingProperty documentHandlingSelect = null;Property documentHandlingStatus = null;foreach (Property prop in WiaDev.Properties){if (prop.PropertyID == WIA_PROPERTIES.WIA_DPS_DOCUMENT_HANDLING_SELECT)documentHandlingSelect = prop;if (prop.PropertyID == WIA_PROPERTIES.WIA_DPS_DOCUMENT_HANDLING_STATUS)documentHandlingStatus = prop;}if (documentHandlingSelect != null) //may not exist on flatbed scanner but required for feeder{//check for document feederif ((Convert.ToUInt32(documentHandlingSelect.get_Value()) & WIA_DPS_DOCUMENT_HANDLING_SELECT.FEEDER) != 0){hasMorePages = ((Convert.ToUInt32(documentHandlingStatus.get_Value()) & WIA_DPS_DOCUMENT_HANDLING_STATUS.FEED_READY) != 0);}}return hasMorePages;}catch (COMException ex){WiaScannerException se = BuildScannerException(WiaDev, ex);throw se;}}
TWAIN Adapter AcquireImages method
public ArrayList TransferPictures(){ArrayList pics = new ArrayList();if (srcds.Id == IntPtr.Zero){return pics;}TwRC rc;IntPtr hbitmap = IntPtr.Zero;TwPendingXfers pxfr = new TwPendingXfers();do{pxfr.Count = 0;hbitmap = IntPtr.Zero;TwImageInfo iinf = new TwImageInfo();rc = DSiinf(appid, srcds, TwDG.Image, TwDAT.ImageInfo, TwMSG.Get, iinf);if (rc != TwRC.Success){CloseSrc();return pics;}rc = DSixfer(appid, srcds, TwDG.Image, TwDAT.ImageNativeXfer, TwMSG.Get, ref hbitmap);if (rc != TwRC.XferDone){CloseSrc();return pics;}rc = DSpxfer(appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.EndXfer, pxfr);if (rc != TwRC.Success){CloseSrc();return pics;}pics.Add(hbitmap);}while (pxfr.Count != 0);rc = DSpxfer(appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.Reset, pxfr);return pics;}
nicee
ReplyDeleteI have the same code in my scanner app. Problem is that it only scans ONE document, even though feeder has multiple. Looking at the last DSpxfer call in the 'do' loop, the pxfr variable always returns zero. The "ScandAllPro" software that comes with the scanner empties the feeder, but my code does not. Any ideas?
ReplyDeleteI need to develop Vb.net Windows Application for scan Image..so Which one is best for scan either WIA or Twain...?Please direct me in right direction
ReplyDeleteI think WIA is better, because it doesn't require any installations on your clint PC, while for TWAIN you should install scanner drives. Disadvantage of WIA that not all scanners support it.
ReplyDeleteTo cover all the cases you can use a combination of both, in example that i attached (ScannerAdapterFactory class), first it tried to connect scanner via WIA and in case of failure it tries TWAN.
Very nice, and Can it scan duplex?
ReplyDeletenice information
ReplyDeleteThis can explain the difference between TWAIN and WIA in photocopy machine specs I was looking for
http://plazafotocopy.com/product/canon-ir-adv-c2220
Thanks for sharing
ReplyDeleteThis can explain the difference between TWAIN and WIA
Nice pattern, but twain doesn't work. as Will posted previously. Have any patches?
ReplyDeletenice post..much detailed than http://www.dynamsoft.com/blog/document-imaging/document-scanning-twain-wia-isis-sane/
ReplyDeleteI enjoyed the reading very much. Thanks.
thanks for the detailed article..keep up the good work!
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteI have installed a Teller Scanner TS240 device which works perfectly using the default scanLite application.
ReplyDeleteHowever, when I run your source code provided, I get a "no device selected error."
Kindly assist.