The Windows Phone 7 camera gives you the option to record the location where a picture was taken (under Settings => applications => pictures+camera). With this feature turned on, each application has their latitude, longitude and altitude stored as part of the standard EXIF data. I thought it would be fun to combine the previous blog post I wrote on pushpin clustering with the photos on my camera, to allow me to explore them via a Bing Maps control. With not much more than 100 lines of code I came up with an application which I think is a lot of fun to use.
Here are all the photos on my phone, note the way the pushpins are clustered.
Here are some pictures around Europe, including one of Gergely Orosz waiting for his turn in the Edinburgh Marathon Relay.
And finally, some pictures I took whilst running around Kielder Water during Kielder marathon.
Accessing the EXIF data
You can access the photos on a WP7 device via the XNA MediaLibrary class. The interface that this class provides gives you access to Picture instances which have properties that allow you to access the width / height and a few other basic attributes. They also have methods that return streams which can be used to read the thumbnail and image data, however, they do not expose the picture location. This is 'hidden' within the EXIF data.
With this library, accessing the EXIF data is a one-liner:
The JpegInfo class exposes the raw EXIF geolocation data, which is detailed in the EXIF specification as being expressed as separate components of degrees, minutes and seconds together with a reference direction (North / South, East / West). We can convert from the sexagesimal numeric system used in EXIF, to the decimal system as follows:
Analysing the images
When the application starts a BackgroundWorker is used to read the EXIF data for all of the pictures in the phone's media library, with those that have geolocation data available being stored in a separate list:
The template used for the pushpins simply renders the image thumbnail:
This makes use of a simple value converter which takes a Picture instance and converts it into a BitmapImage which is used as the Source for the image:
The puhspin clusterer allows you to specify a separate template for clustered pushpins. The DataContext for this template is a list of the DataContexts of the clustered pins that it represents. For this application I created a template which renders what looks like a 'stack' of images. The number of pictures in the cluster is rendered as a TextBlock and the last image in the cluster rendered.
The code that renders the last image is a bit cunning, it uses a value converter that performs a Linq style 'last' operations, extracting the last items from a collection of objects:
This feels quite neat to me :-)
The clustered pins look like the following, which is a cluster of 5 images around Paris, with the stunning La Grande Arche de la Défense as the image at the top of the cluster:
Despite its simplicity, I have had a lot of fun playing with this application. It has certainly encouraged me to take as many photos as possible whenever I go travelling.