在 activity 上旋转从图库中选择的图像,结果在 android 上旋转

Get rotation of an image selected from the gallery on activity result on android

这个问题似乎经常出现,我已经阅读了很多关于这个主题的文章是错误的,所以我想阅读并更正它,所以它总是纵向的, 我已经实现了用于启动相机、拍照和检查 Exif 数据以确保其始终为纵向的方法,但这似乎不适用于 selecting 画廊的图像,我的旋转变量将总是 return 0

 ExifInterface exifInterface = new ExifInterface(imgFile.getAbsolutePath());
 int rotation =
        exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
        ExifInterface.ORIENTATION_NORMAL);
        int rotationInDegrees = exifToDegrees(rotation);
        System.out.println(rotation);
        Matrix matrix = new Matrix();

        if (rotation != 0f) {

            matrix.preRotate(rotationInDegrees);
            Bitmap bitmap2 = Bitmap.createBitmap(bitmap, 0,
            0, bitmap.getWidth(), bitmap.getHeight(),
            matrix,false);
            imgView.setImageBitmap(bitmap2);
            path = saveToInternalStorage(imageFileName,bitmap2,getApplicationContext());
            }
            else
            path = saveToInternalStorage(imageFileName,bitmap,getApplicationContext());
            }
            catch (IOException e) {
            e.printStackTrace();
    }

ExifToDegrees 方法

    private static int exifToDegrees(int exifOrientation) {
    if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
        return 90;
    }
    else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
        return 180; }
    else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
        return 270; }
    else if (exifOrientation == 6) {
        return 90; }
    else if (exifOrientation == 3) {
        return 180; }
    else if (exifOrientation == 8) {
        return 270; }
    return 0;
}

如前所述,我已经阅读了很多相关内容,有人说这是 android 的错误,有人说这是新的最近的文件选择器,我们应该使用

    getAbsolutePath() 

并检查每个 SDK 版本并首先保存图像,我完成所有这些并不愉快有人说我们根本不需要使用 Exif

  MediaStore.Images.ImageColumns.ORIENTATION 

应该可以,但还是不行。

我的目标设备是从 ICS 到 M(我拥有我需要授予的所有权限)我正在将图像保存到我的文件夹

  File directory = cw.getDir("SimpleAAC", Context.MODE_PRIVATE);

并将路径保存在数据库中,我从该文件夹加载图像,使用我数据库中的路径并使用通用图像加载器, 在征得许可后,我用这个

启动了画廊
 Intent intent = new Intent();
                    intent.setType("image/*");
                    intent.setAction(intent.ACTION_GET_CONTENT);
                    startActivityForResult(Intent.createChooser(intent, 
                    "Select A Picture"), PICK_IMAGE_REQUEST);
                    dialog.dismiss();

这是我的画廊 onActivityResult 代码

 if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data !=  
 null && data.getData() != null) {

        Uri uri = data.getData();

            BitmapFactory.Options bitmapOptions = new   
            BitmapFactory.Options();
            bitmapOptions.inSampleSize = 4;
            InputStream inputStream = null;
        try {
            inputStream = getContentResolver().openInputStream(uri);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
            Bitmap scaledBitmap = BitmapFactory.decodeStream(inputStream, 
            null, bitmapOptions);
            String timeStamp = new 
            SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            String imageFileName = timeStamp + ".jpg";

        ContextWrapper cw = new ContextWrapper(getApplicationContext());
        File directory = cw.getDir("SimpleAAC", Context.MODE_PRIVATE);
        File mypath = new File(directory,imageFileName);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(mypath);
            scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //the relevant parts of this method(setThumbNailImageAndSave ) are 
        //  included above      


        finalPath = setThumbnailImageAndSave(imageView,mypath);
        ImageLoader imageLoader = ImageLoader.getInstance();
        DisplayImageOptions options = new  
        DisplayImageOptions.Builder().cacheInMemory(true)
                .cacheOnDisc(true).resetViewBeforeLoading(true)
                .showImageForEmptyUri(R.drawable.ic_insert_photo_black_24dp)
                .showImageOnFail(R.drawable.ic_insert_photo_black_24dp)
        .showImageOnLoading(R.drawable.ic_insert_photo_black_24dp).build();

        imageLoader.displayImage(finalPath, imageView, options);
        System.out.println(finalPath);
    }

所以为了结束这个问题,我正在寻求澄清,这是一个错误吗?我可以使用 MediaStore.Images.ImageColumns.ORIENTATION 来解决这个问题吗?如果可以,如何解决?是 intent.setAction(intent.ACTION_GET_CONTENT) 吗?是 post kitkat 文件更改了吗?

老实说,我已经阅读了很多关于此的相互矛盾的信息,但我似乎没有尝试任何工作,感谢所有回复

is this a bug?

在你的代码中?可能吧。目前尚不清楚第一个代码片段中的 imgFile 与最后一个代码片段的关系。但是在最后一个代码片段中,您通过解码位图然后对其进行编码来剥离所有 EXIF headers。如果这是您在第一个代码片段中通过 ExifInterface 检查的文件,那就是您的问题。

can i get around this using MediaStore.Images.ImageColumns.ORIENTATION and if so how?

否,因为您的图像可能不是来自 MediaStore

相反,给定您的 uri,在 ContentResolver 上调用 openInputStream()。然后,将 openInputStream() 传递给 a better ExifInterface, one that can read from streams rather than requiring a file. This sample app 演示了该过程,包括拥有更好的 ExifInterface 代码的副本,尽管我碰巧使用了资产中的 InputStream 而不是来自ContentResolver.

如果您出于其他原因想要制作图像的本地副本,请删除最后一个代码片段中的 decode-and-encode 位图逻辑。相反,openInputStream() 和那个 uri,在你想要的文件上打开一个 FileOutputStream,然后使用正常的 Java I/O 复制字节。这将使 EXIF headers 保持完整。

此外,无论哪种情况,请在后台线程上完成所有这些 Uri 工作。