LoginSignup
7
9

More than 3 years have passed since last update.

Android の Camera2 API を使って 写真を撮る

Last updated at Posted at 2019-05-18

Android の Camera2 API を使って カメラのプレビュー画面を表示する
の続きです。

下記の公式サンプルを例に説明する。

How to use basic functionalities of Camera2 API

下記の記事を参考にした。

Camera2 APIを使ったカメラ機能の実装

CameraDevice#createCaptureSession

カメラのキャプチャセッションを作成するメソッド。

reference: CameraDevice#createCaptureSession

プレビュー画面を表示する場合は、下記のようにキャプチャする出力先に TexttureView の Surface を指定する。

// TexttureView のSurface
    SurfaceTexture texture = mTextureView.getSurfaceTexture();
    texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
    Surface surface = new Surface(texture);

// キャプチャセッションを作成する
    List outputs = Arrays.asList(surface);
    cameraDevice.createCaptureSession(outputs, CameraCaptureSession.StateCallback, backgroundHandler);
            );

ImageReader

カメラからの画像をキャプチャする Surfaceを持つクラス

reference: ImageReader

下記のようにインスタンスを生成する。

// インスタンスを生成する
    ImageReader imageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(), ImageFormat.JPEG, 2);
// リスナーを設定する
    imageReader.setOnImageAvailableListener(
                        imageAvailableListener, backgroundHandler);

写真を撮る場合は、キャプチャする出力先 に
ImageReaderSurface の Surface を追加する。

    List outputs = Arrays.asList(surface, imageReader.getSurface());
    cameraDevice.createCaptureSession(outputs, CameraCaptureSession.StateCallback, backgroundHandler);
            );

CameraCaptureSession#capture

カメラにキャプチャする画像を要求するメソッド

reference: CameraCaptureSession#capture

Picture ボタンをクリックすると、このメソッドを実行する。

    previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
    captureSession.capture(previewRequestBuilder.build(), captureCallback, backgroundHandler);

CaptureCallback の中で、ImageReader をターゲットにして、このメソッドを実行する。

    CaptureRequest.Builder captureBuilder =
    cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
    captureBuilder.addTarget(imageReader.getSurface());
    captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
    captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
    captureSession.capture(captureBuilder.build(), captureCallback, backgroundHandler);

OnImageAvailableListener#onImageAvailable

ImageReaderに画像が設定されたときに呼ばれるメソッド

reference: OnImageAvailableListener#onImageAvailable

このメソッドが呼ばれた時は、下記のように画像の処理を行う。

    backgroundHandler.post(new ImageSaver(reader.acquireNextImage(), mFile));

ImageSaver

画像をファイルに保存するクラス
Camera2API ではなく、公式サンプルで作成したもの

下記のように、ファイルに保存する

    Image image;
    File file;
    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
    byte[] bytes = new byte[buffer.remaining()];
    buffer.get(bytes);
    FileOutputStream output = new FileOutputStream(file);
    output.write(bytes);

画像の保存先

公式サンプルでは、アプリごとの領域である ExternalFilesDir に保存する。
この領域はアクセス権限が不要だが、保存された画像を見るためにはファイルマネージャーアプリが必要となる。

reference: getExternalFilesDir

標準的なカメラアプリと同様に、SD カードの DCIM デレクトリの保存することもできる。
この領域は、SD カードのへのアクセス権限が必要となるが、
コンテンツプロバイダーに画像情報を登録して写真閲覧アプリで見ることができる。

前回 作成した Camera2Source は、基本的な処理は公式サンプルと同じであるが、下記の違いがある。
公式サンプルでは、onImageAvailable が呼ばれた時は ImageSaverを使って画像を保存する。
Camera2Sourceでは、onImageAvailableが呼ばれた時は コールバックで Activity に処理を戻し ImageSaver を使わずに画像を保存する。

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

camera27_saved.png

7
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9