1. ホーム
  2. android

[解決済み] Android Camera Preview Stretched

2022-05-14 02:38:24

質問

Androidでカスタムカメラのアクティビティを作成しているのですが、カメラを回転させるとサーフェスビューの縦横比がおかしくなってしまいます。

アクティビティのoncreateで、カメラのパラメータを表示するサーフェスビューを保持するframelayoutを設定しました。

//FrameLayout that will hold the camera preview
        FrameLayout previewHolder = (FrameLayout) findViewById(R.id.camerapreview);

        //Setting camera's preview size to the best preview size
        Size optimalSize = null;
        camera = getCameraInstance();
        double aspectRatio = 0;
        if(camera != null){
            //Setting the camera's aspect ratio
            Camera.Parameters parameters = camera.getParameters();
            List<Size> sizes = parameters.getSupportedPreviewSizes();
            optimalSize = CameraPreview.getOptimalPreviewSize(sizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);
            aspectRatio = (float)optimalSize.width/optimalSize.height;
        }

        if(optimalSize!= null){
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, (int)(getResources().getDisplayMetrics().widthPixels*aspectRatio));
            previewHolder.setLayoutParams(params);
            LayoutParams surfaceParams = new LayoutParams(LayoutParams.MATCH_PARENT, (int)(getResources().getDisplayMetrics().widthPixels*aspectRatio));
            cameraPreview.setLayoutParams(surfaceParams);

        }

        cameraPreview.setCamera(camera);

        //Adding the preview to the holder
        previewHolder.addView(cameraPreview);

次に、Surfaceビューで、カメラのパラメータを表示するように設定します。

public void setCamera(Camera camera) {
        if (mCamera == camera) { return; }

        mCamera = camera;

        if (mCamera != null) {
            requestLayout();

            try {
                mCamera.setPreviewDisplay(mHolder);
            } catch (IOException e) {
                e.printStackTrace();
            }


            if(mCamera != null){
                //Setting the camera's aspect ratio
                Camera.Parameters parameters = mCamera.getParameters();
                List<Size> sizes = parameters.getSupportedPreviewSizes();
                Size optimalSize = getOptimalPreviewSize(sizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);

                parameters.setPreviewSize(optimalSize.width, optimalSize.height);
                mCamera.setParameters(parameters);
            }

            /*
              Important: Call startPreview() to start updating the preview surface. Preview must 
              be started before you can take a picture.
              */
            mCamera.startPreview();
        }

    }

<イグ

携帯電話を回転させると、レゴマンが背伸びをしたり痩せたりするのがわかります。

カメラビューのアスペクト比が正しいことを確認するにはどうすればよいですか?

どのように解決するのですか?

APIデモを元に、この方法を使ってプレビューサイズを取得しています。

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio=(double)h / w;

        if (sizes == null) return null;

        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        for (Camera.Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

見ての通り、画面の幅と高さを入力する必要があります。このメソッドは、これらの値に基づいて画面の比率を計算し、サポートされているプレビューサイズのリストから、利用可能なものの中からあなたに最適なものを選択します。CameraオブジェクトがNULLでない場合は、以下のようにしてsupportedPreviewSizeのリストを取得します。

mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();

そしてonMeasureで、このように最適なpreviewSizeを取得することができます。

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);

        if (mSupportedPreviewSizes != null) {
           mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
        }
    }

そして、(私のコードではsurfaceChangedメソッドで、私がCameraActivityコードのAPI Demos構造を使用していると言ったように、あなたはEclipseでそれを生成することができます)。

Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.startPreview();

あと、私もほぼ同じアプリをやっていたので、一つヒントを。カメラアプリの場合、ステータスバーを非表示にするのが良い方法です。Instagramのようなアプリケーションは、それをやっている。画面の高さの値が小さくなり、比率の値も変わります。端末によってはプレビューサイズがおかしくなる可能性があります(SurfaceViewが少し削られます)。


ご質問の件ですが、プレビューの比率が正しいかどうかを確認するにはどうしたらよいでしょうか。という質問に対して、「プレビューの比率が正しいかどうかを確認する方法」ということで、「パラメータで設定した高さと幅を取得する。

mCamera.setParameters(parameters);

設定された比率は高さ/幅と同じです。もしカメラが画面上できれいに見えるようにしたいなら、カメラに設定したパラメータの高さと幅の比率は、画面の高さ(ステータスバーを除く)/幅の比率と同じでなければなりません。