Wednesday, 28 May 2008

Thursday, 15 May 2008

Whither Geoquery?

If you were reading this blog earlier in the year, you may have seen these posts on Geoquery for SQL Server 2008.

Since my last post (in March) a few things have happened to stall development:
1) Running. I was injured over summer (that's Dec-Feb down here) and couldn't train - all that extra free time went into developing Geoquery. Now I'm back in training.
2) Holidays. Spent a few weeks in Thailand and Bhutan.
3) Job. It's busier now.
4) I was using the demo version Visual Studio 2008. It's expired. The Express versions just don't cut it for "real" work.
5) I can't help thinking Microsoft is going to release something similar themselves. It was great fun building it up to v0.72, but now real hard work is required to get the functionality "to the next level". That's a lot of effort for "nothing", less fun and more sweat.

I saw today that Google Maps now has a Flash API (and demos), something Yahoo has had for a while. I might get back to playing with silverlightearth.com and deepzoompublisher.com in Silverlight 2.0.

There may yet be a way to tie them all together: converting silverlightearth.com to Silverlight 2.0 will result in a whole pile of C# and Xaml that would then plug right into Geoquery 2008. Will see how things develop... ;-)

DeepZoom "Publisher" with Xps (part 1)

Further to this post about turning a PDF document into a Silverlight 2.0 DeepZoom image, here is some code to parse an XPS document into individual PNG images which can then be turned into DeepZoom content. It's slightly updated from this MSDN forum post: How to convert xps documents to other formats, for example bmp.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Documents;
using System.Windows.Xps.Packaging;
using System.Windows.Media.Imaging;
using System.Windows.Media;
// class definition...
static public void SaveXpsToPng(string xpsFileName)
{
XpsDocument xpsDoc = new XpsDocument(xpsFileName, System.IO.FileAccess.Read);
FixedDocumentSequence docSeq = xpsDoc.GetFixedDocumentSequence();
Dictionary<string, string> docPageText = new Dictionary<string, string>();
string txtPage;

for (int pageNum = 0; pageNum < docSeq.DocumentPaginator.PageCount; pageNum++)
{
DocumentPage docPage = docSeq.DocumentPaginator.GetPage(pageNum);
txtPage = string.Empty;

foreach (System.Windows.UIElement uie in ((FixedPage)docPage.Visual).Children)
{
if (uie is System.Windows.Documents.Glyphs)
{
txtPage += ((System.Windows.Documents.Glyphs)uie).UnicodeString;
}
}

BitmapImage bitmap = new BitmapImage();
RenderTargetBitmap renderTarget =
new RenderTargetBitmap((int)(docPage.Size.Width * 300/96),
(int)(docPage.Size.Height * 300/96),
300,
300,
PixelFormats.Pbgra32);
renderTarget.Render(docPage.Visual);

BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderTarget));
string filename = xpsFileName + ".Page" + pageNum;
FileStream pageOutStream = new FileStream(filename+".png", FileMode.Create, FileAccess.Write);
encoder.Save(pageOutStream);
pageOutStream.Close();
// oh, and save the text too
System.IO.File.WriteAllText(filename + ".txt", txtPage);
}
}

The output files look like this. Two things to note:
1) the PNGs are between 1 and 3Mb in size (around 300dpi I think)
2) there is a .txt file for each image (look carefully in the code above).



Here is one of the images and its associated .txt file



Why output a text file you ask? For indexing and searching! It's debateable whether it makes sense to use DeepZoom as a mechanism for published 'documents' when you can use PDF or the Silverlight 2 XPS Viewer, however for graphically heavy content (say... magazines, photo books) a searchable, indexable DeepZoom collection could actually be a better user experience (particularly for browsing).

Anyway, this is only half the solution - we've got images and text OUT of the Xps document with that code, but we haven't yet processed them IN to DeepZoom via the DeepZoom Composer (Seadragon/Mermaid)... stay tuned...