17

Camera.setDisplayOrientationのドキュメントページには、「カメラ画像をディスプレイと同じ向きで表示する」ことを示す次のコードサンプルが含まれています。

 public static void setCameraDisplayOrientation(Activity activity,
         int cameraId, android.hardware.Camera camera) {
     android.hardware.Camera.CameraInfo info =
             new android.hardware.Camera.CameraInfo();
     android.hardware.Camera.getCameraInfo(cameraId, info);
     int rotation = activity.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;  // compensate the mirror
     } else {  // back-facing
         result = (info.orientation - degrees + 360) % 360;
     }
     camera.setDisplayOrientation(result);
 }

しかし、使用に問題があり、画像が上下逆に表示されることがありました。何度か試行錯誤した結果、正しいコードは次のようになることがわかりました(メソッドの最後の8行を置き換えます)。

    int result = (360 + info.orientation - degrees) % 360;
    camera.setDisplayOrientation(result);

(つまり、背面カメラの計算は前面カメラでも正しいということです。)「ミラーを補正する」というコメントは、回転によってミラーリングを元に戻すことができないため、少し奇妙です。この操作では、90°と270°の回転のみが入れ替わります。私には本当に意味があります。

したがって、問題は、サンプルが実際に間違っているのか、それとも何かが足りないのかということです。 バックカメラとフロントカメラの両方、およびサポートされているすべての向きの複数のデバイスで試してみたので、コードが機能していることがわかりました。言及する価値があるかもしれない1つの小さな詳細:すべての私のデバイスは90°をとして返しましinfo.orientationた。

編集:これが のカメラ関連のコードです。NexusOneとSamsung GalaxySPlusでテストしました。これは私のヘッドトラッキング3Dアプリで使用されており、プレビューは左下隅に表示され、常に正しい向きになっているはずです。

解決策(一種):コードは正しいように見えますが、私のテスト用電話(Samsung Galaxy S Plus)はフロントカメラのCameraInfo.orientationに対して誤った値を返します。このモデルで逆さまに表示されているプレビューについては、多くの関連する議論があります(ここここの例)。修正する方法は、画像を手動で回転させるオプションを含めることです。

4

1 に答える 1

13

私がプロジェクトで使用および適用した、引用したスニペットは、私の状況では問題ありません。

テストに使用したすべてのデバイス(Galaxy Note、Galaxy S III、Galaxy Nexus、Galaxy Ace II、Nexus S)について、info.Orientationすべてフロントカメラで270、バックカメラで90を返します。

質問者と数回話し合った後、私は質問を誤解していることに気づいたので、答えを2つの部分に分けました。

カメラプレビューの向きが間違っている場合は、次の解決策を参照してください。

カメラプレビューの間違った向きの解決策:

まずinfo.Orientation、フロントカメラで270、バックカメラで90を返すことを確認してください。次に、カメラのプレビューアクティビティ(またはプレビューを処理する同様のクラス)の向きを横向きに設定してみてください。

したがって、コードを実行すると、次のことがわかります。

degree = 90画面の向き、info.Orientation = 270フロントカメラ用。次に、、が表示されます。これは、フロントカメラビューに対して時計回りに180度回転し、フロントカメラの逆さまの問題を修正することを意味しますresult = (270 - 90 + 360) % 360result = 180

カメラ写真の結果の間違った向きの解決策:

これinfo.Orientationが当てはまる場合、問題は次のようになります。

  1. 一部のSamsung(またはその他の)デバイス(Galaxy Note、Galaxy SIIIなど)の場合、カメラは実際のピクセルを回転させるのではなく、方向タグのみを書き込みます。
  2. フロントカメラを使用していて上記のコードを使用している場合、正しい向きでプレビューが表示されますが、ショットを撮ると「逆さま」の画像が表示されます。

解決:

/**
 *
 * Get the orientation from EXIF
 * @param filepath
 * @return orientation
 */
public int getExifOrientation(String filepath) {
    int degree = 0;
    ExifInterface exif = null;
    try {
        exif = new ExifInterface(filepath);
    } catch (IOException ex) {
        Log.e("EXIF info", "cannot read exif", ex);
    }
    if (exif != null) {
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
        if (orientation != -1) {
            // We only recognize a subset of orientation tag values.
            switch(orientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                degree = 90;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                degree = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                degree = 270;
                break;
            }
        }
    } else {
        degree = 1;
    }
    Log.i("EXIF info", "Orientation degrees: " + degree);
    return degree;
}

それで

if (isFromCamera) {

    if (fromFrontCam) {
        // try change here if the orientation still wrong, -90 means rotate counter-clockwise 90 degrees.
        matrix.preRotate(-90);
     } else {
        matrix.preRotate(90);
     }
} else {
    // read EXIF data
    getExifOrientation(path)
    // don't forget to handle the situation that some devices won't write exif data
    matrix.preRotate(degree);
}
于 2012-11-01T11:58:27.037 に答える