Android の Camera2 API を使って カメラのプレビュー画面を表示する
の続きです。
下記の公式サンプルを例に説明する。
How to use basic functionalities of 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を持つクラス
下記のようにインスタンスを生成する。
// インスタンスを生成する
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