Developer's Blog

グッときた瞬間を記録するAndroidの新しいカメラAPI

adventcalendar2014-09

こんにちは!共同開発部 開発担当の戸澤です。

クリスマスまでの毎日のお楽しみ、Fenrir Advent Calendar 2014 の 9 日目です!
今回のテーマは 「2014年にグッときたコレ」 は Android 5.0(Lollipop) のカメラAPI です。

Android 5.0には様々な新機能が追加されていますが、今回はあえてクリスマスやお正月、グッときた冬の思い出を記録するために大幅に強化されたカメラAPIを紹介したいと思います。

カメラといえばスマートフォンの機能の中でもよく使われる機能ですが、その制御はけっこう大変。
ハードウェア依存で上手く動かなかったり、設定が難解だったりと苦しめられた方も多いのではないでしょうか?
そんなジャジャ馬なカメラAPI も Android5.0 で非推奨となり「android.hardware.camera2」 として生まれ変わりました。

camera2_docs

何が変わったの?

camera2 API では Camera の機能が CameraManager にまとめられ、既存のカメラ API の置き換えだけでなくフル HD での高速連写撮影や露光時間を変更しての撮影などデジカメでしかできなかった機能が手軽に使えるようになっています。

・フル解像度で 30 fps での高速連写撮影のサポート (Burst mode)
・フレーム間の撮影設定変更のサポート
・RAW 画像撮影のサポート
・マニュアルフォーカス
・マニュアルシャッタースピード
・マニュアル ISO

http://developer.android.com/reference/android/hardware/camera2/package-summary.html

さっそく使ってみよう!

それでは早速、Burst モードを用いて高速連写機能を試してみましょう

カメラの機能には CameraManager からアクセスできるようにまとめられているので、Activity から CameraManager を取得します。

 
// CameraManagerをActivityから取得
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);

おなじみのコードで CameraId の List を Loop して、使用するカメラを選択します。

 
// CameraIdListをLoopして使用するカメラを決定
// 旧 API では「for (int i = 0; i < Camera.getNumberOfCameras(); i++) {」こうしていたところ。
for (String cameraId : manager.getCameraIdList()) {

    // Cameraがサポートできる機能を取得
    // 旧 API の CameraInfo に相当する
    CameraCharacteristics characteristics
        = manager.getCameraCharacteristics(cameraId); 
&#91;/java&#93;</p>
<p>カメラに関する情報は CameraCharacteristics から取得できます。<br /> まずはハードウェアが新しい機能をサポートしているかチェック!</p>
<p>[java] characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); 

CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL

[レスポンス]
・INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY
全てのデバイスは最低でもこのレベルをサポートしています。
このレベルは非推奨となった CameraAPI とほぼ同じです。

・INFO_SUPPORTED_HARDWARE_LEVEL_FULL
ハードウェアレベルをサポートするデバイスは写真と後処理、高フレームレート時の高解像度キャプチャーに対する手動制御機能をサポートします。

「INFO_SUPPORTED_HARDWARE_LEVEL_FULL」が返されれば、Burst モードなど新しい機能がサポートされています。

カメラをプレビューする

カメラを Preview する方法も少し変更されています。
CameraManager から取得した CameraDevice と表示用の TextureView を登録した CaptureRequest を使って CaptureSession.setRepeatingRequest を呼び出すことでカメラをプレビューできます。

 
private void createCameraPreviewSession() {
    try {
        // プレビュー表示用のTextureViewからSurfaceTextureを取得する
        SurfaceTexture texture = mTextureView.getSurfaceTexture();
        assert texture != null;

        // プレビューサイズを調整する
        texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());

        // CameraCaptureSessionを作成する
        Surface surface = new Surface(texture);

        // プレビューを開始する
        mPreviewRequestBuilder
            = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        mPreviewRequestBuilder.addTarget(surface);
        mCameraDevice.createCaptureSession(
            Arrays.asList(surface,mImageReader.getSurface()),
                new CameraCaptureSession.StateCallback() {
                    @Override
                    public void onConfigured(CameraCaptureSession cameraCaptureSession) {
                        if (null == mCameraDevice) {
                            return;
                        }

                        mCaptureSession = cameraCaptureSession;
                        try {
                            mPreviewRequest = mPreviewRequestBuilder.build();
                            mCaptureSession.setRepeatingRequest(mPreviewRequest,
                            mCaptureCallback, mBackgroundHandler);
                        } catch (CameraAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }, null
        );

    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

Burst モードで 1 ショットずつ条件を変えながら、高速連写撮影してみよう

 
try {
    final CaptureRequest.Builder captureBuilder =
        mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);

    List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
    // 2 段階明るく撮影
    captureBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 6);
    // 標準で撮影
    captureBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
    // 1 段階暗く撮影
    captureBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 6);
    // キャプチャーの指示一覧を作成
    requestList.add(captureBuilder.build());
    // 登録した指示通りに連写で撮影
    mCaptureSession.captureBurst(requestList, mCaptureCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
    e.printStackTrace();
}

いかがでしたでしょうか。このほかにも、Android.hardware.camera2 には豊富な機能が用意されています。 詳しい使い方は公式のドキュメントやAndroidSDK v21のサンプル「Camera2Basic」などを参考にしてください。

この API が使えるのは Android5.0(Lollipop) からなので普及するのはもう少し先になるかもしれませんが、最新の端末をお持ちのデベロッパーの皆様はこの冬のグッときた瞬間を記録するために、早速アプリを作ってみてはいかがでしょう?

フェンリルのオフィシャル Twitter アカウントでは、フェンリルプロダクトの最新情報などをつぶやいています。よろしければフォローしてください!

Copyright © 2019 Fenrir Inc. All rights reserved.