Android の Camera2 API を使って マニュアルモードで撮影する

[Android の Camera2 API を使って カメラのプレビュー画面を表示する](https://qiita.com/ohwada/items/7bb65a566114066c8ced)
の続きです。

### 概要

Camera2 API では、3A (Auto Focus, Auto Exposure, Auto White Balance) と呼ばれる自動撮影モードがサポートされている。
それに加えて、露出時間やセンサ感度などのパラメータを指定するマニュアルモードもサポートされている。

Camera2 API の様々な機能を実装したL Camera というアプリが公開されている。
下記のような機能がある。

- マニュアルフォーカス
- マニュアル露出時間
- マニュアルセンサ感度
- DNG出力
- フル解像度バーストモード
- セミバルブモード ( Semi-bulb ) 
- フル解像度ビデオ録画

なお、このアプリは、Scale言語で記述されている。

この記事では、このアプリを参考に、java言語でマニュアル露出を実装する。


[L Camera](https://github.com/PkmX/lcamera)


### マニュアル露出をサポートしているか

下記のように判定する。


```
contains(characteristics.get(
                               CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES),
                        CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
```

### マニュアル露出のパラメータ

マニュアル露出に関するパラメータとして、下記のものが取得できる。

- 露出時間の範囲
- センサ感度の範囲
- 絞りの値の一覧
- 最小フレーム期間 (MinFrameDuration)

[reference : SENSOR_INFO_EXPOSURE_TIME_RANGE](https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#SENSOR_INFO_EXPOSURE_TIME_RANGE)

[reference : SENSOR_INFO_SENSITIVITY_RANGE](https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#SENSOR_INFO_SENSITIVITY_RANGE)

[reference : LENS_INFO_AVAILABLE_APERTURES](
https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#LENS_INFO_AVAILABLE_APERTURES)

[reference : getOutputMinFrameDuration](https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputMinFrameDuration(int,%20android.util.Size))

Nexus5では、下記の値を取得した
> 露出時間の範囲: [13231, 866975130]
> センサ感度の範囲: [100, 10000]
> 絞りの値の一覧: 2.4 (値は１つだけ)
> 最小フレーム期間: 33134528

### マニュアル露出のUI

露出時間やセンサ感度のリストを用意しておき、
その中から選ぶようにする。
露出時間は、慣習に従い 1/60 秒 のような分数で表記する。

![camera217_ui.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64075/183a49ab-0511-d589-619b-485da402f236.png)


### マニュアル露出の設定

マニュアル露出に関するパラメータとして、下記のものが指定できる。

- 制御モード(Control Mode)
- キャプチャの目的 (Capture Intent)
- 自動露出モード
- 露出時間
- センサ感度
- 絞り
- センサフレーム期間 (sensor_frame_duration)
- 手ぶれ補正 (Optical Stabilization)

[reference : CONTROL_AE_MODE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#CONTROL_AE_MODE)

[reference : SENSOR_EXPOSURE_TIME](
https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#SENSOR_EXPOSURE_TIME)

[reference : SENSOR_SENSITIVITY](
https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#SENSOR_SENSITIVITY)

[reference : LENS_APERTURE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#LENS_APERTURE)

[reference : SENSOR_FRAME_DURATION](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#SENSOR_FRAME_DURATION)

[reference : LENS_OPTICAL_STABILIZATION_MODE]
(https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#LENS_OPTICAL_STABILIZATION_MODE)

[reference : CONTROL_CAPTURE_INTENT](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#CONTROL_CAPTURE_INTENT)

設定の例

```
CaptureRequest.Builder builder

// # 3A モードを有効にする
    builder.set(CaptureRequest.CONTROL_MODE, CONTROL_MODE);

// 自動焦点を指定する
    builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);

// マニュアル露出を指定する
    builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);

// マニュアルを指定する
        builder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_MANUAL);

        builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 露出時間の値);
        builder.set(CaptureRequest.SENSOR_SENSITIVITY, センサ感度の値);
        builder.set(CaptureRequest.LENS_APERTURE, 絞りの値);

// 手ぶれ補正を指定する
        builder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE, CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON);
```

### CONTROL_MODE

制御モード
3Aモードの総括的なパラメータ
下記の値をとる


CONTROL_MODE_xxx

|Value|Name|Remarks|
|:------------:|:------------:|:------------:|
|0|OFF| |
|1|AUTO||
|２|USE_SCENE_MODE| |
|３|OFF_KEEP_STATE||

[CONTROL_MODE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#CONTROL_MODE)

### CONTROL_CAPTURE_INTENT

キャプチャの目的
3Aモードの最適なパラメータを決めるためのパラメータ
下記の値をとる

CONTROL_CAPTURE_INTENT_xxx

|Value|Name|Remarks|
|:------------:|:------------:|:------------:|
|0|CUSTOM| |
|1|PREVIEW||
|2|STILL_CAPTURE||
|3|VIDEO_RECORD||
|4|VIDEO_SNAPSHOT||
|5|ZERO_SHUTTER_LAG| |
|6|MANUAL||

[CONTROL_CAPTURE_INTENT](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#CONTROL_CAPTURE_INTENT)


注意
マニュアル露出のときは、OFFを指定すること。
そうしないと、露出時間やセンサ感度の値が 3A ルーチンにより上書きされる。


CONTROL_AE_MODE_xxx

|Value|Name|Remarks|
|:------------:|:------------:|:------------:|
|0|OFF||
|1|ON||
|2|ON_AUTO_FLASH| |
|3|ON_ALWAYS_FLASH| |
|4|ON_AUTO_FLASH_REDEYE| |

[CONTROL_AE_MODE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#CONTROL_AE_MODE)

### 保存形式

JPEG よりも　画質の良い DNG でも保存する。

DNG　には、
出時間やセンサ感度などの撮影条件を EXIF で付加してくれる利点もある。

具体的なプログラムは下記を参考に

 Camera2 API を使って RAW モードで撮影する
https://qiita.com/ohwada/items/cd1e82f926ccd6bf9d5a

### スクリーンショット

プレビュー画面
![camera217-preview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64075/3f272b36-c3c2-e375-0cae-cca49b3de57a.png)

Lightroom で EXIF を表示したもの
指定した露出時間とセンサ感度で撮影したことが確認できる
![camera217_lightroom.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64075/76123ef4-b6cf-bf9f-14b9-8c76e3dbba0a.png)

サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/Camera217