使用Intent MediaStore.ACTION_IMAGE_CAPTURE拍摄照片后,如何找到图片的方向?

21

使用安卓相机应用拍照时,它会检测手机的方向并据此保存照片。因此,如果我拍摄一幢建筑的照片,无论我是竖屏还是横屏拍摄,屋顶都会在顶部。

但是,当我使用

Intent imageCaptureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

在获取图片时,相机应用程序不会响应方向。

如果我将手机竖直(纵向)握持,拍摄的照片将被旋转,建筑物的屋顶位于屏幕左侧。

如何设置意图以使相机考虑方向?

或者我可以通过某种方式推断出拍摄照片时的方向并自行旋转它吗?

还是有其他方法吗?


在这里..https://dev59.com/92w15IYBdhLWcg3wIYK_#7411824 - Fattie
如果ExifInterface对您无效,请阅读我的解决方案。 http://stackoverflow.com/a/24969432/513413 - Hesam
4个回答

27

我找到了答案。这张图片的 Exif 中有方向指示器。如果需要,在Android中可以像这样查看Exif:

ExifInterface exif = new ExifInterface("filepath");  
exif.getAttribute(ExifInterface.TAG_ORIENTATION);

1
仅适用于API Level 10及以上版本...我正在使用此方法,但希望有一种可以在较低API版本上运行的方法。 - Andrew Mackenzie
4
对我来说,所有的方向相关内容看起来都像API Level 5:http://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION 这是Android 2.0版本:http://developer.android.com/guide/appendix/api-levels.html 但我在2.1 / Api level 7上成功地使用了它。 - Stan Kurdziel
1
我已经在我们的应用程序中实现了这个功能,用于处理图像问题。这是一个非常好的功能,可以在开发应用程序时显示和管理图像方向。 - Manoj Kumar
HTC Wildfire S,Android 2.3.6中没有我的exif信息 :( - Andras Balázs Lajtha

11
从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;
}

11
IMAGE_PROVIDER_URI是什么常量?谢谢。 - valerybodak
缺少IMAGE_PROVIDER_URI。 - gts13
1
为什么它告诉我MediaStore.Images.ImageColumns.ORIENTATION字段需要Api级别Q?我以前使用这个字段没有任何问题。 - TatiOverflow

4

快速解决方法是,检查图像的宽度是否大于图像的高度。如果宽度大于高度,则表示该图像为横向图像,您可以将其更改为竖向图像。

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;
}

2

我使用了一个文件提供程序,除了制作临时副本并从中读取数据外,什么都没有起作用。

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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接