【问题标题】:Android : How to detect the image orientation (portrait or landscape) picked from gallery while setting on an imageview?Android:如何在设置图像视图时检测从图库中选择的图像方向(纵向或横向)?
【发布时间】:2012-09-25 11:09:54
【问题描述】:

我正在从画廊(相机相册)挑选的图像视图上设置图像。如果选择的图像是横向的,它会完美显示,但如果图像是纵向模式(即图像是在纵向模式下单击的),它会以 90 度旋转显示图像。现在我试图在设置 imageview 之前找出方向,但所有图像都给出相同的方向和相同的宽度高度。这是我的代码:

Uri selectedImage = intent.getData();
if (selectedImage != null) {
    Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImage);

    int str = new ExifInterface(selectedImage.getPath()).getAttributeInt("Orientation", 1000);
    Toast.makeText(this, "value:" + str, Toast.LENGTH_LONG).show();
    Toast.makeText(this, "width:" + bitmap.getWidth() + "height:" + bitmap.getHeight(), Toast.LENGTH_LONG).show();

【问题讨论】:

标签: android android-imageview android-gallery


【解决方案1】:

使用ExifInterface 旋转图像。使用此方法获取正确的值以从相机旋转捕获的图像。

public int getCameraPhotoOrientation(Context context, Uri imageUri, String imagePath){
    int rotate = 0;
    try {
        context.getContentResolver().notifyChange(imageUri, null);
        File imageFile = new File(imagePath);

        ExifInterface exif = new ExifInterface(imageFile.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;
        }

        Log.i("RotateImage", "Exif orientation: " + orientation);
        Log.i("RotateImage", "Rotate value: " + rotate);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return rotate;
}

并将这段代码放入Activity结果方法并获取旋转图像的值...

String selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};

Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();

int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
filePath = cursor.getString(columnIndex);
cursor.close();

int rotateImage = getCameraPhotoOrientation(MyActivity.this, selectedImage, filePath);

希望这会有所帮助..

【讨论】:

  • exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);对于任何方向图像,总是返回值 0。
  • 对不起,我犯了一个错误。你的方法对我有用。 data.getData() 返回 Uri 而不是 String,请查看您的代码。
  • @Deepak 为什么我必须打电话给context.getContentResolver().notifyChange(imageUri, null)
  • 使用上面的代码,如果你不能顺时针方向旋转图像,请在将图像设置为图像视图时添加一行imageView.setRotation(angle);这条线帮助了我。
  • 谢谢,但我可以使用相同的代码来捕获视频吗?
【解决方案2】:

这也对我有用:

String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION};
Cursor cur = getContentResolver().query(imageUri, orientationColumn, null, null, null);
int orientation = -1;
if (cur != null && cur.moveToFirst()) {
    orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0]));
}
Matrix matrix = new Matrix();
matrix.postRotate(orientation);

【讨论】:

    【解决方案3】:
                          if(bm.getWidth() > bm.getHeight())
                            {
                                Bitmap bMapRotate=null;
                                Matrix mat=new Matrix();
                                mat.postRotate(90);
                            bMapRotate = Bitmap.createBitmap(bm, 0, 0,bm.getWidth(),bm.getHeight(), mat, true);
                            bm.recycle();
                            bm=null;
                            imageDisplayView.setImageBitmap(bMapRotate);
                            }else
                            imageDisplayView.setImageBitmap(bm);
    

    【讨论】:

    • 在某些设备(如 s3 和 s4)上,即使图像是纵向的,宽度也会大于高度。这就是为什么我们不使用这个解决方案,即使它看起来很干净和完美。
    • @JesusDimrix 是的,可能是这样。但是如果图像的头部没有方向信息,那么我们可以使用这种方式。
    • 我疯了,试图让这个工作你的方式对我来说足够好,银河系什么?
    【解决方案4】:

    这是我遇到的一个很好的解决方案:>https://stackoverflow.com/a/34241250/8033090

    一线解决方案:

    Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
    

    Picasso.with(context).load("file:" + photoPath).into(imageView);
    

    这将自动检测旋转并将图像放置在正确的方向

    Picasso 是一个非常强大的库,用于在您的应用中处理图像,包括: 使用最少内存的复杂图像转换。加载可能需要一秒钟,但我只是在图像视图后面放了一些文本,上面写着“正在加载图像”,并且当图像加载时它会覆盖文本。

    【讨论】:

    • 对我不起作用。即使使用 Picasso 或 Glide,在 Galaxy S8 或 Galaxy S9 上拍摄的照片仍会旋转
    • @DenysLobur 你找到解决方案了吗?我也同意这个。银河s8有问题
    • 嘿@Peter,我想我找到了解决方案。你基本上需要实现这个android-developers.googleblog.com/2016/12/…。三星手机给出 'val rotationConstant = ExifInterface.ORIENTATION_*' 作为某个值,例如 1、3、6 等,而其他手机(在我的例子中是小米)给出 'val rotationConstant = ExifInterface.ORIENTATION_UNDEFINED' 等于 0。然后,知道旋转常数,您可以按照自己喜欢的方式旋转图像,如果不是三星手机,则可以将其旋转到 0
    【解决方案5】:

    使用 kotlin 并考虑新 android 版本中 uri 和 exif 的变化:

     var exif: ExifInterface? = null;
     try {
        when (Build.VERSION.SDK_INT) {
            in Int.MIN_VALUE..24 -> exif = ExifInterface(imageUri.path)
            else -> exif = ExifInterface(getContentResolver().openInputStream(data.extras.get("data")))
         }
     } catch (e: IOException) {
         e.printStackTrace();
     }
     val orientation = exif?.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
     bmp = rotateBitmap(bmp, orientation ?: ExifInterface.ORIENTATION_NORMAL)
    

    而rotateBitmap函数是:

    un rotateBitmap(bitmap: Bitmap, orientation: Int): Bitmap {
    val matrix = Matrix()
    when (orientation) {
        ExifInterface.ORIENTATION_NORMAL -> return bitmap
        ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> matrix.setScale(-1f, 1f)
        ExifInterface.ORIENTATION_ROTATE_180 -> matrix.setRotate(180f)
        ExifInterface.ORIENTATION_FLIP_VERTICAL -> {
            matrix.setRotate(180f)
            matrix.postScale(-1f, 1f)
        }
        ExifInterface.ORIENTATION_TRANSPOSE -> {
            matrix.setRotate(90f)
            matrix.postScale(-1f, 1f)
        }
        ExifInterface.ORIENTATION_ROTATE_90 -> matrix.setRotate(90f)
        ExifInterface.ORIENTATION_TRANSVERSE -> {
            matrix.setRotate(-90f)
            matrix.postScale(-1f, 1f)
        }
        ExifInterface.ORIENTATION_ROTATE_270 -> matrix.setRotate(-90f)
        else -> return bitmap
    }
    try {
        val bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
        bitmap.recycle()
        return bmRotated
    } catch (e: OutOfMemoryError) {
        e.printStackTrace()
        return null
    }
    

    }

    【讨论】:

    • 考虑翻转非常重要!
    【解决方案6】:

    在某些安卓设备上使用 EXIF 信息不可靠。 (ExifInterface 方向总是返回 0)

    这对我有用:

    旋转位图

    public static Bitmap rotateBitmap(Context context, Uri photoUri, Bitmap bitmap) 
    {
        int orientation = getOrientation(context, photoUri);
        if (orientation <= 0) {
            return bitmap;
        }
    
        Matrix matrix = new Matrix();
        matrix.postRotate(orientation);
        bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
        return bitmap;
    }
    

    从 MediaStore 获取方向

    private static int getOrientation(Context context, Uri photoUri) 
    {
        Cursor cursor = context.getContentResolver().query(photoUri,
                new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null);
    
        if (cursor.getCount() != 1) {
            cursor.close();
            return -1;
        }
    
        cursor.moveToFirst();
        int orientation = cursor.getInt(0);
        cursor.close();
        cursor = null;
        return orientation;
    }
    

    【讨论】:

    • 它需要 API29 :(
    【解决方案7】:

    另一种解决方案是使用支持库中的 ExifInterface: ExifInterface from support library

    【讨论】:

      【解决方案8】:

      这对我有用:

      private String getOrientation(Uri uri){
          BitmapFactory.Options options = new BitmapFactory.Options();
          options.inJustDecodeBounds = true;
          String orientation = "landscape";
          try{
              String image = new File(uri.getPath()).getAbsolutePath();
              BitmapFactory.decodeFile(image, options);
              int imageHeight = options.outHeight;
              int imageWidth = options.outWidth;
              if (imageHeight > imageWidth){
                  orientation = "portrait";
              }
          }catch (Exception e){
              //Do nothing
          }
          return orientation;
      }
      

      【讨论】:

      • 在某些设备(如 s3 和 s4)上,即使图像是纵向的,宽度也会大于高度。这就是为什么我们不使用这个解决方案,即使它看起来很干净和完美。
      • 使用 enum 或 int 结果会更好看:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多