While working on a new version of TVScout, I’ve been working on adding a management tool which will allow you to choose and fetch from the variety of posters on thetvdb or themoviedb, not just the first poster found. The problem is, I’m displaying the current poster in an (System.Windows.Controls.) Image first. This creates a situation where my program wants to overwrite a resource that’s already in use.The simple fix would be set the Image.Source to null first? Partially right, but the problem is with how you set the file in the first place as there there is still a file lock.
The solution I found was a weird one to say the least. You have to make sure caching is enabled so that WPF will load the image into memory, and release the file lock and then tell it to always ignore the cache. Yes, you read that right.
You have to use the cache and then ignore the cache.
If you don’t ignore the cache, it won’t refresh the image to the new image until the next launch of the application.
private void SetImage(String filename)
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bi.UriSource = new Uri(filename);
bi.EndInit();
image.Source = bi;
}
So you’ll end up with something like this in your code
Scanners are perhaps becoming less and less used as we all move towards a paperless environment with digitals bills and digital photos, but a lot of "official" documentation must always be presented with the original physical copy. The wife and I have a huge collection of such documents which have been horribly archived in several filing cabinets – finding the right document is often a nightmare, let alone using any of the information in them. To combat this, I’ve started on a document manager which (aims to) make it a smooth process from scanning, archiving, searching, tagging, etc all in one.
I thought I’d share the scanning code section, because while scanning wasn’t the easiest thing to dig up, it still wasn’t half as daunting as I thought it would be. Further down you’ll also see code to do optical character recognition (OCR) – that is converting a scanned text document into usable text.
TWAIN or WIA?
In years past, TWAIN (commonly known as Technology Without An Interesting Name) was the way to perform scanning, so that was my starting point on my dig for scanning code. However, I came across a mention of Windows Image Acquisition in my scanners drivers.
"In comparison to TWAIN, WIA is said to be more flexible, because it is a standardized interface that doesn’t require a tight bundling of scanner software and driver (TWAIN-only scanners are often limited to functions that are enabled in its driver-software-bundle). Most recent scanners support WIA."
This isn’t the only way to perform a WIA scan, but it is a very quick and easy way to do it. A standard dialog will appear asking you to select the scanner, and then another dialog will give you a few options (such a previewing, image quality, image mode, which source – by that I mean a document feeder or flatbed depending on your scanners capabilities).
Doing something with the scan
Once the document is scanned in you have to figure out what you want to do with it. If it was a photo for example, simply saving it to JPEG may be suffice, but if it is document you may want to perform OCR to extract the text first.
Saving to JPEG
Saving to JPEG is very easy, wiaImage.SaveFile("temp.jpg");
If you wanted to do more with the JPEG (resize, colour change, filtering, or simply just display in your app) but still wish to treat it as an image, you need to get the image data into either a System.Drawing.Image (WinForms) or System.Windows.Controls.Image (WPF).
OCR is by no means a small task to undertake by yourself, but luckily Office (2003 and up) includes an API named Microsoft Office Document Imaging (MODI) you can program against to let Office process the image for you. Unfortunately, MODI isn’t installed by default with Office 2007 but it is easy enough to add by running the Office setup again, selecting "Add or Remove Features", and then selecting "Scanning, OCR and Indexing Service Filter"
All Office OCR operations must go through the COM library, "Microsoft Office Document Imaging 12.0 Type Library" (that’s for Office 2007) (MDIVWCTL.DLL) so add a reference to it.
The key thing to note is that MODI.Document only accept input files from an string representing the filepath, so you have to save the scanned document to disk (in either JPEG or TIFF) rather than reading from memory.
As far as I can tell, this doesn’t retain any layout data (ie, BlockA of text was situation at X,Y) so it doesn’t appear to be the perfect solution for my document manager but it is free (well, so long as you’ve got Office) so I’ll overlook that for now.
My Demo’s Happen Here entry (entries closed last month) was on Visual Studio 2008, how it can rock your socks by creating Twitter clients in WPF and Silverlight.
For interests sake, the screencast was recorded using Microsoft’s Community Clips Recorder and edited with Windows Movie Maker – both free (well, providing you have Windows). Community Clips Recorder is fairly basic when you compare it against Camtasia, as it has no editing, zooming, or highlighting capabilities. However depending on the situation Camtasia is overly complex and the price difference is something to be considered.
Last year I began creating a Windows Live Messenger plugin which set your status (through DDE) to what game you were playing. Unfortunately development was cut short when I realised it had a really nasty habit of chewing up CPU resources.
However, I’m happy to say I’ve squashed that bug by using a single process handler, rather than one for each game. A rather obvious mistake when you think about it, but truth be told, I haven’t thought about it for months! I’ve also added all the games in the Xfire_Games.ini file, which is somewhere in the thousands! Obviously, I haven’t tested all of these, so they may not all work.
Unfortunately, WLM still requires signed DLL’s/can’t seem to handled unmanaged code wrappers for the plugins so it has limited ability to ‘replace’ XFire for in game chat…a separate program would have to be running/called by the plugin for that to work. My knowledge of DirectX is limited at best, so it may be one of those things that never happens.
In HKEY_CURRENT_USER\Software\Microsoft\MSNMessenger, set AddInFeatureEnabled to 1
Create HKEY_LOCAL_MACHINE\SOFTWARE\Aeoth, add a new String Value called Location. Set the value of ‘Location’ to where you extracted the dll and xml files (ie, D:\wsg0.1)
Install the DLL into the Global Assembly Cache – drag and drop it into C:\Windows\Assembly or from commandline, gacutil -I wgs.addin.dll
Run Windows Live Messenger, Options, Add-ins, Find the DLL, Click ‘Settings’, Detect Games. Close that settings window
Use the drop down where you set your ’status’, and you should see a "Turn on ‘WGS’". Select that.
Play games!
To Do
Easier installer
In game chat (via separate program/relaying messages)
XFire_games.ini import utility/auto-update of database file