CodeZine(コードジン)

特集ページ一覧

Silverlight 3で強化されたグラフィックとメディア機能

Silverlight 3徹底入門(6)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
目次

WriteableBitmapを利用した画像の操作

 Silverlight 3で追加されたWriteableBitmapクラスを利用すると、Silverlightの要素をキャプチャーしたり、キャプチャーした画像の変換を行ったり、じかにピクセル情報を編集したりする機能を持っています。ここでは、WriteableBitmapクラスを利用していくつかのサンプルを解説したいと思います。

画面のキャプチャーを取り変換を行う

 まずは現在の画面をキャプチャーして画面に表示するサンプルを考えてみましょう。WriteableBitmapはコンストラクターにUIElementとTransformを受け取るオーバーラードがあるので、Silverlightの画面キャプチャーを行う際はこのコンストラクターを利用してWriteableBitmapのインスタンスを作成します。

 [リスト5]のような画面定義のXAMLがあったとして、テキストボックスに表示された内容をボタンクリックのタイミングで画像に変換し、キャンバスに画像を表示するサンプルを考えてみましょう。

[リスト5]UI要素をキャプチャーするプログラムの画面定義(CaptureBitmap.xaml)
<StackPanel x:Name="LayoutRoot">
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="テキストを入力してください" />
        <TextBox Width="150" x:Name="inputText" />
        <Button Content="通常のキャプチャー" Click="NormalCapture_Click" />
        <Button Content="2倍のサイズでキャプチャー" Click="BigCapture_Click" />
    </StackPanel>
    <Canvas x:Name="pictureCanvas" />
</StackPanel>

 キャプチャーボタンがクリックされた時の記述は[リスト6]のようになります。

[リスト6]UI要素をキャプチャーするプログラムのロジック部(CaptureBitmap.xaml.cs)
private void NormalCapture_Click(object sender, RoutedEventArgs e)
{
    pictureCanvas.Children.Clear();
    pictureCanvas.Children.Add(new Image()
    {
        Source = new WriteableBitmap(inputText, null),
    });
}

 この例では、ボタンがクリックされたタイミングで現在のキャンパスの内容をクリアし、WriteableBitmap経由でテキストボックス(inputText)の内容を画像に変換し、キャンパスに再描画しています。

 もし、「取得した画像のサイズを2倍にして表示したい」といった場合は、WritableBitmapのコンストラクターの第2引数にTransformを指定して[リスト7]のように記述します。

[リスト7]UI要素をキャプチャーするプログラムのロジック部その2(CaptureBitmap.xaml.cs)
private void BigCapture_Click(object sender, RoutedEventArgs e)
{
    var tf = new ScaleTransform();
    tf.SetValue(ScaleTransform.ScaleXProperty, 2.0);
    tf.SetValue(ScaleTransform.ScaleYProperty, 2.0);
 
    pictureCanvas.Children.Clear();
    pictureCanvas.Children.Add(new Image()
    {
        Source = new WriteableBitmap(inputText, tf),
    });
}

 図10は2倍のサイズでキャプチャーボタンをクリックしたときの実行結果です。

図10:[リスト6]、[リスト7]の実行結果
図10:[リスト6]、[リスト7]の実行結果

キャプチャーを画像ファイルとして保存する。

 WriteableBitmapでは、UIElementであればMediaElementに表示中の動画や、現在表示されているコンテナそのものなど、どんなものでもキャプチャーすることが可能です。Silvelright 3では画面の印刷を行う際にはJavascriptの印刷機能に頼ることが多いですが、WriteableBitmapを使えば、キャプチャー情報を画像としてクライアントのローカルファイルに保存し、印刷に関しては画像ビューワーなどの外部ツールに任せてしまうといったシナリオも考えられます。

 [リスト8]は表示しているコンテンツを丸ごとキャプチャーして、ビットマップファイルに保存している例です。

[リスト8]キャプチャー結果の保存(SaveBitmap.xaml.cs)
private void Button_Click(object sender, RoutedEventArgs e)
{
    // ファイルの保存ダイアログを表示
    var saveDialog = new SaveFileDialog()
    {
        DefaultExt = ".bmp",
        Filter = "ビットマップ(*.bmp)|*.bmp",
    };

    if (saveDialog.ShowDialog() == true)
    {
        // 現在の画面情報のキャプチャーを取得
        var bitmap = new WriteableBitmap(this, null);

        // 出力ファイルのストリームを取得
        var fileStream = saveDialog.OpenFile();

        // Bitmapファイル形式に変換して保存
        SaveBitmapImage(bitmap, fileStream);
        fileStream.Close();
    }
}

/// <summary>
/// WritableBitmapに読み込んだBitmapをビットマップイメージに保存します。
/// </summary>
/// <remarks>
/// Bitmapのファイル形式はGoogleでの検索結果を参照
/// http://www.google.co.jp/search?rlz=1C1GGLS_jaJP357JP358&aq=f&sourceid=chrome&ie=UTF-8&q=bitmap+%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88
/// </remarks>
private void SaveBitmapImage(WriteableBitmap bitmap, Stream fileStream)
{
    using (var buffer = new BinaryWriter(fileStream))
    {
        //ファイルヘッダー 
        buffer.Write((byte)'B');
        buffer.Write((byte)'M');
        buffer.Write(54 + bitmap.Pixels.Length * 4);
        buffer.Write((short)0);
        buffer.Write((short)0);
        buffer.Write(54);

        // 情報ヘッダー
        buffer.Write(40);
        buffer.Write(bitmap.PixelWidth);
        buffer.Write(-bitmap.PixelHeight);
        buffer.Write((short)1);
        buffer.Write((short)32);
        buffer.Write(new byte[24]);

        // ファイルデータ
        foreach (var px in bitmap.Pixels)
        {
            buffer.Write(px);
        }
    }
}

 分離ストレージ以外のユーザーストレージに画像を保存するためには、SaveFileDialogクラスを使いユーザーに対話的にファイルを選択してもらう必要があります。SaveFileDialogで保存ファイル先のファイルが選択されると、OpenFileメソッドからファイルのストリームを取得できます(図11)。

図11:SaveFileDialogの表示
図11:SaveFileDialogの表示

 WriteableBitmapクラスではキャプチャーした画像のピクセルごとに色情報は保持していますが、そのまま画像ファイルに変換する機能は実装されていません。今回は自作のSaveBitmapImageメソッドを用意し、画像ファイルのフォーマットでデータを書き出しています。

まとめ

 エフェクトとかシェーダーとかいうと拒否反応を起こしそうになる筆者ですが、今回調べていくなかではそれほど低いレイヤーでのプログラムが必要になるということもなく、Silverlight 3で新しく追加になった疑似3Dで画像を変換したり、コントロールにエフェクトを適用したりといった使い方であれば問題なく利用できました。

 3Dやエフェクトと言うと身構えてしまいがちですが、結構簡単に実現できてしまうので、まずは試してみてはどうでしょうか。



  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:Silverlight 3徹底入門

もっと読む

著者プロフィール

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

  • WINGSプロジェクト かるあ (杉山 洋一)(カルア(スギヤマ ヨウイチ))

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5