アプリで決めたActivityの向きがLANDSCAPEの時、Camera2のCameraDeviceから受け取るカメラのプレビューの向きがずれる
昨日のImageReaderのメモで プレビューの向きがおかしいのが気になる、という話を書きました。
その件について調べると
などどうもアプリの画面の向きがLANDSCAPEの場合、そういうことがあるらしい。
一つには、TextureView
に画像変換用の Matrix
をセットすることで、TextureViewにセットされる画像をいじることができて、例えば下記のように記述した場合、
// https://stackoverflow.com/questions/34536798/android-camera2-preview-is-rotated-90deg-while-in-landscape Matrix rotate = new Matrix(); rotate.postScale(0.5f, 0.5f); rotate.postTranslate(IMAGE_HEIGHT / 2, 0); rotate.postRotate(60); mTextureView.setTransform(rotate);
みたいな感じとなる。
これをもうちょっとうまくやる。
// Landscapeのアプリの場合、カメラの向きとプレビューの向きがずれるっぽい // https://stackoverflow.com/questions/34536798/android-camera2-preview-is-rotated-90deg-while-in-landscape Matrix rotate = new Matrix(); rotate.postRotate(270); // デバイスの向きとアプリの向きの差分から決めると良い // 関連: https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java#L520-L541 rotate.postTranslate(0, mTextureView.getWidth()); rotate.postScale(1.0f * 1.15f, 0.56f * 1.15f); // とりあえず頑張ってうめた mTextureView.setTransform(rotate);
これでだいたいプレビューの向きとサイズがあってくる。
このMatrixでの操作手順は、前操作した結果にさらに次の操作が反映されるので実際紙などを使って考えた方が早い。
さて、さっきのコードについてScaleが手打ちだとちょっと困るのでもう少しだけ頑張って
private void createCameraPreviewSession() { // Landscapeのアプリの場合、カメラの向きとプレビューの向きがずれるっぽい // https://stackoverflow.com/questions/34536798/android-camera2-preview-is-rotated-90deg-while-in-landscape Matrix rotate = new Matrix(); rotate.postRotate(270); // デバイスの向きとアプリの向きの差分から決めると良い // 関連: https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java#L520-L541 rotate.postTranslate(0, mTextureView.getWidth()); rotate.postScale((1.0f * IMAGE_WIDTH / IMAGE_HEIGHT) * (mTextureView.getWidth() / mTextureView.getHeight()), (1.0f * IMAGE_HEIGHT / IMAGE_WIDTH) * (mTextureView.getWidth() / mTextureView.getHeight())); mTextureView.setTransform(rotate); SurfaceTexture texture = mTextureView.getSurfaceTexture(); texture.setDefaultBufferSize(IMAGE_WIDTH, IMAGE_HEIGHT); // 自分の手元のデバイスで決めうちしてます
こう。
今日時点での全体のコードは https://gist.github.com/woshidan/5443e4d0d779ffff036862d7010e14ef
気になってることについては
- [新しい気になること]デバイスの向きとアプリの向きの差分
- [既存気になること]CameraDevice解放のタイミングについて
- [既存気になること]CameraCaptureSession closeのタイミングについて