新しいCamera2を単純なSurfaceViewで動作させようとしていますが、ライブプレビューで問題が発生しています。一部のデバイスでは、画像が不均衡に引き伸ばされ、他のデバイスでは見栄えがします。
プレビューストリームサイズのサイズに合うようにプログラムで調整するSurfaceViewをセットアップしました。
Nexus 5ではこれは問題ないように見えますが、1台のSamsungデバイスがうまく機能していません。また、Samsungデバイスには、プレビューの右側に黒い境界線があります。
SurfaceViewを操作することは本当に不可能ですか、それとも今回はTextureViewに切り替えるときですか?
はい、それは確かに可能です。 SurfaceView
とそれに関連するSurface
は2つの異なるものであり、それぞれにサイズを割り当てることができます。
Surface
は、カメラの出力を保持する実際のメモリバッファであるため、そのサイズを設定すると、各フレームから取得する実際の画像のサイズが決まります。カメラから利用できるフォーマットごとに、このバッファーを作成できる可能な(正確な)サイズの小さなセットがあります。
SurfaceView
は、この画像が利用可能な場合に表示するものであり、基本的にはレイアウト内の任意のサイズにすることができます。基になる関連画像データをレイアウトサイズに合わせて拡大しますが、この表示サイズはデータのサイズとは異なることに注意してください-Androidは、表示用に画像データのサイズを自動的に変更します。これがおそらくあなたのストレッチを引き起こしています。
たとえば、次のように、camera2basicのAutoFitTextureViewに似たSurfaceView
ベースのautofitビューを作成できます(これが私が使用しているものです)。
import Android.content.Context;
import Android.util.AttributeSet;
import Android.view.SurfaceView;
public class AutoFitSurfaceView extends SurfaceView {
private int mRatioWidth = 0;
private int mRatioHeight = 0;
public AutoFitSurfaceView(Context context) {
this(context, null);
}
public AutoFitSurfaceView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AutoFitSurfaceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
* calculated from the parameters. Note that the actual sizes of parameters don't matter, that
* is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
*
* @param width Relative horizontal size
* @param height Relative vertical size
*/
public void setAspectRatio(int width, int height) {
if (width < 0 || height < 0) {
throw new IllegalArgumentException("Size cannot be negative.");
}
mRatioWidth = width;
mRatioHeight = height;
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (0 == mRatioWidth || 0 == mRatioHeight) {
setMeasuredDimension(width, height);
} else {
if (width < height * mRatioWidth / mRatioHeight) {
setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
} else {
setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
}
}
}
}
createCaptureSession のドキュメントには
SurfaceViewに描画する場合:SurfaceViewのSurfaceが作成されたら、setFixedSize(int、int)を使用してSurfaceのサイズをgetOutputSizes(SurfaceHolder.class)によって返されるサイズの1つに設定します。
私はCamera2を使ったことがありません(しかし、新しいテクノロジーでは非常に興味深いです)。私が提案できるのは、サンプルに従うことだけです。また、注意深くチェックすると、サンプルはカスタムTextureView
を使用しているので、プロジェクトにコピーしてみてください。
/**
* A {@link TextureView} that can be adjusted to a specified aspect ratio.
*/
public class AutoFitTextureView extends TextureView {
また、SurfaceViewとTextureViewの違いは(理論的には)、レイアウトで通常のビューとして使用でき、他のビュー階層を通じて「全体をパンチ」できることと、Camera2はAPI21 +でのみ使用できることを考慮しています... TextureView
への移行に害はありません