kazuakix の日記

Windows Phone とか好きです

Windows Phone 8.1 でサムネイル画像を作成する

画面に大量の画像を表示する場合、大きな画像を表示だけ縮小して表示するのではなく あらかじめ縮小した画像を表示する方が効率的です。(当たり前ですが)

そして WinRT にはサムネイルを作るための API が用意されています。

日本語ドキュメントには「Windows Phone 8 には実装されていません」と書かれているのですが、英語ドキュメント(Windows Phone 8.1) を見ると Phone でも対応している事がわかります。言ってる間に翻訳も追いついて来ると思いますが注意が必要ですね。
 
さて、この GetThumbnailAsync ですが、StorageFile のメソッドになっています。当然ですが画像はいったん普通に取得する必要があります。

画像の読み込み

前準備として画像を読み込んで、テンポラリ領域に保存しておきます。

public async Task GetImage(string imageUri)
{
    var uri      = new Uri(imageUri);
    var fileName = Path.GetFileName(uri.LocalPath);
    var cache    = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);

    // ローカルに保存
    using (var req = new HttpClient())
    using (var res = await req.GetAsync(imageUri))
    { 
        if (res.IsSuccessStatusCode)
        {
            using (var src = await res.Content.ReadAsStreamAsync())
            {
                using (var dst = await cache.OpenStreamForWriteAsync())
                {
                    await src.CopyToAsync(dst);
                }
            }

 
これを普通に表示させる場合、

            using (var src = await cache.OpenReadAsync())
            {
                this.ImageSize = string.Format("Size : {0:#,##0} KB", src.Size / 1024);

                this.PreviewImage = new BitmapImage();
                this.PreviewImage.SetSource(src);
            }

ImageSize, PreviewImage はこんな感じで画面上のコントロールにバインディングされていると思ってください。

<Image Source="{Binding PreviewImage}"/>
<TextBlock Text="{Binding ImageSize}" />

f:id:kazuakix:20140913000739j:plain,w360

綺麗に表示されていますね。
 

サムネイル画像を作成する

サムネイル画像を作成する場合は、上記の OpenReadAsync の部分を GetThumbnailAsync に置き換えてやるだけです。

using (var thumbnail = await cache.GetThumbnailAsync(ThumbnailMode.SingleItem))
{
    this.ImageSize = string.Format("Size : {0:#,##0} KB", thumbnail.Size / 1024);

    this.PreviewImage = new BitmapImage();
    this.PreviewImage.SetSource(thumbnail);
}

f:id:kazuakix:20140913000725j:plain,w360

若干 画像が荒くなっていますが、サイズは大幅に小さくなっていますね。
 
尚、画面上のサイズがわかっている場合は GetThumbnailAsync にサイズを指定することである程度品質を調整することもできます。

using (var thumbnail = await cache.GetThumbnailAsync(ThumbnailMode.SingleItem, 360))
{
    // 同じ
}

f:id:kazuakix:20140913000708j:plain,w360

試しに 360 というサイズを与えてみることで 若干画質(とサイズ)が上がりました。