スマートフォンでカメラ画像を取得し JavaScript でエフェクトをかけてみた(その3:mozCameras編)


# ■はじめに

mozCameras API をつかってみました。
Firefox OS に最初から入っているカメラアプリもこの mozCameras API を使用しています。
機能が非常に豊富で、 mozCameras API を使うことでカメラ機能を最大限に活かしたアプリが作ることができそうです。

https://developer.mozilla.org/ja/docs/Web/API/Navigator/mozCameras

# ■Permissionの設定

mozCameras を使うには Privileged 以上のアプリである必要があります。一昔前では Certified 以上の権限が必要で、メーカやキャリアしか作成出来ませんでした。しかし、今では一般の開発者でも使えるようになりました。

```
  "permissions": {
    "camera": {
      "description": "Required for accessing cameras on the device." 
    }
  }
```

# ■処理フロー

処理フローはこの様になります。

<img src="https://qiita-image-store.s3.amazonaws.com/0/27642/5f007a60-b0cb-caaf-be3d-70567dd604b0.png" width="70%">

# ■CameraManager の取得

まず最初に CameraManager のオブジェクトを取得します。

window.navigator 配下に mozCameras の WebAPI を叩くことで、 CameraManager オブジェクトが取得できます。

```
  var cameras = window.navigator.mozCameras;
```

https://developer.mozilla.org/ja/docs/Web/API/Navigator/mozCameras

# ■カメラオブジェクトの取得

次にカメラオブジェクトを取得します。

CameraManager.getCamera() のメソッドを実行することで利用可能なカメラインスタンスを取得できます。

https://developer.mozilla.org/ja/docs/Web/API/CameraManager

Fx0 の様に前面、背面といった複数のカメラを搭載している端末も有るため、CameraManager.getListOfCameras() を実行しカメラのリストを取得したほうが良いです。

```
  var options = {
    mode: 'picture',
    recorderProfile: 'jpg',
    previewSize: {
      width: 1280,
      height: 720
    }
  };

  var camera = navigator.mozCameras.getListOfCameras()[0];

  function onSuccess(cameraControl) {
    // cameraControlからカメラの情報を取得/設定する 
  };

  function onError(error) {
    // エラー時の処理
  };

  navigator.mozCameras.getCamera(camera, options, onSuccess, onError);
```

カメラデバイスのオブジェクトの取得に成功すると、onSuccess()が呼ばれ、
引数で渡された cameraControl からカメラの情報を取得/設定することが出来ます。
これを使うことでホワイトバランスの設定やズームといった操作を行うことが出来ます。

https://developer.mozilla.org/en-US/docs/Web/API/CameraControl


# ■プレビュー表示

取得した画像はデフォルトでは横向きになっている為、まずは回転します。今回は貼り付ける際に CSS の transform にて回転させてます。

```
  transform: rotate(90deg);
```

<img src="https://qiita-image-store.s3.amazonaws.com/0/27642/ade0edde-4b85-b717-3340-d51780a198f7.png" width="60%">


# ■静止画の撮影

次に撮影です。
CameraControl.takePicture() を使用することで撮影できます。結果は blob 形式で返却されるため、 img 要素へ設定したり、そのまま SD カードに保存することが出来ます。

注意点として、takePicture()を行う前に、フォーカスをあわせる必要がありますので、 autoFocus() メソッドを呼ぶようにする必要があります。
呼ばないとボケボケな画像になります・・・

```
  cameraControl.autoFocus(function() {
    var pictureOptions = {
      rotation: 90
    };

    cameraControl.takePicture(pictureOptions, function(blob) {
      // 結果は、blobで取得。
    });
  });
```

# ■ シャッター音について

mozCameras API も getUserMedia 同様にシャッター音は鳴りません。鳴らすためのメソッドも用意されていないため、自前でシャッター音を鳴らす必要があります。
前回同様、Audio APIで実現できます。

# ■エフェクト処理

取得した写真をimg要素に追加した後、 Seriously.js を使用してエフェクト処理を行います。

また、今回は試してませんが、、mozCameras API の CameraControl.effect に値を設定することで、エフェクト処理を行うことができるみたいです。


<b>エフェクト前</b>
<img src="https://qiita-image-store.s3.amazonaws.com/0/27642/3bc8bd60-8ab6-7c9a-5ec6-04ca28df4534.png" width="60%">



<b>エフェクト後</b>
<img src="https://qiita-image-store.s3.amazonaws.com/0/27642/206e45dd-8c5d-6dcd-212f-3882be530b5b.png" width="60%">



# ■おわりに

作成したアプリはこちらに格納しています。よろしければ覗いてみてください。

https://github.com/namaranran/effecter

mozCameras API を使用すれば最初からインストールされているカメラアプリと同等以上のカメラが作れそうです。
ただし、機能がある分使い方が複雑です。


これまで紹介した様にカメラを使うには以下の3つの方法がありました。

* camera API
* getUserMedeia
* mozCameras API

それぞれメリット・デメリットが有るため、用途に応じて使い分けると良いかもしれません。

| 種別            | メリット  | デメリット|
|----------------|-----------|---------|
| camera API     |APIを呼び出すだけで良いので実装が簡単 | 標準のカメラアプリに連携するため、作り込みが出来ない |
| getUserMedeia  |実装が簡単。自前でカメラアプリを作るには良い| 画質が荒く、ユースケースを意識する必要あり |
| mozCameras API |高機能なカメラを自前で作成できる| 実装が複雑になる |