Android-カメラのプレビューが横向き


123

カメラの画面をプレビューで表示しています。

すべてが正常に機能し、サーフェスが作成され、サーフェスが設定され、サーフェスが表示されます。

ただし、ポートレートモードでは常に誤った90度の角度で画像が表示されます。

写真のような:

代替テキスト

次のコードを使用すると、画像が正しく設定されることを認識しています。

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

しかし、他の要素が含まれているアクティビティ内にプレビューがあり、私のアクティビティを横向きモードで表示するのは意味がありません。(デフォルトでは無効になっています)

だからとにかくプレビューの向きを変えるだけの方法があるのだろうか?そして、残りのアクティビティを縦向きモードで正しく表示したままにしますか?

それとも正しくプレビューが表示されるようにプレビューを回転させますか?


回答:


145

この問題は、特定のハードウェアのバグとしてここに示されているように見えましたが、API 8で利用可能なmCamera.setDisplayOrientation(degrees)への呼び出しを使用することで克服できます。

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {            
    if (isPreviewRunning) {
        mCamera.stopPreview();
    }

    Parameters parameters = mCamera.getParameters();
    Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();

    if(display.getRotation() == Surface.ROTATION_0) {
        parameters.setPreviewSize(height, width);                           
        mCamera.setDisplayOrientation(90);
    }

    if(display.getRotation() == Surface.ROTATION_90) {
        parameters.setPreviewSize(width, height);                           
    }

    if(display.getRotation() == Surface.ROTATION_180) {
        parameters.setPreviewSize(height, width);               
    }

    if(display.getRotation() == Surface.ROTATION_270) {
        parameters.setPreviewSize(width, height);
        mCamera.setDisplayOrientation(180);
    }

    mCamera.setParameters(parameters);
    previewCamera();                      
}

And the previewCamera method :

public void previewCamera() {        
    try {           
        mCamera.setPreviewDisplay(mSurfaceHolder);          
        mCamera.startPreview();
        isPreviewRunning = true;
    } catch(Exception e) {
        Log.d(APP_CLASS, "Cannot start preview", e);    
    }
}

これはHTCの欲望に関するものであり、最初に各ローテーションチェックにログステートメントを入れてローテーションを確認し、デバイスでデバッグして、デバイスをローテーションしている間にlogCat出力を監視する必要がありました。HTCの欲望の場合、0は予想どおりの電話(縦)、90度は電話を90度反時計回りに回転させていました(時計回りであると想定していました)。コードでは、電話が90度または180度のときにディスプレイを回転させる必要がないことがわかります。デバイスがこれを処理するように見えました。1点のみが正常に機能しない:270度の回転とは、デバイスを時計回りに90度回転させ、ディスプレイの回転カウンターが正常であることを示しますが、デバイスを反時計回りに270度回転させると、適切に補正されていないように見えます。

PS適切なローテーションでの幅と高さの入れ替えに注意してください。


7
しかしsetDisplayOrientation(degree); メソッドはフォーム2.2をサポートしていますが、下位バージョンはどうですか?parameters.setRotation(90); parameters.set( "orientation"、 "portrait"); 機能していません。以前のバージョンの解決策がある場合は、私を助けてください。
Vikram

1
私は常にポートレートモードで表示されるプレビューをアプリに実装しました。私は常に画面を90度回転させていましたが、これはHTC Desire Cでテストするまですべてのデバイスで機能するように見えました。今はデバイスでこれをテストすることを期待していないので、これが修正されるかどうかを明確にしてください最終的にHTCの欲求にうまく働いたことを示唆しています。ありがとう!
argenkiwi

13
mCamera.setParameters(parameters);表面寸法は、自分の携帯電話のための有効なプレビューサイズではないため、ステートメントは、私のアプリをクラッシュ(私は目に見えるステータスバーを保つかもしれないので?)。ただし、パラメータを設定せずにmCamera.setDisplayOrientation(90)then を使用しても機能することがわかりましたmCamera.setPreviewDisplay(mSurfaceHolder);
nicopico 2013

3
switchステートメントを使用するとよりクリーンになります
Siavash

2
これは、プレビューがすべてのデバイスで横向きであると想定していませんか?一部のデバイスでは横向きで、他のデバイスでは縦向きです...デバイスのデフォルトのカメラの向きが電話の縦向きの面と一致しているかどうかを確認する方法はありますか?
Siavash 2016年

16

表示方向を設定してみてください。それは私の問題を解決します。

 mCamera.setDisplayOrientation(90);

5
保存時に縦向きの画像を横向きに保存します。解決策はありますか?
Akanksha Rathore

@Akanksha:このフラグはプレビュー表示にのみ適用されます。onPreviewFrame()またはに返されるバッファの方向は変更されませんonPictureTaken()
Alex Cohn

13
 public void surfaceCreated(SurfaceHolder holder) {
     mCamera = Camera.open();
     mCamera.setDisplayOrientation(90);
     try {
         mCamera.setPreviewDisplay(holder);
         mCamera.setPreviewCallback(new PreviewCallback() {

             @Override
             public void onPreviewFrame(byte[] data, Camera camera) {
             }
         });

     } catch (Exception e) {
         e.printStackTrace();
     }
}

このコードを試してください


3
保存時に縦向きの画像を横向きに保存します。解決策はありますか?
Akanksha Rathore

@AkankshaはおそらくEXIFパラメータに関係しています。
EpicPandaForce 2016

4

フロントカメラに問題がありました(逆さまの問題)。次に、Androidドキュメントに記載されている次の方法を使用しました-

public void setCameraDisplayOrientation(Activity activity , int icameraId , Camera camera1s)
    {
        CameraInfo cameraInfo = new CameraInfo();

        Camera.getCameraInfo(icameraId, cameraInfo);

        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();

        int degrees = 0; // k

        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 (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
        {
            // cameraType=CAMERATYPE.FRONT;

            result = (cameraInfo.orientation + degrees) % 360;
            result = (360 - result) % 360; // compensate the mirror

        }
        else
        { // back-facing

            result = (cameraInfo.orientation - degrees + 360) % 360;

        }
        // displayRotate=result;
        camera.setDisplayOrientation(result);


    }

3
この方法は、カメラのドキュメントから来ている:developer.android.com/reference/android/hardware/...
VinceFior

@VinceFior彼が公式文書から投稿した場合、何か問題がありますか?
Ranjith Kumar

1
@RanjithKumar特にありませんが、私はソースにクレジットを与え、そこに人々がより多くのコンテキストを示すようにしたかっただけです。:)
VinceFior

3

私はmCamera.setDisplayOrientation(90)のアドバイスを受けてそれを行いました。しかし、何らかの理由でバージョン2.3.3では他のアプローチが機能しないため、ビットマップも回転させました。

ビットマップを回転させるためにこれを行いました:

Matrix matrix = new Matrix();
matrix.postRotate(90);
imageView1 = new ImageView(this);
Bitmap bitmap = BitmapFactory.decodeFile(files[i].getAbsolutePath());
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap , 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(rotatedBitmap, 80, 80, true);
imageView1.setImageBitmap(scaledBitmap);

0

私のコードをチュートリアルのコードと比較しました。最終的に修正したのは、次のコードをAndroidManifext.xmlに挿入することです。<activity>タグ内:

android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation">

0
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // If your preview can change or rotate, take care of those events here.
    // Make sure to stop the preview before resizing or reformatting it.

    if (mHolder.getSurface() == null) {
        // preview surface does not exist
        return;
    }

    try {
        mCamera.stopPreview();
    } catch (Exception e) {
        e.printStackTrace();
    }

    Camera.Parameters parameters = mCamera.getParameters();
    Display display = ((WindowManager) getContext().getSystemService(WINDOW_SERVICE)).getDefaultDisplay();

    if (display.getRotation() == Surface.ROTATION_0) {
        parameters.setPreviewSize(h, w);
        mCamera.setDisplayOrientation(90);
    }

    if (display.getRotation() == Surface.ROTATION_90) {
        parameters.setPreviewSize(w, h);
        mCamera.setDisplayOrientation(0);
    }

    if (display.getRotation() == Surface.ROTATION_180) {
        parameters.setPreviewSize(h, w);
        mCamera.setDisplayOrientation(270);
    }

    if (display.getRotation() == Surface.ROTATION_270) {
        parameters.setPreviewSize(w, h);
        mCamera.setDisplayOrientation(180);
    }

    previewCamera();
}

public void previewCamera() {
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (Exception e) {
        //Log.d(APP_CLASS, "Cannot start preview", e);
        e.printStackTrace();
    }
}

0

SENSOR_ORIENTATIONの値は、90度にハードコーディングする代わりに回転に使用する値を説明していると思います

CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        if (manager == null) {
            Log.i(TAG, "camera manager is null");
            return;
        }
        for (String id: manager.getCameraIdList()) {
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(id);
            Integer orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
            Log.i(TAG, "camera sensor orientation is " + orientation);
        }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.