我正在捕捉图像并将其设置为图像视图。

public void captureImage() {

    Intent intentCamera = new Intent("android.media.action.IMAGE_CAPTURE");
    File filePhoto = new File(Environment.getExternalStorageDirectory(), "Pic.jpg");
    imageUri = Uri.fromFile(filePhoto);
    MyApplicationGlobal.imageUri = imageUri.getPath();
    intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
    startActivityForResult(intentCamera, TAKE_PICTURE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intentFromCamera) {
    super.onActivityResult(requestCode, resultCode, intentFromCamera);

    if (resultCode == RESULT_OK && requestCode == TAKE_PICTURE) {

        if (intentFromCamera != null) {
            Bundle extras = intentFromCamera.getExtras();
            if (extras.containsKey("data")) {
                bitmap = (Bitmap) extras.get("data");
            }
            else {
                bitmap = getBitmapFromUri();
            }
        }
        else {
            bitmap = getBitmapFromUri();
        }
        // imageView.setImageBitmap(bitmap);
        imageView.setImageURI(imageUri);
    }
    else {
    }
}

public Bitmap getBitmapFromUri() {

    getContentResolver().notifyChange(imageUri, null);
    ContentResolver cr = getContentResolver();
    Bitmap bitmap;

    try {
        bitmap = android.provider.MediaStore.Images.Media.getBitmap(cr, imageUri);
        return bitmap;
    }
    catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

但问题是,某些设备上的图像每次旋转时。例如,在三星设备上,它工作得很好,但在索尼Xperia上,图像旋转了90度,在东芝Thrive(平板电脑)上旋转了180度。


当前回答

可悲的是,上面的@jason-robinson回答对我没用。

虽然旋转函数工作得很完美:

public static Bitmap rotateImage(Bitmap source, float angle) {
    Matrix matrix = new Matrix();
    matrix.postRotate(angle);
    return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix,
            true);
}

我必须做以下事情来获得方向,因为Exif方向总是0

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode,resultCode,data);
    if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && data != null) {
            Uri selectedImage = data.getData();
            String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION};
            Cursor cur = managedQuery(imageUri, orientationColumn, null, null, null);
            int orientation = -1;
            if (cur != null && cur.moveToFirst()) {
                    orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0]));
            }
            InputStream imageStream = getContentResolver().openInputStream(selectedImage);
            Bitmap bitmap = BitmapFactory.decodeStream(imageStream);
            switch(orientation) {
                    case 90:
                            bitmap = rotateImage(chosen_image_bitmap, 90);
                            break;
                    case 180:
                            bitmap = rotateImage(chosen_image_bitmap, 180);
                            break;
                    case 270:
                            bitmap = rotateImage(chosen_image_bitmap, 270);
                            break;
                    default:
                            break;
            }
            imageView.setImageBitmap(bitmap );

其他回答

在没有使用ExifInterface的情况下得到了这个问题的答案。我们可以得到相机的旋转不管是前置相机还是后置相机无论你使用的是哪一个然后在创建位图时我们可以使用matrix。postrotate (degree)来旋转位图

public int getRotationDegree() {
    int degree = 0;

    for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(i, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            degree = info.orientation;

            return degree;
        }
    }

    return degree;
}

计算旋转后,你可以像下面这样旋转你的位图:

 Matrix matrix = new Matrix();

 matrix.postRotate(getRotationDegree());

 Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);

这里的bm应该是位图。

如果你想知道前置摄像头的旋转,只需更改camera . camerainfo。CAMERA_FACING_BACK to Camera.CameraInfo。CAMERA_FACING_FRONT以上。

我希望这能有所帮助。

如果有人在Android 4.4 (KitKat)上使用ExifInterface获得方向时遇到问题,这可能是因为从URI获得了错误的路径。在堆栈溢出问题中看到一个解决方案,从URI获得真正的路径,Android奇巧新的存储访问框架

通常建议使用ExifInterface解决问题,就像@Jason Robinson所建议的那样。如果这种方法不起作用,你可以试着查找最新拍摄的图像的方向…

private int getImageOrientation(){
    final String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.ImageColumns.ORIENTATION };
    final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
    Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            imageColumns, null, null, imageOrderBy);

    if(cursor.moveToFirst()){
        int orientation = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION));
        cursor.close();
        return orientation;
    } else {
        return 0;
    }
}

这可能是不言而喻的,但请始终记住,您可以在服务器上处理其中一些映像处理问题。我使用类似于这个线程中包含的响应来处理图像的即时显示。然而,我的应用程序要求图像存储在服务器上(这可能是一个常见的要求,如果你希望图像在用户切换手机时保持不变)。

关于这个主题的许多讨论中包含的解决方案没有讨论EXIF数据缺乏持久性的问题,这种数据无法在位图的图像压缩中幸存下来,这意味着您需要在服务器每次加载图像时旋转图像。或者,您可以将EXIF方向数据发送到服务器,然后根据需要旋转图像。

对我来说,在服务器上创建一个永久的解决方案更容易,因为我不必担心Android的秘密文件路径。

首先,你应该知道,自Android 7.0以来,我们必须使用FileProvider和ContentUri,否则你会得到一个烦人的错误,试图调用你的意图。这是示例代码:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getUriFromPath(context, "[Your path to save image]"));
startActivityForResult(intent, CAPTURE_IMAGE_RESULT);

方法getUriFromPath(Context, String)基于用户版本的Android创建FileUri (file://…)或ContentUri (content://…)

public Uri getUriFromPath(Context context, String destination) {
    File file =  new File(destination);

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
        return FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file);
    } else {
        return Uri.fromFile(file);
    }
}

onActivityResult后,你可以捕捉图像被相机保存的uri,但现在你必须检测相机旋转,这里我们将使用修改后的@Jason Robinson回答:

首先,我们需要基于Uri创建ExifInterface

@Nullable
public ExifInterface getExifInterface(Context context, Uri uri) {
    try {
        String path = uri.toString();
        if (path.startsWith("file://")) {
            return new ExifInterface(path);
        }
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            if (path.startsWith("content://")) {
                InputStream inputStream = context.getContentResolver().openInputStream(uri);
                return new ExifInterface(inputStream);
            }
        }
    }
    catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

上面的代码可以简化,但我想显示一切。因此,从FileUri我们可以创建基于字符串路径的ExifInterface,但从ContentUri我们不能,Android不支持。

在这种情况下,我们必须使用基于InputStream的其他构造函数。记住这个构造函数默认是不可用的,你必须添加额外的库:

compile "com.android.support:exifinterface:XX.X.X"

现在我们可以使用getExifInterface方法来获取我们的角度:

public float getExifAngle(Context context, Uri uri) {
    try {
        ExifInterface exifInterface = getExifInterface(context, uri);
        if(exifInterface == null) {
            return -1f;
        }

        int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_UNDEFINED);

        switch (orientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                return 90f;
            case ExifInterface.ORIENTATION_ROTATE_180:
                return 180f;
            case ExifInterface.ORIENTATION_ROTATE_270:
                return 270f;
            case ExifInterface.ORIENTATION_NORMAL:
                return 0f;
            case ExifInterface.ORIENTATION_UNDEFINED:
                return -1f;
            default:
                return -1f;
        }
    }
    catch (Exception e) {
        e.printStackTrace();
        return -1f;
    }
}

现在你有角度适当旋转你的图像。