Androidのカメラアプリで写真を撮ると、携帯電話の向きが検出され、それに応じて写真が保存されます。そのため、建物の写真を撮ると、携帯電話を横向きでも縦向きでも、屋根が上面になります。
しかし、私が使用するとき
Intent imageCaptureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
写真を撮るために、カメラアプリは向きに反応しません。電話を縦に持っていると(ポートレート)、結果の画像が回転し、建物の屋根が画面の左側になります。
カメラが向きを考慮に入れるようにインテントを設定するにはどうすればよいですか?
または、写真がどの方向に撮影されたかを何らかの方法で推測し、後で自分で回転させることはできますか?
または別の方法はありますか?
私は答えを見つけました。画像の Exif には、向きのインジケーターがあります。念のため、ExifはAndroid次のように表示できます:
ExifInterface exif = new ExifInterface("filepath");
exif.getAttribute(ExifInterface.TAG_ORIENTATION);
可能な場合はExifから読み取り、それ以外の場合はMediaStoreから読み取ります
public static int getImageOrientation(Context context, String imagePath) {
int orientation = getOrientationFromExif(imagePath);
if(orientation <= 0) {
orientation = getOrientationFromMediaStore(context, imagePath);
}
return orientation;
}
private static int getOrientationFromExif(String imagePath) {
int orientation = -1;
try {
ExifInterface exif = new ExifInterface(imagePath);
int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (exifOrientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
orientation = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
orientation = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
orientation = 90;
break;
case ExifInterface.ORIENTATION_NORMAL:
orientation = 0;
break;
default:
break;
}
} catch (IOException e) {
Log.e(LOG_TAG, "Unable to get image exif orientation", e);
}
return orientation;
}
private static int getOrientationFromMediaStore(Context context, String imagePath) {
Uri imageUri = getImageContentUri(context, imagePath);
if(imageUri == null) {
return -1;
}
String[] projection = {MediaStore.Images.ImageColumns.ORIENTATION};
Cursor cursor = context.getContentResolver().query(imageUri, projection, null, null, null);
int orientation = -1;
if (cursor != null && cursor.moveToFirst()) {
orientation = cursor.getInt(0);
cursor.close();
}
return orientation;
}
private static Uri getImageContentUri(Context context, String imagePath) {
String[] projection = new String[] {MediaStore.Images.Media._ID};
String selection = MediaStore.Images.Media.DATA + "=? ";
String[] selectionArgs = new String[] {imagePath};
Cursor cursor = context.getContentResolver().query(IMAGE_PROVIDER_URI, projection,
selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
int imageId = cursor.getInt(0);
cursor.close();
return Uri.withAppendedPath(IMAGE_PROVIDER_URI, Integer.toString(imageId));
}
if (new File(imagePath).exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, imagePath);
return context.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}
return null;
}
簡単に修正するには、画像の幅が画像の高さよりも大きいかどうかを確認できます。それはそれが風景であることを意味し、あなたはそれを肖像画に変えることができます。
private Bitmap fromGallery(final Uri selectedImageUri) {
try {
Bitmap bm = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImageUri);
ExifInterface exif = new ExifInterface(selectedImageUri.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int angle = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
angle = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
angle = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
angle = 270;
break;
default:
angle = 0;
break;
}
Matrix mat = new Matrix();
if (angle == 0 && bm.getWidth() > bm.getHeight())
mat.postRotate(90);
else
mat.postRotate(angle);
return Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), mat, true);
}
catch (IOException e) {
Log.e("", "-- Error in setting image");
}
catch (OutOfMemoryError oom) {
Log.e("", "-- OOM Error in setting image");
}
return null;
}
私はファイルプロバイダーを使用しましたが、一時的なコピーを作成してそこからデータを読み取る以外は何も機能しませんでした。
public static int getOrientation(Context context, Uri uri) {
int rotate = 0;
try {
ParcelFileDescriptor parcelFileDescriptor =
context.getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
FileInputStream input = new FileInputStream(fileDescriptor);
File tempFile = File.createTempFile("exif", "tmp");
String tempFilename = tempFile.getPath();
FileOutputStream output = new FileOutputStream(tempFile.getPath());
int read;
byte[] bytes = new byte[4096];
while ((read = input.read(bytes)) != -1) {
output.write(bytes, 0, read);
}
input.close();
output.close();
ExifInterface exif = new ExifInterface(tempFile.getAbsolutePath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
} catch (Exception e) {
Log.i(TAG, e.getLocalizedMessage());
}
return rotate;
}
ボーナス回転機能
public static Bitmap rotateImage(Context context, Uri uri, int orientation) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
context.getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
if (orientation > 0) {
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
return bitmap;
}