Silverlight 2:Deep Zoomのサンプル


※2010/7/22 画像のリンク切れ修正、サンプルコード、解説を一部追加しました。
DeepZoomComposer バージョン1.0.000.1 ダウンロード

Silverlight 2で注目のDeep Zoom。
Deep Zoomは非常に大きな画像もスムーズに拡大・縮小できる技術です。

Deep Zoom Composer(こちらからダウンロード)というツールを使えば、とても簡単に作成できてしまいます。
Deep Zoom Composerの現時点での最新版は ver.0.9.000.6 (2009/2/17リリース)です。

Deep Zoom のサンプルをご覧下さい。
このサンプルでは、Deep Zoom Composerが生成したDeep Zoomに少し手を加えて、個々の画像に付けた
タグでフィルタリングするようにしています。


【タグでフィルタリングするDeep Zoom サンプル】
(※Silverlightランタイムが必要です。ダウンロードはこちら。)

[silverlight: deepzoom/sample1/DeepZoomProject.xap]

右側のTag List は、Deep Zoomで表示されている画像に付けられている全てのタグです。
リストからタグを選択すると、そのタグが付けられた画像だけ表示されます。

■ Deep Zoom Composerで画像にタグを付ける

1.「Import」→「Add Image」ボタンから画像を選択します。

2.「Compose」を選択、画像を配置します。
画像を複数選択して右クリック → 「Arrange into Grid」を選択すると自動的に配置してくれます。

3.画像にタグを付けます。
右のタブ「Layers」から画像を選択し、「Tag」の入力欄に指定したいタグを入力します。
タグを複数付ける場合は、カンマで区切って入力します。

4.「Export」を選択、DeepZoomデータを出力します。
『Image Settings』の「Export as a collection(multiple images)」を選択して出力すると
Deep Zoomの画像データと共に、タグ情報を含む個々の画像情報が記述されたMetadata.xmlが生成されます。
(xapファイルと同じ場所のGeneratedImagesフォルダの下)

出力されたMetadata.xmlの中身です。
サンプルでは、このMetadata.xmlを読み込み、<Tag/>を取得しています。

【Metadata.xml】

<?xml version=”1.0″?>
<Metadata version=”1″>
<AspectRatio>1.44486696718583</AspectRatio>
<Image>
<FileName>画像ファイルパス…</FileName>
<x>0.687499999999999</x>
<y>0.696907222871069</y>
<Width>0.312500000000001</Width>
<Height>0.302257810800755</Height>
<ZOrder>3</ZOrder>
<Tag>flower,rose</Tag>
</Image>

Deep Zoom Composerを使うと、クリック時にズームをするなどの基本的な操作はあらかじめ用意された状態で
Deep Zoomプロジェクトを生成してくれます。
xamlの中でDeepZoomを表示するにはMultiScaleImageコントロールを使い、SourceプロパティにDeepZoomCompserが出力したdzc_output.xmlを指定します。

<MultiScaleImage x:Name=”msi” Source=”/GeneratedImages/dzc_output.xml” />

※2010/7/22 追加
DeepZoomComposerでせっかくつけたタグですが、そのままではDeepZoom内で利用することができません。

MultiScaleImage.SubImagesプロパティから、MultiScaleSubImageのコレクションを取得することができます。
このMultiScaleImageが個々の画像に対応しています。
このMultiScaleImageと、Metadata.xml内に定義されているタグを紐付ける作業をしなければなりません。
MultiScaleSubImage.ZIndexプロパティと、Metadata.xml の<ZOrder>が一致するものを紐付けます。

1.タグ情報を含むMultiScaleImageのラッパークラスを作っておきます。

public class DZImage

{
  public List<string> TagList { get; set; } //複数のタグを持てるようにリストでタグを保持します。
  public MultiScaleSubImage SubImage { get; set; }
}

2.全てのDZImageを格納するリストを用意しておきます。

private List dzImageList;

3.Metadata.xmlを読み込みます。ここではLINQ to XMLを使います。

XDocument metadataXML = XDocument.Load(“Metadata.xml”);
XElement element = metadataXML.Element(“Metadata”);
var imgs = from i in element.Descendants(“Image”)
            select i;

foreach(XElement img in imgs)
{
  //タグを取得します。
  string tagString = img.Element(“Tag”).Value;

  //タグが複数ある場合はカンマで分割し、配列へ格納します。
  string[] separator = {“,”,”, “};
  string[] tags = tagString.Split(separator, StringSplitOptions.RemoveEmptyEntries);

  //DZImageを生成します。
  //Metadata.xmlの<ZOrder>を取得します。
  int zOrder = int.Parse(img.Element(“ZOrder”).Value);

  DZImage dzImage = new DZImage()
  {
    TagList = tags.ToList(),
    SubImage = msi.SubImages[zOrder-1]
  };

  dzImageList.Add(dzImage);
}

これで、DeepZoom画像とタグが紐付けは終わりです。
省略しましたが、上のコードの foreach(XElement img in imgs){…} の中で
サンプルの右側にあるタグのListBoxを作るために、タグのリスト(重複するものは省く)を作成しています。

タグListBoxからどれかのタグが選択されると、ListBoxのSelectionChangedイベントを受けて
選択されたタグが付けられた画像だけ表示するようにフィルタリングします。
フィルタリング用のメソッドです。

private void FilteringImages(string filterTag)
{
  filteredSubImageList = new List();//表示する画像を入れるリスト

  foreach (DZImage dzImg in dzImageList)
  {
    if (dzImg.TagList.Contains(filterTag))
    {
      filteredSubImageList.Add(dzImg.SubImage);
      dzImg.SubImage.Opacity = 1;
    }
    else
    {
        dzImg.SubImage.Opacity = 0;
    }
  }
}

タグが含まれる画像のOpacityは1、含まれない画像は0で表示・非表示を設定します。
後は、必要に応じて表示する画像を並び替えるなどの処理を加えます。

DeepZoomComposerはメタデータを生成してくれますが、画像との紐付けのひと手間は必要
ということで、簡単な説明ですがご参考になればと思います。