ホーム > デベロッパ > BREW プログラミング入門 > BREW でカメラ (後編) > - 2 / 3 -

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;
}

セレクト キーを押すことでプレビュー モードとスナップショット モードとでモード切替できるようにすれば完成です。