はじめに
先日、世界初となるWindows Phone 7.5端末のIS12Tが発売されました。現時点(2011年9月12日)ではWindows Phone 7.5が搭載された端末はこの1台だけです。
IS12Tには、13.2Mの高画質カメラが搭載されています。前回 カメラプレビューの表示に使ったプロジェクトを拡張して、フラッシュモードの設定、撮影解像度の取得と設定、静止画撮影を行うまでをご紹介させていただきます。
前回から機能を追加したサンプルプロジェクトを用意しましたので、是非ソースコードと一緒に記事を読み進めて頂ければと思います。
フラッシュモードを設定する
静止画撮影を行う上で必要なフラッシュモードの設定と撮影解像度の設定についてご紹介したいと思います。
標準カメラはデフォルトで、被写体の周りが暗い場合にカメラ撮影時にフラッシュを炊く設定になっています。フラッシュを発光させるかどうかの設定値はenumで定義されています。
Windows Phone OS 7.1で定義されているフラッシュモードは下記の通りです。
フラッシュモード
説明
FlashMode.On
フラッシュは常にON
FlashMode.Auto
自動発光モード
FlashMode.Off
フラッシュは常にOFF
FlashMode.RedEyeReduction
赤目補正モード
フラッシュモードがFlashMode.On、FlashMode.RedEyeReductionの場合、必ずフラッシュが発光します。FlashMode.Autoの場合にWindows Phone OSがフラッシュをさせるかどうかを判定し、必要であればカメラ撮影時にフラッシュが発光します。
FlashMode.Offの場合フラッシュは発光しません。
フラッシュモードを設定する
上記の表の通り、定義としてはフラッシュモードが4つありますが、それぞれのWindows Phone端末でハードウェア的にサポートしていない可能性があります。
そこでまずPhotoCamera.IsFlashModeSupportedメソッドを使用して、現在のカメラでそのフラッシュモードが使用できるのかを判定し、使用可能であればフラッシュモードの設定を変更するようにします。
if ( camera . IsFlashModeSupported ( FlashMode . RedEyeReduction )) {
camera . FlashMode = FlashMode . RedEyeReduction ;
}
余談ですが、カメラのフラッシュを懐中電灯代わりに使用しているアプリケーションが公開されているのをMarketplaceにて発見しました。VideoSourceを設定せずプレビューを非表示の状態でフラッシュモードを常にONに設定することで実現しているようです。
camera . FlashMode = FlashMode . On ;
フラッシュは静止画撮影時に一瞬発光させるものであるため、発光パーツの消耗や消費電力的にフラッシュを付けっぱなしにするのはあまりおススメできませんが、面白いアイディアですね。
静止画撮影を行う
静止画撮影を行うトリガーとしてApplicationBarに下図のように撮影用のメニューアイテムを追加しました。
MainPage.xamlのApplicationBar.MenuItemsにApplicationBarMenuItemを追加しています。追加したメニューアイテムには、静止画撮影のトリガーとなるClickイベントのハンドラを設定しています。
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible = "True"
IsMenuEnabled = "True" Mode = "Minimized" >
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem
x:Name = "menuItemTakePicture"
Text = "Take Picture"
Click = "menuItemTakePicture_Click" />
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
ここでトリガーとして用意したmenuItemTakePicture_Clickメソッドがコールされた時、静止画撮影を行うように実装してみましょう。
静止画撮影の解像度の設定
Windows Phone OSを搭載するためのハードウェア要件として、5Mピクセル以上のカメラを搭載しなければいけないことになっています。
私の持っているHTC Mozartは最大8Mピクセルまでしか撮影できませんが、IS12Tは13Mピクセルまで撮影することが可能です。機種によって搭載されているカメラセンサーは異なり、当然撮影可能な解像度も違ってきます。
実行中のWindows Phone端末で撮影可能な解像度を得るためには、PhotoCamera.AvailableResolutionsプロパティからSizeの配列を取得します。
var sizes = camera . AvailableResolutions ;
camera . Resolution = sizes . Last ();
デバッグ実行中のスクリーンショットを取りました。下図の通り解像度が取得できているのが確認できます。
Windows Phoneエミュレータでの撮影可能な解像度を取得したところです。取得できた解像度は、640×360、640×480(VGA) 、2592×1944(5M) 、3264×2448(8M)の4つ。通常Windows Phoneの標準カメラアプリでは存在しない撮影サイズが含まれていることに注目してください。
静止画撮影シーケンスを開始する
さて、本題の静止画撮影処理を実装していきましょう。先にフラッシュモードと撮影解像度の設定を行います。可能性としては無視できると思いますが、将来端末間で実装に差が出た場合を考え、明確に任意の値を設定するようにしておきましょう。
アプリケーションバーのメニューの「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データを保存しました。
Isolated Storage Explorer Toolの使い方
Windows Phoneの分離ストレージはセキュアな反面、格納したデータをPC側のエクスプローラー等のファイルシステムからアクセスすることができず、開発効率が落ちてしまう原因となっていました。
Windows Phone SDK 7.1から分離ストレージに対してアクセスする方法として「Isolated Storage Explorer Tool」というツールが追加されました。コマンドラインベースであまり使いやすいとは言えませんが、今まで分離ストレージにアクセスできなかったことを考えると、格段にデバッグ効率が上がったと言えます。
このツールが追加されたのはWindows Phone SDK 7.1からですが、対象となるアプリケーションはWindows Phone OS 7.0向けのものでも問題ありません。
Isolated Storage Explorer Toolでできることは以下の3つです。
Windows Phone内の分離ストレージからPCへデータを転送
PCからデータをWindows Phone内の分離ストレージへ転送
Windows Phone内の分離ストレージのディレクトリの一覧表示
Isolated Storage Explorer Toolのコマンドのパラメータ
開発環境であるWindowsが32bit版か64bit版かで、インストールされているディレクトリが異なります。自分の環境に合ったものを選択してください。
Windowsが32bit版の場合
"C:\Program Files\Microsoft SDKs\Windows Phone\v7.1\Tools\IsolatedStorageExplorerTool\ISETool.exe"
Windowsが64bit版の場合
"C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.1\Tools\IsolatedStorageExplorerTool\ISETool.exe"
ISETool.exeに指定する書式は以下の通りです。
ISETool.exe <ts|rs|dir[:device-folder ]> <xd|de> <Product GUID > [<desktop-path >]
コマンドの引数を前から順に説明していきます。
パラメータ
説明
ts
(Take snapshot) Windows Phone内の分離ストレージからPCへデータを転送
rs
(Restore snapshot) PCからデータをWindows Phone内の分離ストレージへ転送
dir
Windows Phone内の分離ストレージのディレクトリの一覧表示 特定のディレクトリの一覧をみたい場合は「dir:"/Shared"」のように指定する。ディレクトリを指定しなかった場合はルートディレクトリの一覧が表示される。
xd
Windows Phoneエミュレータを対象とする
de
Windows Phone端末(実機)を対象とする
Product GUID
データをダンプしたい対象となるアプリのWPAppManifest.xmlに書かれているProduct GUID
desktop-path
PC側の転送先または転送元パス
これらのパラメータを使いわけることで、最初に紹介した3つの機能別にISETool.exeを使い分けることができます。Visual Studioのソリューションエクスプローラーから、テストを行いたいプロジェクトのPropertiesディレクトリにあるWMAppManifest.xmlを開いてください。
App要素にProductID属性がありますのでメモしておいてください。例として使用しているCameraPreviewTestのプロダクトIDは「d529745c-470a-4fc0-aab0-50b76d24bfe3」で、このIDを使用して、分離ストレージからのデータの取り込みやデータの格納を行います。
Windows Phone内の分離ストレージからPCへデータを転送
プロダクトIDが「d529745c-470a-4fc0-aab0-50b76d24bfe3」のアプリケーションの分離ストレージの内容を、Windows Phone端末(実機)からPCの「c:\test」ディレクトリへ転送しています。
> ISETool.exe ts de d529745c-470a-4fc0-aab0-50b76d24bfe3 c:\test
コマンドを実行し、問題なく終了するとDownload Successfulと表示されます。特に進捗が表示されることも無いので、サイズの大きなファイルを転送している場合は、コマンドプロント上でのフィードバックがありませんので注意してください。
> ISETool.exe ts de d529745c-470a-4fc0-aab0-50b76d24bfe3 c:\test
Download Started ... Into Folder: c:\test
Download Successful Into Folder: c:\test
PCからデータをWindows Phone内の分離ストレージへ転送
プロダクトIDが「d529745c-470a-4fc0-aab0-50b76d24bfe3」のアプリケーションの分離ストレージに対して、PCの「c:\test」ディレクトリのデータをWindows Phone端末(実機)へ転送しています。
> ISETool.exe ts de d529745c-470a-4fc0-aab0-50b76d24bfe3 c:\test
Windows Phone内の分離ストレージのディレクトリの一覧表示
プロダクトIDが「d529745c-470a-4fc0-aab0-50b76d24bfe3」のアプリケーションの分離ストレージのルートディレクトリ一覧を参照します。
> ISETool.exe ts dir d529745c-470a-4fc0-aab0-50b76d24bfe3
dirに続いて「:device-folder 」を指定すると特定のディレクトリ一覧を参照することが可能です。
以下の例では、プロダクトIDが「d529745c-470a-4fc0-aab0-50b76d24bfe3」のアプリケーションの分離ストレージのルート直下のSharedディレクトリ一覧を参照しています。
> ISETool.exe dir:"/Shared" de d529745c-470a-4fc0-aab0-50b76d24bfe3
<DIR> Transfers
<DIR> ShellContent
<DIR> Media
撮影した画像がきちんと撮れているかを確認するために分離ストレージに保存されたデータを確認してみましょう。Isolated Storage Explorer Toolを使って、分離ストレージに保存したJPEGデータをPCへ転送してみました。
問題なくPCへ転送が行われ、エクスプローラーで表示できていることを確認できました。
さいごに
プレビュー表示に使用する画像のことを、プレビューフレームやプレビューバッファーと呼びます。
次回は、プレビューフレームを取得し、カメラからインプットを表示させるだけではなく、画像を加工した上でプレビュー表示を行うTipsと、バーコードライブラリを使用してバーコードの読み取りを行う方法をご紹介したいと思います。
今回は以上で終わりです。ありがとうございました。