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

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

はじめに

Windows Phoneには、アプリケーション内で静止画撮影を行う為の基本的なカメラの機能が提供されています。Windows Phone OS 7.1よりサポートされています。

PhotoCameraクラスには静止画撮影、オートフォーカス、フラッシュモードなどの機能を使用するためのメソッドが含まれています。またそれぞれの処理完了のイベントが用意されています。

また、静止画撮影関係の機能以外にも、プレビュー中のフレーム(画像)をARGB32形式、YCbCr形式、Y成分(輝度情報)のみの形式で取得することが出来ます。

プレビューフレームを用いることで、リアルタイムでカラーエフェクトを掛けながら表示したり、特定のマーカーを探しアニメーションを表示するなどの拡張現実(AR)アプリケーションを開発することが可能になりました。

今回、新規にプロジェクトを作成してカメラプレビューを行う方法を紹介したいと思います。サンプルプロジェクトを用意しましたので、是非ソースコードと一緒に記事を読み進めて頂ければと思います。

カメラプレビューを行う前の準備を行う

ツールバーの[ファイル][新規作成]から[プロジェクト]を選択し、新しいプロジェクトを作成しましょう。Visual C#のテンプレートから「Windows Phone Application」を選択して、新しいプロジェクトを作成します。プロジェクトの名前は「CameraPreviewTest」にしておきます。

次にWindows Phoneプラットフォームのターゲットを選択します。カメラ機能を使用するには、上述した通りWindows Phone OS 7.1以降である必要がありますので、Windows Phone OSのターゲットは「Windows Phone OS 7.1」を選択しましょう。

画像

カメラ機能を使用するためには、Windows Phone Apllication マニュフェストファイルのWMAppManifest.xmlのCapabilities要素に「ID_CAP_ISV_CAMERA」という権限を追加しておく必要があります。

上記手順どおりにプロジェクトを作成した場合は、デフォルトで権限が追加されていると思いますが、カメラ機能が使えなかったりする場合は、下図スクリーンショットを参考にVisual StudioでWMAppManifest.xmlを開いて、Capabilities要素に「ID_CAP_ISV_CAMERA」を追加しておいてください。

画像

ソリューションエクスプローラーからCameraPreviewTestプロジェクトを右クリックし、⁠参照の追加」を選択してください。.NETタブにMicrosoft.XNA.Frameworkがあると思いますので追加を行います。

画像

MainPage.xamlの「LayoutRoot」という名前のGridを以下のコードで置き換えてください。カメラプレビューを表示する為の「PreviewRectangle」という名前の矩形(Rectangle)を追加しています。

矩形を塗りつぶすBrushオブジェクトの一種に、単色で塗りつぶすSolidColorBrushがあります。これと同様に動画で塗りつぶすVideoBrushを使って、カメラデバイスから入力されたプレビューフレームでPreviewRectangleの矩形を塗りつぶします。

<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock x:Name="PageTitle" Text="CameraPreviewTest" 
                   Margin="9,-7,0,0" 
                   Style="{StaticResource PhoneTextTitle2Style}"/>
    </StackPanel>

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <!-- この矩形にカメラプレビューを表示する -->
        <Rectangle x:Name="PreviewRectangle">
            <Rectangle.Fill>
                <VideoBrush x:Name="PreviewBrush" />
            </Rectangle.Fill>
        </Rectangle>
    </Grid>
</Grid>

カメラプレビューを開始する

カメラプレビューを表示させるだけであれば、生成したPhotoCameraオブジェクトをカメラにVideoBrushのソースをPhotoCamera.SetSourceメソッドで設定するだけです。

protected override void OnNavigatedTo(NavigationEventArgs e) {
    camera = new PhotoCamera();
    PreviewBrush.SetSource(camera);
}

端末にはカメラデバイスが搭載されていますが、大抵の場合カメラデバイスは端末に対して横向きに搭載されているので、表示の際に回転させる必要があります。

カメラの初期化が完了すると、Initializedイベントが発行されます。カメラの初期化処理完了後にcamera_Initializedメソッドでブラシへ回転処理を適用します。

using System;
using System.Windows.Navigation;
using System.Windows.Media;
using Microsoft.Phone.Controls;
using Microsoft.Devices;

namespace CameraPreviewTest {
    public partial class MainPage : PhoneApplicationPage {

        // コンストラクター
        public MainPage() {
            InitializeComponent();
        }

        PhotoCamera camera = null;

        // ページがフレームでアクティブになったら呼び出される
        protected override void OnNavigatedTo(NavigationEventArgs e) {
            camera = new PhotoCamera();
            camera.Initialized += camera_Initialized;
            PreviewBrush.SetSource(camera);
        }

        // ページがフレームでアクティブでなくなったら呼び出される
        protected override void OnNavigatedFrom(NavigationEventArgs e) {
            if (camera != null) {
                camera.Dispose();
                camera = null;
            }
        }

        // カメラの初期化処理の完了
        void  camera_Initialized(object sender, CameraOperationCompletedEventArgs e) {
            // 初期化処理に失敗した場合は何もしない
            if (!e.Succeeded)
                return;

            // カメラの回転角度に合わせてプレビュー表示も回転させる
            Dispatcher.BeginInvoke(() => {
                PreviewBrush.RelativeTransform = new CompositeTransform() {
                    CenterX = 0.5, CenterY = 0.5,
                    Rotation = camera.Orientation
                };
            });
        }
    }
}

アプリケーションを起動し、ページがフレームでアクティブになったらOnNavigatedToメソッドが呼び出されます。このメソッドにてカメラに対してVideoBrushのソースを設定しているので、カメラプレビューが開始されます。

画像

オートフォーカスを開始する

カメラはピントが合っていないとボケた映像になります。ピントを合わせて綺麗にプレビューさせたり静止画撮影を行う為にはフォーカスを調整する必要があります。PhotoCameraクラスには、Focusという自動でピントを合わせるメソッドがあります。

// オートフォーカス処理を開始する
camera.Focus();

Windows Phoneの標準のカメラアプリケーションでは、プレビュー画面をタップするとオートフォーカスを行います。サンプルプロジェクトの方でも同じ様に実装してみましょう。カメラプレビューを表示している矩形のPreviewRectangleがタップされるのをトリガーにして、PhotoCamera.Focusメソッドを呼び出します。

MainPage.xamlで配置しているPreviewRectangleにTapイベントのハンドラを追加してください。

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <!-- この矩形にカメラプレビューを表示する -->
    <Rectangle x:Name="PreviewRectangle" Tap="PreviewRectangle_Tap">
        <Rectangle.Fill>
            <VideoBrush x:Name="PreviewBrush" />
        </Rectangle.Fill>
    </Rectangle>
</Grid>

AutoFocusCompletedイベントのハンドラを設定して、PhotoCamera.Focusメソッドを使います。フォーカス調整が完了するとcamera_AutoFocusCompletedメソッドが呼ばれます。

// 表示領域がタップされるとオートフォーカス処理を開始する
private void PreviewRectangle_Tap(object sender, System.Windows.Input.GestureEventArgs e) {
    if (camera == null) {
        return;
    }

    System.Diagnostics.Debug.WriteLine("AutoFocus Start: " + DateTime.Now.ToString("HH:mm:ss.fff"));
    camera.AutoFocusCompleted += camera_AutoFocusCompleted;
    // オートフォーカス処理を開始する
    camera.Focus();
}

// オートフォーカスの完了
void camera_AutoFocusCompleted(object sender, CameraOperationCompletedEventArgs e) {
    camera.AutoFocusCompleted -= camera_AutoFocusCompleted;
    System.Diagnostics.Debug.WriteLine("AutoFocus End  : " + DateTime.Now.ToString("HH:mm:ss.fff"));
}

実機にサンプルアプリケーションをデプロイしてみました。アプリケーションが起動するとプレビューが始まりますので、画面をタップしオートフォーカス処理を行い、ピントを合わせました。

画像

オートフォーカスを中止する

前述のオートフォーカス処理は少し時間が掛かってしまいます。実機(HTC Mozart)上で、オートフォーカスの開始から終了まで約2秒ほど掛かりました。

おそらく端末によって処理に掛かる時間の加減はありますが、少し時間の掛かる処理であることは間違いありません。処理中にオートフォーカスを中止するには、PhotoCamera.CancelFocusメソッドを使用します。

// オートフォーカス処理を中止する
camera.CancelFocus();

さいごに

カメラプレビューとオートフォーカスの使い方をご紹介させて頂きました。次回はカメラを使っての静止画撮影とフラッシュモードの使い方についてご紹介させて頂きたいと思います。

おすすめ記事

記事・ニュース一覧