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

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度。


当前回答

最好试着以特定的方向照相。

android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden"

为了获得最好的结果,在cameraview活动中给出景观方向。

其他回答

首先,你应该知道,自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;
    }
}

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

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

通过使用滑动库,你可以得到图像与精确的方向,而不需要检查旋转

在kotlin

CoroutineScope(Dispatchers.IO).launch {
         var bitmap = Glide.with(context).asBitmap().load(imagePathOrUriOrLink)
                /*.apply(
                    RequestOptions()
                        .override(MAXIMUM_IMAGE_RESOLUTION)
                )*/ //uncomment it if you want original image
                /*.diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true)*/ //uncomment it you want to not cache image
                .submit().get()//this is synchronous approach  
}

使用这个依赖

api 'com.github.bumptech.glide:glide:4.12.0'
kapt 'com.github.bumptech.glide:compiler:4.12.0'

可悲的是,上面的@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 );

这里的解决方案基于上面的解决方案,但只需要上下文和图像文件作为输入

public static Bitmap rectifyImage(Context context,File imageFile){
    Bitmap originalBitmap= BitmapFactory.decodeFile(imageFile.getAbsolutePath());
    try{
        Uri uri=Uri.fromFile(imageFile);
        InputStream input = context.getContentResolver().openInputStream(uri);
        ExifInterface ei;
        
        if (Build.VERSION.SDK_INT > 23)
            ei = new ExifInterface(input);
        else
            ei = new ExifInterface(uri.getPath());

        int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
        switch (orientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                return rotateImage(originalBitmap, 90);
            case ExifInterface.ORIENTATION_ROTATE_180:
                return rotateImage(originalBitmap, 180);
            case ExifInterface.ORIENTATION_ROTATE_270:
                return rotateImage(originalBitmap, 270);
            default:
                return originalBitmap;
        }
    }catch (Exception e){
        return originalBitmap;
    }
}

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