カメラプレビューから直接プレビューフレームを取り出せ無かったWindows Phone OS 7.0では、CameraCaptureTaskを利用してバーコードの読み込みを行いました。詳細については、ZXing Barcode Scanning Libraryを使ってバーコードを読み込む(Windows Phone OS 7.0)をご覧ください。
ここでは、PhotoCameraクラス
を利用してカメラプレビューから映像を取り出しながら、解析を行いリアルタイム取り込みをしてみましょう。今回読み取るバーコードはこれです。
前述した通り、PhotoCameraから取り込んだ映像を矩形PreviewRectangleに表示して、取り込んだ映像をリアルタイムに解析し、バーコードの認識が出来ればリストボックスBarcodeListBoxへ解析結果を追加していきます。
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <!-- この矩形にカメラプレビューを表示する --> <Rectangle x:Name="PreviewRectangle" Margin="0"> <Rectangle.Fill> <VideoBrush x:Name="PreviewBrush" /> </Rectangle.Fill> </Rectangle> <ListBox Name="BarcodeListBox" /> </Grid>
MainPageクラスにPhotoCameraのインスタンス変数を追加しました。
public partial class MainPage : PhoneApplicationPage { // コンストラクター public MainPage() { InitializeComponent(); } PhotoCamera camera = null;
OnNavigatedToにてPhotoCameraクラスのインスタンスを生成します。同時に初期化処理完了のイベントハンドラの設定とPreviewBrushのデータソースとしてcameraを指定します。
// ページがフレームでアクティブになったら呼び出される protected override void OnNavigatedTo(NavigationEventArgs e) { camera = new PhotoCamera(); camera.Initialized += camera_Initialized; PreviewBrush.SetSource(camera); }
カメラの起動と初期化処理が完了すると、camera_Initializedメソッドが実行されます。カメラは大抵横向きに付いていますのでカメラの回転角度に合わせてプレビュー表示を回転させます。
// カメラの初期化処理の完了 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 }; }); }
カメラのプレビュー表示の仕組みはカメラデバイスのレンズから取り込んだ映像をパラパラ漫画のように表示させて、人間の目から見ると滞りなく動いているように見せているアレです。パラパラ映像を切り替える速度の単位をfps(frame per second)といいます。要は1秒間に何枚の画像を表示出来るの?という単位です。
リアルタイムといっても、Windows Phoneに搭載されているカメラの入力フレームレートは約30fps。1秒間に30枚の映像を処理しています。1枚辺り33ミリ秒です。この速度でバーコードの解析は難しいので、1秒間に2回解析を行うようにタイマーを定義します。
// プレビューフレームの解析を行うタイマー DispatcherTimer readTimer = 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 }; }); }
これでカメラ起動は完了です。あとはリアルタイムでプレビューフレームの取り込みを行います。PhotoCamera.GetPreviewBufferArgb32メソッドで、ARGB32フォーマットでプレビュー中に表示されている画像(プレビューフレーム)を取得します。
読み取った結果は、こんな感じになります(画質が悪くて申し訳ない……)。
ライブラリから直接CameraCaptureTask
を起動する事も出来るらしいのですが、うちの環境では上手く動いてくれなかったのでこのような実装になりました。またライブラリ自体もBeta版ですのでそのうち動くようになると思います。