酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

CameraCaptureUIやFileOpenPickerで取得したストリームを簡単にWriteableBitampへ変換する拡張メソッド

IRandomAccessStream型のストリームから直接WriteableBitmapオブジェクトを生成することはできません。WriteableBitmapオブジェクトを生成するには幅と高さがあらかじめ知っておく必要があるからです。

BitmapDecoderクラスを使用して、データソースであるJPEGやPNGファイルをBitmapへデコードします。一度デコードしてしまえば、高さと幅、そしてピクセルデータであるbyte配列を得ることができます。

幅(Width)と高さ(Height)が分かっていれば、byte配列型からWriteableBitmapオブジェクトを作成することができますので、ピクセルデータであるWriteableBitmapオブジェクトのPixelBufferプロパティにbyte配列型のデータを書き込んでいきます。IBuffer型であるPixelBufferプロパティに対して書き込みをおこなうには、一度System.IO.Streamオブジェクトへ変換します。

このストリームはWriteableBitampのピクセルデータそのものですので、ストリーム内の位置を先頭に戻し、パラメータで渡されたbyte配列で上書きします。

毎回長いコードを書くのに疲れたので、拡張メソッドを作ってみました。

using System;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime; // for IBuffer.AsStream() Method
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Media.Imaging;

namespace Softbuild.Media
{
    static class WriteableBitmapExtensions
    {
        public static async Task<WriteableBitmap> FromStreamWithContentType(IRandomAccessStreamWithContentType stream)
        {
            // ストリームからピクセルデータを読み込む
            var decoder = await BitmapDecoder.CreateAsync(stream);
            var transform = new BitmapTransform();
            var pixelData = await decoder.GetPixelDataAsync(decoder.BitmapPixelFormat, decoder.BitmapAlphaMode,
                transform, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.ColorManageToSRgb);
            var pixels = pixelData.DetachPixelData();

            // WriteableBitmapへピクセルデータをコピーする
            var bitmap = new WriteableBitmap((int)decoder.OrientedPixelWidth, (int)decoder.OrientedPixelHeight);
            using (var bmpStream = bitmap.PixelBuffer.AsStream())
            {
                bmpStream.Seek(0, SeekOrigin.Begin);
                bmpStream.Write(pixels, 0, (int)bmpStream.Length);
            }
            return bitmap;
        }
    }
}

2012.7.31.追記

WriteableBitmapを作る拡張メソッドなのに、クラス名がBitmapImageExtensionsだったので、WriteableBitmapExtensionsに名前を変更しました。