Thursday 24 July 2008

DeepZoom Composer Tag "Generator" MkIII

A comment on a previous post says Because WebClient has a dependency on a web server running, the version I wrote won't be added as a project template into Deep Zoom Composer, which sounds like a shame and got me wondering how to get around the 'WebClient' problem.

The 'WebClient' problem is actually related to security and the sandbox. Kirupa's Tag Sample needs to load Metadata.xml into Silverlight/c#, and it uses WebClient to trigger an asynchronous download...

but you can't do that if you Silverlight control is hosted in a web page off your local disk!

It turned out to be pretty easy to get around - firstly here's a screenshot: the page has simply been double-clicked off the hard-drive, yet it is still able to load *some metadata* to enable tagging & description display.

Ah-ha - so you notice I said "some metadata" and not Metadata.xml. Since it is so hard to 'load' Xml off the filesystem (thanks to the Silverlight sandbox), and since my Tag Generator is parsing and re-writing Metadata.xml anyway, we just write another (JSON) file - Metadata.xml.js then go around the sandbox and load as JSON via Javascript Interop.

It took a little experimenting to get right, but the basic changes to make it work are:

1) Tag Generator emits JSON

2) Tag Generator saves "Metadata.xml.js"

3) Html page references "Metadata.xml.js"

4) Declare 'matching' C#/Silverlight class (to JSON), and a method to Deserialize to it

5) THE MAGIC Javascript Eval turns our string into JSON, replacing the LoadXMLData() at the start of the post

6) Update xmlClient_DownloadStringCompleted to walk the JSON object array instead of Xml, and the rest of the code 'just works'!

You'll want to add a couple of assembly references to your Silverlight (System.Json, System.ServiceModel.Web) and namespaces (System.IO, System.Text, System.Json, System.Runtime.Serializatin.Json) to get everything working. This post on Consum(ing) a JSON object in Silverlight set me on the right track, and the Silverlight and JavaScript Interop Basics filled in the gaps.

The Javascript Interop is capable of much more: HtmlPage.Window.Invoke for going to Javascript, and the [Scriptable*] attributes to expose managed code for Javascript to use; but a simple Eval was all I need for this little experiment.

p.s. I did wonder whether it's possible to "include" an .XML file in the HTML for DOM access... I vaguely remember IE supporting 'XML data islands' or something along those lines. However JSON definitely seems like the 'modern' way to approach the problem IMO, and without getting into x-browser compatibility stuff...

Monday 21 July 2008

OpenSearch [in your browser]

Scott Hanselman blogged today about adding OpenSearch to a website; he made it sound so easy that I had to update and

You can now access both "search" functions direct from your browser, then you can search:

Searcharoo for 'new york'

SilverligthEarth for 'new york'

and of course SilverligthEarth (2.0 beta) for 'new york'

In order to get it to 'look right' I had to rustle up a couple of favicons... I think they look okay for a few minutes work :-)

Sunday 20 July 2008

DeepZoom Composer Tag "Generator"

If you've read the previous two posts, they're about using the new Tag input of Deep Zoom Composer, you'll know that the tags you type in DZC can be used to filter your Deep Zoom Collection like this.

HOWEVER, you probably already add metadata to your photos (using a program like iTag), right?

Rather than RE-type into Composer, the attached project TagUpdater will 'post-parse' your Metadata.xml (after you've finished laying out your photos in DeepZoom Componser) and extract your Title, Description, Keywords (Tags) and Rating, which it will then save back to the XML.

Simply type this:
TagUpdater.exe "C:\...\ClientBin\GeneratedImages\Metadata.xml"

See this:

And it does this:

Then deep zoom away (use this post as a guide).

Note that TagUpdater currently extracts more metadata fields than Silverlight DeepZoom Tag Cloud example displays, but it's trivial to add more (such as the Title and Rating). Further, TagUpdater could be tweaked to extract camera data, GPS location and any other information to be saved in Metadata.xml for use in Silverlight.


Note: I borrowed the jpeg parser from Searcharoo, parts of which were originally written by Asim Goheer and Omar Shahine. It could be updated to use WIC.

Saturday 19 July 2008

DeepZoom Composer Tag "Cloud" Mk II

Adding tags within the latest Deep Zoom Composer is a neat way to navigate DeepZoom 'Collections'.

But if we are going to introduce a new file (Metadata.xml) why not really leverage it?

To that end, I've added a Description element to the Metadata.xml file and typed my own descriptions for each image in my collection. There are two new TextBlocks in the Silverlight control to show the data, and whenever your mouse is over an image, its Tag and Description are displayed. Try it out (beta 2) (or RC0).

The code to match extract the description is a simple extension of the Tag sample.

Then we need to add some code to the MouseMove event to see what SubImage we're over:

which uses SubImageHitTest() from ProjectSilverlight to determine the index of the image to show Tag/Description for.

Finally, you'll notice the 'browse by tag' is now a very basic "cloud". To accomplish that I replaced the ListBox with WrapPanel for Silverlight 2.0 off CodeProject, replaced the items with Buttons and added this ControlTemplate:

The updated files are Page.xaml.cs and Page.xaml.

Wednesday 9 July 2008

DeepZoom Composer Tag "Cloud"

One of the Deep Zoom Composer team recently posted a Filtering by Tag Sample that takes advantage of the new "Tag" input in the latest Deep Zoom Composer release.

Kirupa says specifically "A major limitation in the current version is that if you have multiple tags separated by commas, the application doesn’t break them up and allow you to filter by them.That means, your images can only have one tag associated with them. Don’t worry – I will fix that shortly"...

Turns out you can enable multiple tags with relatively few changes to the example code (and a bit of inspiration from Kosta's Tag Cloud example).

The result looks like this (click to view larger image; notice the tags are scaled according to frequency), or try it here (beta2) (or RC0. The Metadata.xml shows how the source data looks.

The only changes to Kirupa's sample were in the xmlClient_DownloadStringCompleted handler, which is called when the Metadata.xml has been retrieved. To try out the multiple-tag-"cloud" you should follow his instructions to get it running, then update xmlClient_DownloadStringCompleted with this code. Don't forget to seperate your tags with commas or semicolons!

The major changes to enable multiple tags were:

1. split and trim the tag string/s

2. use the uniqueTags Dictionary to store the 'count' of tag occurances

3. loop through all the tags to build a unique list, rather than assume just one is attached to the image

4. 'hardcode' the relative font sizes

There are many areas where this code to be improved - the tag handling is case sensitive (so "monastery" and "Monastery" would be listed seperately), the font size could be calculated (logarithmically?) rather than hardcoded , the tag-list could be more 'cloud like' rather than being hosted in a ListBox and much more. They may be addressed in future posts... or attempted by the reader.