web-dev-qa-db-ja.com

Androidポートレートを撮影したときにカメラの意図が画像の風景を保存する

私は見て回ったが、非常にいらいらする問題に対する確かな答え/解決策はないようだ。

私は縦向きで写真を撮り、保存/破棄を押すと、ボタンも正しい向きになります。問題は、後で画像を取得するときに横向きになっている場合です(写真は反時計回りに90度回転しています)

特定の向きでカメラを使用するようにユーザーに強制する必要はありません。

写真がポートレートモードで撮影されたかどうかを検出し、ビットマップをデコードして正しい方向に反転させる方法はありますか?

37
StuStirling

写真は常にカメラがデバイスに組み込まれている向きで撮影されます。画像を正しく回転させるには、画像に保存されている方向情報(EXIFメタデータ)を読み取る必要があります。そこには、画像が撮影されたときのデバイスの向きが保存されます。

EXIFデータを読み取り、それに応じて画像を回転させるコードを次に示します。fileは画像ファイルの名前です。

BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file, bounds);

BitmapFactory.Options opts = new BitmapFactory.Options();
Bitmap bm = BitmapFactory.decodeFile(file, opts);
ExifInterface exif = new ExifInterface(file);
String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int orientation = orientString != null ? Integer.parseInt(orientString) :  ExifInterface.ORIENTATION_NORMAL;

int rotationAngle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) rotationAngle = 90;
if (orientation == ExifInterface.ORIENTATION_ROTATE_180) rotationAngle = 180;
if (orientation == ExifInterface.ORIENTATION_ROTATE_270) rotationAngle = 270;

Matrix matrix = new Matrix();
matrix.setRotate(rotationAngle, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
Bitmap rotatedBitmap = Bitmap.createBitmap(bm, 0, 0, bounds.outWidth, bounds.outHeight, matrix, true);

2017-01-16更新

25.1.0サポートライブラリのリリースに伴い、ExifInterfaceサポートライブラリが導入されました。これにより、おそらくExif属性へのアクセスが容易になるはずです。 Android Developer's Blog をご覧ください。

87
Ridcully

選択された回答は、この質問および同様の質問に答えられる最も一般的な方法を使用します。ただし、Samsungの前面カメラと背面カメラの両方では機能しませんでした。 Samsungやその他の主要メーカーのフロントカメラとバックカメラの両方で機能する別のソリューションが必要な場合、nvhausidによるこの回答は素晴らしいものです。

https://stackoverflow.com/a/18915443/6080472

クリックスルーしたくない人にとって、関連する魔法は、メディアファイル上でEXIFまたはカーソルに依存するのではなく、CameraInfoを使用することです。

Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
Android.hardware.Camera.CameraInfo info = new Android.hardware.Camera.CameraInfo();
Android.hardware.Camera.getCameraInfo(mCurrentCameraId, info);
Bitmap bitmap = rotate(realImage, info.orientation);

リンク内の完全なコード。

1
D. Scott