【问题标题】:Get rotation of an image selected from the gallery on activity result on android在android上的活动结果中获取从图库中选择的图像的旋转
【发布时间】:2016-11-21 19:34:03
【问题描述】:

这个问题似乎经常出现,我已经阅读了很多关于这个主题的内容我的问题是当我从图库中选择一张图片并将其传递给活动结果时,方向是错误的,所以我想阅读它并且纠正它,使它始终是肖像, 我已经实现了用于启动相机、拍照和检查 Exif 数据以确保其始终为纵向的方法,但这似乎不适用于为画廊选择图像,我的旋转变量将始终返回 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)吗?是kitkat后文件更改吗?

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

【问题讨论】:

  • 你为什么不直接测量宽度和高度。如果宽度大于高度,您可以假设它是横向的。
  • 去过那里,我的朋友感谢您的回复,这不适用于很多设备,但绝对是计划 b @Eugene H
  • @nightcoder 有很多设备,这种方法不适用于我发现的最佳方法是将字节复制到文件然后您可以完全访问所有数据

标签: android image android-intent exif image-rotation


【解决方案1】:

这是一个错误吗?

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

我可以使用 MediaStore.Images.ImageColumns.ORIENTATION 解决这个问题吗?如果可以,如何解决?

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

相反,鉴于您的uri,请在ContentResolver 上致电openInputStream()。然后,将openInputStream() 传递给a better ExifInterface,它可以从流中读取而不需要文件。 This sample app 演示了该过程,包括拥有更好的 ExifInterface 代码的副本,尽管我碰巧使用资产中的 InputStream 而不是 ContentResolver

如果您出于其他原因想要制作图像的本地副本,请去掉最后一个代码 sn-p 中的位图逻辑解码和编码。相反,openInputStream()uri,在所需文件上打开 FileOutputStream,并使用普通 Java I/O 复制字节。这将保持 EXIF 标头完好无损。

另外,在任何一种情况下,请在后台线程上完成所有 Uri 工作。

【讨论】:

  • 天才,非常感谢你,我已经阅读了很多你提到的内容,例如在解码位图时丢失了 exif 信息,我会在早上继续,再次感谢
  • 也许现在我可以阻止所有这些恶作剧了?
  • 或者也许自从你的帖子检查了你的演示项目和你的许多其他帖子之后我就没有读过,老实说我根本不明白,你所说的从输出流中复制字节归档也超出了我的范围
  • 完成!!!再次感谢@CommonsWare 使用了将字节复制到文件的方法,它现在可以正常工作了,非常感谢您
猜你喜欢
  • 2015-11-02
  • 1970-01-01
  • 2014-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多