CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8

Hybrid View

  1. #1
    Join Date
    Oct 2007
    Posts
    25

    Windows Image Acquisition (WIA) Code

    I would like to give back to the community here by posting some code on how to use WIA for an ADF scanner.

    The lack of C# examples makes it difficult for the average coder to figure out. Firstly, please understand that I am relatively new to csharp and this is my first attempt at coding with WIA. I am sure there are parts that could be done better and I'm still not convinced I'm doing it the correct way, however it works which is better than any other example I could find.

    An Important note for those who are not aware: WIA only works on windows ME, XP and Vista. Vista uses a newer version of WIA and I have not tested this code on Vista yet. I have only tested with XP. TWAIN is more compatible with different operating systems.

    Please note that if you are planning on using WIA for a digital camera, then the example over here - http://www.codeproject.com/dotnet/wi...tingdotnet.asp - should be sufficient enough.

    Unfortunately when using a flatbed scanner with an ADF (Auto Document Feeder) tray the example does not work. My project required using an HP scanjet 5590 scanner. The users would be scanning up to 100 pages at a time.

    Firstly, you will need the WIA Automation Library 2.0 to be added as a reference in your project. This library can be downloaded from Microsoft's website. You are looking for wiaaut.dll.

    Once you've got the library installed and added as a reference in your project you may need the following variables in your class:

    Code:
    string DeviceID;
    
    const string wiaFormatBMP ="{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}";		
    const string wiaFormatPNG ="{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}";
    const string wiaFormatGIF ="{B96B3CB0-0728-11D3-9D7B-0000F81EF32E}";
    const string wiaFormatJPEG ="{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}";
    const string wiaFormatTIFF ="{B96B3CB1-0728-11D3-9D7B-0000F81EF32E}";
    These are probably in an enum somewhere in the class as well if you look hard enough. Please take note of the DeviceID string. I initially coded my scanning to select which scanning device on one button's event and then scan on another button's event. To be able to determine which scanner was selected you will need to remember the DeviceID.

    The following code is part of some code that gave me a breakthrough in how to determine if there is another page waiting to be scanned in the ADF tray. It is required in order for the main code to work.

    Code:
    class WIA_DPS_DOCUMENT_HANDLING_SELECT
    	{
    		public const uint FEEDER = 0x00000001;
    		public const uint FLATBED = 0x00000002;
    	}
    
    	class WIA_DPS_DOCUMENT_HANDLING_STATUS
    	{
    		public const uint FEED_READY = 0x00000001;
    	}
    
    	class WIA_PROPERTIES
    	{
    		public const uint WIA_RESERVED_FOR_NEW_PROPS = 1024;
    		public const uint WIA_DIP_FIRST = 2;
    		public const uint WIA_DPA_FIRST  =  WIA_DIP_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
    		public const uint WIA_DPC_FIRST  = WIA_DPA_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
    		//
    		// Scanner only device properties (DPS)
    		//
    		public const uint WIA_DPS_FIRST    =                      WIA_DPC_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
    		public const uint WIA_DPS_DOCUMENT_HANDLING_STATUS  =     WIA_DPS_FIRST + 13;
    		public const uint WIA_DPS_DOCUMENT_HANDLING_SELECT  =     WIA_DPS_FIRST + 14;
    	}
    
    	class WIA_ERRORS
    	{
    		public const uint BASE_VAL_WIA_ERROR = 0x80210000;
    		public const uint WIA_ERROR_PAPER_EMPTY  = BASE_VAL_WIA_ERROR + 3;
    	}
    Now comes the most important part. The actual scanning. Most of it should be commented sufficiently enough.


    Code:
    void ADFScan()
    		{
    			
    			//Choose Scanner
    			CommonDialogClass class1 = new CommonDialogClass();
    			Device d = class1.ShowSelectDevice(WiaDeviceType.UnspecifiedDeviceType, true,false);
    			if (d != null)
    			{
    				this.DeviceID = d.DeviceID;
    			}
    			else
    			{
    				//no scanner chosen
    				return;
    			}
    			
    			
    			
    			WIA.CommonDialog WiaCommonDialog = new CommonDialogClass();
    			
    			bool hasMorePages = true;
    			int x = 0;
    			int numPages = 0;
    			while (hasMorePages)
    			{
    				//Create DeviceManager
    				DeviceManager manager = new DeviceManagerClass();
    				Device WiaDev = null;
    				foreach (DeviceInfo info in manager.DeviceInfos)
    				{
    					if (info.DeviceID == this.DeviceID)
    					{
    						WIA.Properties infoprop = null;
    						infoprop = info.Properties;
    						
    						//connect to scanner
    						WiaDev = info.Connect();
    
    						
    						break;
    					}
    				}
    				
    				
    				
    				//Start Scan
    				
    				WIA.ImageFile img = null;
    				WIA.Item Item = WiaDev.Items[1] as WIA.Item;
    				
    				try
    				{
    
    					img = (ImageFile)WiaCommonDialog.ShowTransfer(Item,wiaFormatJPEG,false);
    
    
    					//process image:
    					//one would do image processing here
    					//
    
    					//Save to file
    					string varImageFileName = "c:\\test" + x.ToString() + ".jpg";
    					if (File.Exists(varImageFileName))
    					{
    						//file exists, delete it
    						File.Delete(varImageFileName);
    					}
    					img.SaveFile(varImageFileName);
    					numPages++;
    					img = null;
    					
    				}
    				catch (Exception ex)
    				{
    					MessageBox.Show("Error: " + ex.Message);
    				}
    				finally
    				{
    					Item = null;
    					//determine if there are any more pages waiting
    					Property 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;
    						
    						
    					}
    
    					hasMorePages = false; //assume there are no more pages
    					if (documentHandlingSelect != null)
    						//may not exist on flatbed scanner but required for feeder
    					{
    						//check for document feeder
    						if ((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);
    						}
    					}
    					x++;
    				}
    			}
    			
    		}
    On the HP scanjet I'm using if it does not find any pages in the ADF then it does a single scan from the glass tray. This still works. In the example above I am just saving the images to the root of c: drive and overwriting any existing images with the same name.

    In the comments where I've put "Image Processing" you can do you image manipulation like cropping, resizing, rotating, etc. before saving the image. There are supposedly built in functions to do this in the WIA automation library but I have been unsuccessful in getting them to work. I am instead using the multitude of image editing examples available on the net to do all those things.

    The only thing that concerns me with this code is that on every loop it reconnects to the scanner. I would have thought the logical thing would be to connect once and then tell it to scan another page. As much as I tried I could not get that to work. In the end this was the only way that seemed to work correctly and I have not had any issues with it.

    I hope this code helps someone

  2. #2
    Join Date
    Feb 2010
    Posts
    1

    Re: Windows Image Acquisition (WIA) Code

    i signed up to this site just to thank you, you are amazing!

  3. #3
    Join Date
    Oct 2010
    Posts
    1

    Smile Re: Windows Image Acquisition (WIA) Code

    Thanks for such a nice explanation. I am trying to run this code on XP (SP3) and using Fujitsu 6140 ADF scanner. The issue is the code keeps running even the feeder is empty. documentHandlingSelect.get_Value() always returns 1. Is there any way to rectify this?

  4. #4
    Join Date
    Jun 2012
    Posts
    1

    Re: Windows Image Acquisition (WIA) Code

    Is it applicable with ASP.net

  5. #5
    Join Date
    Oct 2007
    Posts
    25

    Re: Windows Image Acquisition (WIA) Code

    Quote Originally Posted by ameerasajid View Post
    Is it applicable with ASP.net
    I'm afraid I'm not really able to answer that.

    It's been 5 years since I posted the original info and not long after I switched to Java and php for coding predominantly, so my c# is a bit out of practice.

    I havn't worked with ASP much, but since I understand it's a server-side language (like php) I don't see it working for accessing the WIA unless the scanner was connected to the server - in which case I don't see the app being very useful. So my guess would be that you cannot do it.

  6. #6
    Join Date
    Nov 2012
    Posts
    1

    Re: Windows Image Acquisition (WIA) Code

    really really thank you.

    regards

  7. #7
    Join Date
    May 2016
    Posts
    1

    Re: Windows Image Acquisition (WIA) Code

    He has spent many days looking like using the ADF correctly.

    Thank you so much...

    I try with HP laserjetpro mfp m127fn and works!!!

  8. #8
    Join Date
    Feb 2019
    Posts
    1

    Re: Windows Image Acquisition (WIA) Code

    I have the same problem and I test with your code and it´s run ok on Windows 7 and hp LaserJet 570 scanner using adf, but the same code return error in Windows 10, when it try to capture the second page return error COM. Any idea?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured