BREW でカメラ (後編) - 2 / 3 -
追加するマクロと変数
カメラの状態を表すマクロ定数を定義します。スナップショットは 2 つのマクロ定数を定義しています。カメラが停止したときと、スナップショット モードでの撮影が完了したときを区別するのに必要となるからです。
// ICAMERA インターフェース未初期化 #define CAMERA_STATUS_NULL 0 // ICAMERA インターフェース取得済み #define CAMERA_STATUS_READY 1 // プレビュー モード #define CAMERA_STATUS_PREVIEW 2 // スナップショット モードへ移行開始 #define CAMERA_STATUS_BEGIN_SNAPSHOT 3 // スナップショット モード (完了) #define CAMERA_STATUS_SNAPSHOT 4 // カメラ終了処理開始 #define CAMERA_STATUS_BEGIN_STOP 5 // カメラ解放開始 #define CAMERA_STATUS_BEGIN_FREE 6
マクロ定数とメディア データを格納する変数をアプレット構造体に追加します。
typedef struc _camera_app { ... // add your own variables here... ... int _cameraStatus; // カメラの状態 AEEMediaData _mediaData; // メディア データ } camera_app;
カメラの状態は、アプリ起動時に実行される camera_app_InitAppData 関数で初期化します。
boolean camera_app_InitAppData(camera_app* pMe) { ... // Insert your code here for initializing or allocating resources... // カメラ関係の変数の初期化 pMe->_camera = NULL; pMe->_cameraStatus = CAMERA_STATUS_NULL; ... }
カメラ インターフェースの初期化
カメラ インターフェースの初期化関数 camera_app_InitializeCamera 関数で、メディア データ、画像サイズ、遅延エンコードモードを設定します。
int camera_app_InitializeCamera(camera_app *pMe) { ... if (result == SUCCESS) { ... ICAMERA_SetDisplaySize(pMe->_camera, &size); // ここから追加 // メディア データの設定 // スナップショット モードを利用する前には // ファイルに保存しない場合でも必ず設定しなければならない // 今回は使用しないので、適当な値を設定 pMe->_mediaData.clsData = MMD_FILE_NAME; pMe->_mediaData.pData = "dummy.jpg"; ICAMERA_SetMediaData(pMe->_camera, &(pMe->_mediaData), "image/jpeg"); // 画像サイズの設定 (必須) // 今回は QVGA にする size.cx = 240; size.cy = 320; ICAMERA_SetSize(pMe->_camera, &size); // 遅延エンコードを使用するためには必須 ICAMERA_DeferEncode(pMe->_camera, TRUE); } else { pMe->_camera = NULL; // 次を追加 pMe->_cameraStatus = CAMERA_STATUS_NULL; } return result; }
カメラの停止
カメラの停止を行う camera_app_StopCamera 関数です。
// カメラを停止する int camera_app_StopCamera(camera_app *pMe) { // 次を追加 pMe->_cameraStatus = CAMERA_STATUS_BEGIN_STOP; return ICAMERA_Stop(pMe->_camera); }
_cameraStatus 変数に CAMERA_STATUS_BEGIN_STOP を代入することで、コールバック関数内で camera_app_StopCamera 関数によってカメラの停止が判断できます。
インターフェースの解放
カメラ インターフェースを解放を行う camera_app_FreeCamera 関数を定義します。カメラが動作にかかわらずに camera_app_FreeCamera 関数を呼び出せようにします。
void camera_app_FreeCamera(camera_app *pMe) { if (!pMe->_camera) { // 解放済み return; } if (pMe->_cameraStatus == CAMERA_STATUS_BEGIN_FREE) { // 現在解放処理に移行中なら何もしない return; } if (pMe->_cameraStatus == CAMERA_STATUS_READY) { // カメラが待機状態なので、そのまま解放できる ICAMERA_Release(pMe->_camera); pMe->_camera = NULL; pMe->_cameraStatus = CAMERA_STATUS_NULL; } else { // カメラが動作中なので、一旦終了させる必要がある if (pMe->_cameraStatus == CAMERA_STATUS_BEGIN_STOP) { // 二重に ICAMERA_Stop() を呼ぶのを防ぐ pMe->_cameraStatus = CAMERA_STATUS_BEGIN_FREE; } else { pMe->_cameraStatus = CAMERA_STATUS_BEGIN_FREE; ICAMERA_Stop(pMe->_camera); } } }
camera_app_FreeAppData() 中の
camera_app_StopCamera(pMe);
を
camera_app_FreeCamera(pMe);
に変更します。
プレビューの開始
プレビューを開始する camera_app_PreviewCamera 関数です。
int camera_app_PreviewCamera(camera_app *pMe) { int result = SUCCESS; if (pMe->_cameraStatus == CAMERA_STATUS_PREVIEW) { // 現在プレビュー中なら何もしない return result; } if (pMe->_cameraStatus == CAMERA_STATUS_READY) { // カメラが待機状態なので、そのままプレビュー モードに移行できる pMe->_cameraStatus = CAMERA_STATUS_PREVIEW; result = ICAMERA_Preview(pMe->_camera); } else { // カメラが動作中なので、一旦終了させる必要がある pMe->_cameraStatus = CAMERA_STATUS_PREVIEW; result = ICAMERA_Stop(pMe->_camera); } return result; }
カメラの状態を保持する変数が増えたので、カメラが起動・停止に関係なく問題は起きません。
スナップショットの撮影
スナップショット モードに移行するための関数 camera_app_SnapshotCamera 関数を定義します。
int camera_app_SnapshotCamera(camera_app *pMe) { int result = SUCCESS; if (pMe->_cameraStatus == CAMERA_STATUS_BEGIN_SNAPSHOT) { // 現在スナップショット モードに移行中なら何もしない return result; } if (pMe->_cameraStatus == CAMERA_STATUS_READY) { // カメラが待機状態なので、そのままスナップショット モードに移行できる pMe->_cameraStatus = CAMERA_STATUS_SNAPSHOT; result = ICAMERA_RecordSnapshot(pMe->_camera); } else { // カメラが動作中なので、一旦終了させる必要がある pMe->_cameraStatus = CAMERA_STATUS_BEGIN_SNAPSHOT; result = ICAMERA_Stop(pMe->_camera); } return result; }
スナップショット モードに移行するときには、カメラを停止しておくことがポイントです。
camera_app_OnSnapshot 関数には、スナップショット撮影が完了したときの全ての処理を記述します。それから、スナップショット モードで撮影した画像を画面に表示します。
void camera_app_OnSnapshot(camera_app *pMe) { IBitmap *bitmap; int result = SUCCESS; // 画像を取得 // この画像は自分で解放しなければならない result = ICAMERA_GetFrame(pMe->_camera, &bitmap); if (result != SUCCESS) { return; } // 画面に描画する IDISPLAY_BitBlt(pMe->pIDisplay, 0, 0, pMe->DeviceInfo.cxScreen, pMe->DeviceInfo.cyScreen, bitmap, 0, 0, AEE_RO_COPY); IDISPLAY_Update(pMe->pIDisplay); // 画像を解放する IBITMAP_Release(bitmap); }
処理内容は camera_app_OnPreview 関数と同じです。
camera_app_OnSnapshot 関数の呼び出しは、コールバック関数 camera_app_OnCamera 関数で行います。
void camera_app_OnCamera(void *pUser, AEECameraNotify *pNotify) { camera_app *pMe = (camera_app *)pUser; switch (pNotify->nStatus) { case CAM_STATUS_FRAME: // 新たなフレームを取得した if (pMe->_cameraStatus == CAMERA_STATUS_PREVIEW) { // プレビュー用画像が取得できた camera_app_OnPreview(pMe); } break; case CAM_STATUS_DONE: // 何らかの処理が完了した switch (pMe->_cameraStatus) { case CAMERA_STATUS_PREVIEW: pMe->_cameraStatus = CAMERA_STATUS_READY; // プレビュー モードへの移行途中である // もう一度 camera_app_PreviewCamera() を呼ばなければならない camera_app_PreviewCamera(pMe); break; case CAMERA_STATUS_BEGIN_SNAPSHOT: pMe->_cameraStatus = CAMERA_STATUS_READY; // スナップショット モードへの移行途中である // もう一度 camera_app_SnapshotCamera() を呼ばなければならない camera_app_SnapshotCamera(pMe); break; case CAMERA_STATUS_SNAPSHOT: pMe->_cameraStatus = CAMERA_STATUS_READY; // スナップショット モードでの撮影が完了した camera_app_OnSnapshot(pMe); break; case CAMERA_STATUS_BEGIN_STOP: // カメラの終了処理が完了した pMe->_cameraStatus = CAMERA_STATUS_READY; break; case CAMERA_STATUS_BEGIN_FREE: pMe->_cameraStatus = CAMERA_STATUS_READY; // ICamera インターフェースの解放作業の途中である // もう一度 camera_app_FreeCamera() を呼ばなければならない camera_app_FreeCamera(pMe); break; } break; } }
サスペンドとレジュームへの対応
サスペンドとレジュームに対応させます。
camera_app_HandleEvent 関数を次のようにします。
static boolean camera_app_HandleEvent(camera_app* pMe, AEEEvent eCode, uint16 wParam, uint32 dwParam) { switch (eCode) { ... // App is being suspended case EVT_APP_SUSPEND: // Add your code here... // サスペンドへ移行するときは、 // ICamera インターフェースを解放する必要がある camera_app_FreeCamera(pMe); return(TRUE); // App is being resumed case EVT_APP_RESUME: // Add your code here... camera_app_InitializeCamera(pMe); return(TRUE); ... } return FALSE; }
セレクト キーを押すことでプレビュー モードとスナップショット モードとでモード切替できるようにすれば完成です。