Windows Phoneアプリケーション開発入門

第36回 Mangoで追加されたカメラ機能を使ってみよう!(2)

この記事を読むのに必要な時間:およそ 6 分

静止画撮影シーケンスを開始する

さて,本題の静止画撮影処理を実装していきましょう。先にフラッシュモードと撮影解像度の設定を行います。可能性としては無視できると思いますが,将来端末間で実装に差が出た場合を考え,明確に任意の値を設定するようにしておきましょう。

画像

アプリケーションバーのメニューの「take picture」がタップされると,撮影シーケンス中に発行されるイベントハンドラの設定を行い,PhotoCamera.CaptureImageメソッドにて静止画撮影のシーケンスを開始します。

private void menuItemTakePicture_Click(object sender, EventArgs e) {
    // 静止画撮影可能な解像度を取得する
    var sizes = camera.AvailableResolutions;
    // 撮影可能な解像度のうち一番大きなものを設定
    camera.Resolution = sizes.Last();

    // 撮影シーケンス時に発行されるイベントにハンドラを設定
    camera.CaptureStarted += new EventHandler(camera_CaptureStarted);
    camera.CaptureImageAvailable += new EventHandler<ContentReadyEventArgs>(camera_CaptureImageAvailable);
    camera.CaptureThumbnailAvailable += new EventHandler<ContentReadyEventArgs>(camera_CaptureThumbnailAvailable);
    camera.CaptureCompleted += new EventHandler<CameraOperationCompletedEventArgs>(camera_CaptureCompleted);

    // 静止画撮影の開始要求
    camera.CaptureImage();
}

静止画撮影の要求を投げると,まずCaptureStartedイベントが発行されます。連続撮影しないのであればこの時点でプレビューを止めてしまって良いかもしれません。

// 静止画撮影の開始
void camera_CaptureStarted(object sender, EventArgs e) {
    Debug.WriteLine("camera_CaptureStarted");
}

撮影した画像は最終的にJPEGデータにエンコードされます。PhotoCamera.Resolutionプロパティに指定した大きな解像度の画像のエンコードが完了すると,CaptureImageAvailableイベントが通知されます。

撮影とエンコードが正しくできているかを調べるため,エンコード済みの静止画画像のストリームが引数のContentReadyEventArgs.ImageStreamプロパティから取得できますので,これを分離ストレージへ保存します。

// カメラからの静止画取り込み終了し画像が使用可能になった
void camera_CaptureImageAvailable(object sender, ContentReadyEventArgs e) {
    Debug.WriteLine("camera_CaptureImageAvailable");

    try {
        // 分離ストレージへキャプチャーデータへ保存する
        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
        using (var strm = store.CreateFile("capture_image.jpg")) {
            var bytes = new byte[256 * 1024];
            while (true) {
                int read = e.ImageStream.Read(bytes, 0, bytes.Length);
                if (read <= 0) break;
                strm.Write(bytes, 0, read);
            }
        }
    } catch (Exception ex) {
        // ここでエラー処理
    } finally {
        e.ImageStream.Close();
    }
}

サムネイル画像のJPEGエンコードが完了するとCaptureThumbnailAvailableイベントが通知されます。エンコードの完成したほうが先に通知されます。

サムネイル画像もCaptureImageAvailableイベントの処理と同様に分離ストレージへ保存してしまいましょう。

// カメラからの静止画取り込み終了しサムネイル画像が使用可能になった
void camera_CaptureThumbnailAvailable(object sender, ContentReadyEventArgs e) {
    Debug.WriteLine("camera_CaptureThumbnailAvailable");

    try {
        // 分離ストレージへサムネイルデータへ保存する
        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
        using (var strm = store.CreateFile("thumbnail.jpg")) {
            var bytes = new byte[256 * 1024];
            while (true) {
                int read = e.ImageStream.Read(bytes, 0, bytes.Length);
                if (read <= 0) break;
                strm.Write(bytes, 0, read);
            }
        }
    } catch (Exception ex) {
        // ここでエラー処理
    } finally {
        e.ImageStream.Close();
    }
}

最後にCaptureCompletedイベントが通知されて,静止画撮影シーケンスは完了です。引数のCameraOperationCompletedEventArgsのSucceededプロパティを参照することで,静止画撮影が成功したのか失敗したのかを判定することができます。

// 静止画撮影の完了
void camera_CaptureCompleted(object sender, CameraOperationCompletedEventArgs e) {
    Debug.WriteLine("camera_CaptureCompleted");

    if (e.Succeeded) {
        // 静止画撮影が成功した時の処理
    } else {
        // 静止画撮影が失敗した時の処理 
    }
}

以上,静止画撮影の開始までの設定と静止画撮影シーケンス中に発生するイベントについて説明いたしました。今回のTipsでは,分離ストレージにJPEGデータを保存しました。

著者プロフィール

和田健司(わだけんじ)

1982年10月12日生まれ。大阪で働くプログラマ。Microsoft MVP for Device Application Development(Jul 2010 - Jun 2011)。Windows Mobileに傾倒し今に至る。Windows Mobile向けのTipsを書いています。iPhoneアプリ開発を始めました。嫌いな食べ物はカレー。

URL: http://ch3cooh.jp/
Blog: http://d.hatena.ne.jp/ch3cooh393/