Geosense For Windows for devs

logo

Now that Rafael Rivera and Long Zheng have launched Geosense For Windows (or you can see Long’s post on it), I can happily brag how MahTweets has supported this since before they started working on it.

Geosense and MahTweets both use the Windows 7 Location and Sensor Platform – Geosense being the provider, MahTweet being the consumer. We supported it in MahTweets to geotag tweets and Flickr photos, in the hope that one day Microsoft or the hardware partners would be kind enough to consider Australia a real country and finally release some relevant hardware to the platform here. So far that hasn’t happened, which is where Geosense steps in.

Geosense with .NET

Geosense by itself doesn’t really do anything terribly exciting to the end user – it’s what Geosense enables for developers that is awesome. Location based services and games are primarily on phones only as it can be a hassle for the user to manually enter their location all the time – now it’s dead easy to bring those services and games to the desktop through rich clients.

To start with, grab the Sensor and Location .NET Interop Sample Library.

Below is an abridged version of the MahTweets GlobalPosition class file (it does some other stuff for other platforms that don’t have the sensor API’s, but that’s just a matter of people manually setting their location).

using Windows7.Location;
public class Location
{
    public String City { get; set; }
    public String Country { get; set; }
    public double Latitude { get; set; }
    public double Longitude { get; set; }
}

public static class GlobalPosition
{
    private static LatLongLocationProvider _provider;
    private static CivicAddressLocationProvider _civicprovider;
    private static bool _loadproviderthrowsexception = false;
    private const uint DEFAULT_REPORT_INTERVAL = 0;

    public static Location GetLocation()
    {
        Location l = new Location();

        try
        {
            if (_loadproviderthrowsexception)
            {
                return null;
            }

            if (_provider == null)
            {
                _provider = new LatLongLocationProvider(DEFAULT_REPORT_INTERVAL);
                _civicprovider = new CivicAddressLocationProvider(DEFAULT_REPORT_INTERVAL);
            }
            var y = _civicprovider.GetReport() as CivicAddressLocationReport;

            l.City = y.City;
            l.Country = y.CountryOrRegion;

            var x = _provider.GetReport() as LatLongLocationReport;
            l.Latitude = x.Latitude;
            l.Longitude = x.Longitude;
            return l;
        }
        catch (Exception ex)
        {
            return null;
        }

    }
}

Easy. The code speaks for itself – create a LocationProvider, query it to get the Latitude/Longitude. The rest is up to you.

Bonus Points

And if you’re a Powershell junkie, the following works too

[Reflection.Assembly]::LoadFile("<absolute location to dll>\Windows7.SensorAndLocation.dll")
$provider = new-object Windows7.Location.LatLongLocationProvider(0)
$position = $provider.GetReport()
$position.Latitude
$position.Longitude

 

WPF Image creating file lock work around

2 December 2008 , ,    3 Comments

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

SetImage("YourImage.jpg");GetNewImage();Image.Source = null;SaveNewImage("YourImage.jpg");SetImage("YourImage.jpg");

 

CodeSnippet: Scanning with WIA & OCR with Office

23 September 2008 , , , ,    2 Comments

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."

(source: Wikipedia)

Lift the image from a physical file into memory

To access WIA in .NET, you’ll need to add a reference to the COM library, "Microsoft Windows Image Acquisition Library v2.0" (wiaaut.dll).

using WIA;

….

const string wiaFormatJPEG = "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}";
CommonDialogClass wiaDiag = new CommonDialogClass();
WIA.ImageFile wiaImage = null;

wiaImage = wiaDiag.ShowAcquireImage(
        WiaDeviceType.UnspecifiedDeviceType,
        WiaImageIntent.GrayscaleIntent,
        WiaImageBias.MaximizeQuality,
        wiaFormatJPEG, true, true, false);
wia_1 

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).

wia_2

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).

WIA.Vector vector = wiaImage.FileData;
Image image = new Image();
image.Source = BitmapFrame.Create(new MemoryStream((byte[])vector.get_BinaryData()));

OCR

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"

install_modi

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.

MODI.Document mDoc = new MODI.Document();
mDoc.Create("temp.jpg");
mDoc.OCR(MODI.MiLANGUAGES.miLANG_SYSDEFAULT, true, true);
MODI.Image mImage = (MODI.Image)mDoc.Images[0];MessageBox.Show(mImage.Layout.Text);

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.


 

Screencast: WPF+SL2 Silverlight Clients

2 August 2008 , , , , ,    1 Comment

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.

Or you can stream the original video in WMV from Silverlight.Live.Com. You can download the solution (73kB) containing the three projects, which requires the Silverlight 2 Beta 2 SDK.

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.


 

WLM Game Status 0.3

wlmgsv03

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.

Install Instructions

  1. Download WLM Game Status from CodePlex
  2. Open up RegEdit.exe
  3. In HKEY_CURRENT_USER\Software\Microsoft\MSNMessenger, set AddInFeatureEnabled to 1
  4. 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)
  5. Install the DLL into the Global Assembly Cache – drag and drop it into C:\Windows\Assembly or from commandline, gacutil -I wgs.addin.dll
  6. Run Windows Live Messenger, Options, Add-ins, Find the DLL, Click ‘Settings’, Detect Games. Close that settings window
  7. Use the drop down where you set your ‘status’, and you should see a "Turn on ‘WGS’". Select that.
  8. Play games!

To Do