C# WIA with Automatic Document Feeder (ADF) retuns only one page on certain scanners - image

I have a HP Scanjet 7000 (duplex & ADF scanner) and a HP Scanjet 5500c (only ADF) and a scanner program I'm developing which uses WIA 2.0 on Windows 7.
The problem is that the code works perfectly on the older scanner model, but on the newer one the code seems to run just fine through the first page, then fail on the second. If I step through the code around the following line;
image = (WIA.ImageFile)wiaCommonDialog.ShowTransfer(item, wiaFormatTIFF, false);
the old scanner stops and waits for another call to be made on the same reference, but the newer one just runs through all it's pages from the feeder in one continuous operation.
I notice if I'm using the default scanning program in Windows 7, the newer one returns a single .tif file which contains all the separate pages. The older one returns separate .jpg files (one for each page).
This indicates to me that the newer scanner is scanning through its whole feeder before it is ready to return a collection of images where the older one returns ONE image between each page scanned.
How can I support this behavior in code? The following is part of the relevant code which works on the older scanner model:
public static List<Image> Scan(string scannerId)
{
List<Image> images = new List<Image>();
List<String> tmp_imageList = new List<String>();
bool hasMorePages = true;
bool useAdf = true;
bool duplex = false;
int pages = 0;
string fileName = null;
string fileName_duplex = null;
WIA.DeviceManager manager = null;
WIA.Device device = null;
WIA.DeviceInfo device_infoHolder = null;
WIA.Item item = null;
WIA.ICommonDialog wiaCommonDialog = null;
manager = new WIA.DeviceManager();
// select the correct scanner using the provided scannerId parameter
foreach (WIA.DeviceInfo info in manager.DeviceInfos)
{
if (info.DeviceID == scannerId)
{
// Find scanner to connect to
device_infoHolder = info;
break;
}
}
while (hasMorePages)
{
wiaCommonDialog = new WIA.CommonDialog();
// Connect to scanner
device = device_infoHolder.Connect();
if (device.Items[1] != null)
{
item = device.Items[1] as WIA.Item;
try
{
if ((useAdf) || (duplex))
SetupADF(device, duplex); //Sets the right properties in WIA
WIA.ImageFile image = null;
WIA.ImageFile image_duplex = null;
// scan image
image = (WIA.ImageFile)wiaCommonDialog.ShowTransfer(item, wiaFormatTIFF, false);
if (duplex)
{
image_duplex = (ImageFile)wiaCommonDialog.ShowTransfer(item, wiaFormatPNG, false);
}
// save (front) image to temp file
fileName = Path.GetTempFileName();
tmp_imageList.Add(fileName);
File.Delete(fileName);
image.SaveFile(fileName);
image = null;
// add file to images list
images.Add(Image.FromFile(fileName));
if (duplex)
{
fileName_duplex = Path.GetTempFileName();
tmp_imageList.Add(fileName_duplex);
File.Delete(fileName_duplex);
image_duplex.SaveFile(fileName_duplex);
image_duplex = null;
// add file_duplex to images list
images.Add(Image.FromFile(fileName_duplex));
}
if (useAdf || duplex)
{
hasMorePages = HasMorePages(device); //Returns true if the feeder has more pages
pages++;
}
}
catch (Exception exc)
{
throw exc;
}
finally
{
wiaCommonDialog = null;
manager = null;
item = null;
device = null;
}
}
}
device = null;
return images;
}
Any help on this issue would be very much appreciated! I can't seem to find a working solution on the web. Just unanswered forum posts from people with the same problem.

we had a very similar problem and various solutions, e.g. by setting certain properties, did not help. The main problem was that the scanner (ADF) retracted all pages on startup, regardless of what was happening in the program code.
The process repeatedly led to errors, since "too much" was made before the next page was scanned. This applies in particular to the fact that another "Connect" was attempted.
For this reason, we have modified the code so that the individual pages can be read in as quickly as possible:
public List<Image> Scan(string deviceID)
{
List<Image> images = new List<Image>();
WIA.ICommonDialog wiaCommonDialog = new WIA.CommonDialog();
WIA.Device device = this.Connect(deviceID);
if (device == null)
return images;
WIA.Item item = device.Items[1] as WIA.Item;
List<WIA.ImageFile> wiaImages = new List<ImageFile>();
try
{
// scan images
do
{
WIA.ImageFile image = (WIA.ImageFile)wiaCommonDialog.ShowTransfer(item, wiaFormatJPEG, false);
wiaImages.Add(image);
} while (true);
}
catch (System.Runtime.InteropServices.COMException ex)
{
if ((uint)ex.ErrorCode != WIA_PROPERTIES.WIA_ERROR_PAPER_EMPTY)
throw ex;
}
catch (Exception ex)
{
throw ex;
}
foreach (WIA.ImageFile image in wiaImages)
this.DoImage(images, image);
return images;
}

I see you're calling a method called SetupADF, which is not shown, that presumably sets some properties on the device object. Have you tried setting WIA_DPS_PAGES (property 3096) and/or WIA_DPS_SCAN_AHEAD_PAGES (property 3094)?
I have a blog post about scanning from an ADF in Silverlight, and I believe a commenter came up against the same issue you're having. Setting WIA_DPS_PAGES to 1 fixed it for him. I ended up modifying my code's SetDeviceProperties method to set WIA_DPS_PAGES to 1 and WIA_DPS_SCAN_AHEAD_PAGES to 0.

After alot of trial and error I stumbled upon a solution which worked for reasons I'm not quite sure of. It seems like the ShowTransfer() method was unable to convert the page to .png or .tiff WHILE scanning. Setting the format to JPEG or BMP actually solved the issue for me:
image = (ImageFile)scanDialog.ShowTransfer(item, wiaFormatJPEG, false);
I think I saw somewhere on the web that this method actually returns BMP regardless of the format specified. Might be that converting the image to png or tiff is too heavy as opposed to using bmp or jpeg.
On a sidenote, I'm setting the property setting: 3088 to 0x005 (adf AND duplex mode).

Related

How does location cache works?

I have an application that gets the GPS location of the devices every time the user fills-up the form. My problem is capturing the GPS location takes too long. It takes about 40 seconds to 60 seconds before the GPS has been captured. I am using jamesmontemagno's Geolocator plugin.
GPS Parameters:
Accuracy: 100 meters
Timeout: 1 minute
Here is my code that I am using right now:
var defaultgpsaccuracy = Convert.ToDouble(Preferences.Get("gpsaccuracy", String.Empty, "private_prefs"));
var defaultgpstimeout = Convert.ToDouble(Preferences.Get("gpstimeout", String.Empty, "private_prefs"));
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = defaultgpsaccuracy;
position = await locator.GetLastKnownLocationAsync();
if (position != null)
{
string location = position.Latitude + "," + position.Longitude;
lblStartLocation.Text = location;
}
else
{
position = await locator.GetPositionAsync(TimeSpan.FromMinutes(defaultgpstimeout), null, false);
string location = position.Latitude + "," + position.Longitude;
lblStartLocation.Text = location;
}
These are my questions:
I used locator.GetLastKnownLocationAsync(); how long before the location cache refreshes?
And does the last known location refreshes when there is a change of location
And does the location refreshes when the devices is outside the accuracy range for example the accuracy is 100 meters does the location cache refresh when the device is outside the 100 meters range of the last know location?
I would highly recommend looking through the documentation for that particular plugin, James Montemagno is a well known and respected developer employed my Microsoft working on the Xamarin framework, so his plugins, extensions and toolkits tend to be pretty highly optimised for use in cross-platform applications.
Looking at the documentation it's clear that trying to get the last 'known' location looks at an internally cached location data set and is not necessarily optimized for near real-time queries. However it can be used to reduce the number of actual location queries you have to do within your app.
The full snippet from the linked documentation is as follows:
public async Task<Position> GetCurrentLocation()
{
public static async Task<Position> GetCurrentPosition()
{
Position position = null;
try
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 100;
position = await locator.GetLastKnownLocationAsync();
if (position != null)
{
//got a cahched position, so let's use it.
return position;
}
if (!locator.IsGeolocationAvailable || !locator.IsGeolocationEnabled)
{
//not available or enabled
return null;
}
position = await locator.GetPositionAsync(TimeSpan.FromSeconds(20), null, true);
}
catch (Exception ex)
{
Debug.WriteLine("Unable to get location: " + ex);
}
if (position == null)
return null;
var output = string.Format("Time: {0} \nLat: {1} \nLong: {2} \nAltitude: {3} \nAltitude Accuracy: {4} \nAccuracy: {5} \nHeading: {6} \nSpeed: {7}",
position.Timestamp, position.Latitude, position.Longitude,
position.Altitude, position.AltitudeAccuracy, position.Accuracy, position.Heading, position.Speed);
Debug.WriteLine(output);
return position;
}
}
This method is designed to follow a hierarchical patter of location retrieval, it starts with the last 'known' position and queries if necessary, you could also take this a step further and add in a timeout to checking for a cached location if you wanted to.
In regards to how often this data is refreshed, I'd refer you to the documentation section titled 'Background Updates'
James talks about a driving app as an example of how this works. The refresh is handled differently across Android and iOS but here's the snippet regarding Android:
For this you will want to integrate a foreground service that
subscribes to location changes and the user interface binds to. Please
read through the Xamarin.Android Services documentation
In the code example he uses he shows you how to create a 'listener' that will check for changes to location periodically. This might be a better fit for what you're trying to do depending on the purpose of your application.

itextsharp 5.4.4 - GetDrawingImage decodes this image the wrong way - why?

This pdf is displayed on my Firefox very well but in a C# program I wrote using itextsharp 5.4.4, I used the GetDrawingImage method of the PdfImageObject and I get a grabled image.
I used itextsharp in the following way:
PdfReader reader = new PdfReader(filename);
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
ImageRenderListener listener = new ImageRenderListener();
parser.ProcessContent(pageNumber, listener);
Where ImageRenderListener is a IRenderListener, which implements the RenderImage method in the following way:
public void RenderImage(ImageRenderInfo renderInfo)
{
PdfImageObject image = renderInfo.GetImage();
PdfObject obj = image.Get(PdfName.FILTER);
PdfName filter = null;
if (obj is PdfName)
{
filter = (PdfName)obj;
}
else if (obj is PdfArray)
{
foreach(var o in (PdfArray)obj)
{
if (o is PdfName)
{
filter = o as PdfName;
break;
}
}
}
if (filter != null)
{
System.Drawing.Image drawingImage = image.GetDrawingImage();
...
...
...
}
The drawing image is stored in the listener and then drawn to the screen etc...
I tried to understand this, I get that the filter is a /CCITTFaxDecode but the streamContentType is somehow a png, could someone enlighten me on this matter?
The reason for this problem is explained in the following video: Ripping your PDF files apart. If you don't want to sit through the complete video, fast forward to minute 24 and watch everything up onto minute 27. Note the conclusion on minute 27: In general, there are no images in PDF. (That's exaggerated, but if you understand the 3 minutes of explanation, you understand what Mark Stephens means.)
If you want the details about why CCITTFaxDecode is changed into PNG, please read chapter 10 of my book.

DataBound controls loading images and avoiding image cache in WP7

I want to load images into a Pivot header to substitute the lack of a Gallery control in WP7. I'm trying to populate them from a URL, and want to make sure that the image is not kept in the cache (by setting UriSource = null) to make sure that they don't take too much resources.
There's no way to do this in the XAML itself, can someone give me sample code to handle this from code-behind. my attempts have been unsuccessful. what am I doing wrong here?
public class PhotoGalleryVM
{
public ObservableCollection<BitmapImage> Images
{
get
{
ObservableCollection<BitmapImage> list = new ObservableCollection<BitmapImage>();
foreach (RoomImage r in App.appData.currentChoices.roomImages)
{
BitmapImage img = new BitmapImage(new Uri(Uri.UnescapeDataString(r.largeUri)));
img.UriSource = null;
list.Add(img);
}
return list;
}
}
}
There is an option that enables to ignore image cache:
bitmapImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
Read more at msdn

How to call webservice methods in Windows Phone 7?

For connecting to webservices i wrote the following code.
WebClient wc = new WebClient();
wc.DownloadStringAsync(new Uri("http://www.Webservices.asmx"));
wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
void wc_DownloadStringCompleted(object sender,DownloadStringCompletedEventArgs e)
{
Debug.WriteLine("Web service says: " + e.Result);
using (var reader = new StringReader(e.Result))
{
String str = reader.ReadToEnd();
}
}
by using above code Get the string result.But i want get the result in HTMLVisulaizer then i know the what are the methods having that webservice.then i can easily access the particular method.
Please tell me how to call a web service method in Windows phone 7?in webservice i am having 5 webmethods.how to get that and how to call the Particular webmenthod.
Please tell me thanks in advance.
#venkateswara Are you talking about obtaining a list of known WebReference methods so you know which one to call in you code? Do you not see the this of known method calls when you add the WebReference to your WP7 project? Since you will be developing the WP7 app in VS I can't see the reason you would want to do this. Even if you don't own the webservice yourself, you will need to connect to it from VS in order to add the reference to your project.
Below is the screen in VS2010 where a WebReference is added. The Operations are listed on the right.
Once added you can use the ObjectBrowser to understand how the methods should be called.
Please let me know if I have missed something from your question.
#Jason James
The first step:
You must add referent Services ,like Jason James has very detailed instructions .
step 2 :
You can open App.xaml.cs , in Functions Apps
public Apps()
{
// Global handler for uncaught exceptions.
UnhandledException += Application_UnhandledException;
// Show graphics profiling information while debugging.
if (System.Diagnostics.Debugger.IsAttached)
{
// Display the current frame rate counters.
Application.Current.Host.Settings.EnableFrameRateCounter = true;
// Show the areas of the app that are being redrawn in each frame.
//Application.Current.Host.Settings.EnableRedrawRegions = true;
// Enable non-production analysis visualization mode,
// which shows areas of a page that are being GPU accelerated with a colored overlay.
//Application.Current.Host.Settings.EnableCacheVisualization = true;
}
// You can declare objects here that you will use
//Examlpe: NameservicesReferent.(Function that returns services) = new NameservicesReferent.(Function that returns services)();
Ws_Function = new Nameservices.ServiceSoapClient();
}
step 3:
in Mainpage.xaml.cs
GlobalVariables.Ws_advertise.getLinkAdvertiseIndexCompleted += new EventHandler<advertise.getLinkAdvertiseIndexCompletedEventArgs>(Ws_advertise_getLinkAdvertiseIndexCompleted);
GlobalVariables.***NameWedservise***.getLinkAdvertiseIndexAsync("**parameters to be passed**");
step 4:
void Ws_advertise_getLinkAdvertiseIndexCompleted(object sender, advertise.getLinkAdvertiseIndexCompletedEventArgs e)
{
//function returns the results to you, the example here is an array
string[] array = null;
try
{
array = e.result;
if(array != null)
}
cath(exception ex)
{
}
finally
{
array = null;
GlobalVariables.Ws_advertise.getLinkAdvertiseIndexCompleted -= new EventHandler<advertise.getLinkAdvertiseIndexCompletedEventArgs>(Ws_advertise_getLinkAdvertiseIndexCompleted);
}
}

How do you save images to a Blackberry device via HttpConnection?

My script fetches xml via httpConnection and saves to persistent store. No problems there.
Then I loop through the saved data to compose a list of image url's to fetch via queue.
Each of these requests calls the httpConnection thread as so
...
public synchronized void run()
{
HttpConnection connection = (HttpConnection)Connector.open("http://www.somedomain.com/image1.jpg");
connection.setRequestMethod("GET");
String contentType = connection.getHeaderField("Content-type");
InputStream responseData = connection.openInputStream();
connection.close();
outputFinal(responseData, contentType);
}
public synchronized void outputFinal(InputStream result, String contentType) throws SAXException, ParserConfigurationException, IOException
{
if(contentType.startsWith("text/"))
{
// bunch of xml save code that works fine
}
else if(contentType.equals("image/png") || contentType.equals("image/jpeg") || contentType.equals("image/gif"))
{
// how to save images here?
}
else
{
//default
}
}
What I can't find any good documentation on is how one would take the response data and save it to an image stored on the device.
Maybe I just overlooked something very obvious. Any help is very appreciated.
Thanks
I tried following this advise and found the same thing I always find when looking up BB specific issues: nothing.
The problem is that every example or post assumes you know everything about the platform.
Here's a simple question: What line of code writes the read output stream to the blackberry device? What path? How do I retrieve it later?
I have this code, which I do not know if it does anything because I don't know where it is supposedly writing to or if that's even what it is doing at all:
** filename is determined on a loop based on the url called.
FileOutputStream fos = null;
try
{
fos = new FileOutputStream( File.FILESYSTEM_PATRIOT, filename );
byte [] buffer = new byte [262144];
int byteRead;
while ((byteRead = result.read (buffer ))!=- 1)
{
fos.write (buffer, 0, byteRead);
}
fos.flush();
fos.close();
}
catch(IOException ieo)
{
}
finally
{
if(fos != null)
{
fos.close();
}
}
The idea is that I have some 600 images pulled from a server. I need to loop the xml and save each image to the device so that when an entity is called, I can pull the associated image - entity_id.png - from the internal storage.
The documentation from RIM does not specify this, nor does it make it easy to begin figuring it out.
This issue does not seem to be addressed on this forum, or others I have searched.
Thanks
You'll need to use the Java FileOutputStream to do the writing. You'll also want to close the connection after reading the data from the InputStream (move outputFinal above your call to close). You can find all kinds of examples regarding FileOutputStream easily.
See here for more. Note that in order to use the FileOutputStream your application must be signed.

Resources