【今更だけどandroid.hardware.Cameraを使う】カメラプレビューをTextureViewに表示する

このエントリーを Google ブックマーク に追加
Pocket
[`yahoo` not found]

android.hardware.Cameraを使うことで、Android端末にあるカメラデバイスにアクセスして使うことができます。
android.hardware.Cameraは、現在では非推奨となっていますがOpenCV等ではまだまだ使われています。

Android端末に実装されているカメラデバイスは固有の性能があります。
そのため、ある端末では出来るのに別の端末では出来ないということが多々あります。
今回はカメラプレビューをTextureViewに表示する方法を説明します。
下記の実装はすべて前回までに作ったクラスを修正しています。

Camera#setPreviewTextureの使い方

final void setPreviewTexture(SurfaceTexture surfaceTexture)で利用可能なSurfaceTextureを渡すことで、SurfaceTextureにカメラプレビューを表示することができます。
public class MyCameraPreviewSurfaceTexture extends TextureView implements TextureView.SurfaceTextureListener {

    private final static String TAG = "MyCameraPreview";

    private int cameraId;

    private SurfaceTexture surface;

    private Camera mCamera;

    public MyCameraPreviewSurfaceTexture(Context context, int cameraId) {
        super(context);
        this.cameraId = cameraId;
        setSurfaceTextureListener(this);
    }

    private void startPreview() {
        mCamera = Camera.open(this.cameraId);
        try {
            mCamera.setPreviewTexture(this.surface);
        } catch (IOException e) {
            e.printStackTrace();
        }
        mCamera.setDisplayOrientation(getCameraDisplayOrientation());
        Camera.Parameters parameters = mCamera.getParameters();
        if(parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            mCamera.setParameters(parameters);
        }

        mCamera.startPreview();
    }

    private void stopPreview(){
        if (mCamera != null) {
            mCamera.stopPreview();
        }
    }

    public void onPause(){
        if(mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }

    public int getCameraDisplayOrientation() {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        int rotation = ((Activity)getContext()).getWindowManager().getDefaultDisplay().getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0: degrees = 0; break;
            case Surface.ROTATION_90: degrees = 90; break;
            case Surface.ROTATION_180: degrees = 180; break;
            case Surface.ROTATION_270: degrees = 270; break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;
        } else {
            result = (info.orientation - degrees + 360) % 360;
        }
        return result;
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        this.surface = surface;
        stopPreview();
        startPreview();
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        stopPreview();
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(final SurfaceTexture surface) {
        Log.d(TAG, "onSurfaceTextureUpdated: ");
    }
}

TextureView#getBitmapを使う

TextureView#getBitmapは現在表示されている描画内容をBitmapとして取得するメソッドです。
最初からBitmapインスタンスになっているためそのままViewに適用することができます。

    public void showBitmap() {
        Bitmap bitmap = getBitmap(500,500);
        Toast toast = new Toast(getContext());
        ImageView imageView = new ImageView(getContext());
        imageView.setImageBitmap(bitmap);
        toast.setView(imageView);
        toast.show();
    }