Android获取相机位图的方向?并向后旋转-90度

lac*_*cas 55 android

我有这个代码:

//choosed a picture
public void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (resultCode == RESULT_OK) {
        if (requestCode == ImageHelper.SELECT_PICTURE) {

            String picture           = "";

            Uri selectedImageUri     = data.getData();
            //OI FILE Manager
            String filemanagerstring = selectedImageUri.getPath();
            //MEDIA GALLERY
            String selectedImagePath = ImageHelper.getPath(mycontext, selectedImageUri);

            picture=(selectedImagePath!=null)?selectedImagePath:filemanagerstring;
Run Code Online (Sandbox Code Playgroud)

...

这只是一个图片选择器,来自画廊.这很不错,但是当我在一个imageview上打开这张照片时,带有相机的"PORTRAIT MODE"的图像看起来不错,但带有相机的"LANDSCAPE MODE"的图像在-90度开启.

我怎样才能将这些照片旋转回去?

    Bitmap output       = Bitmap.createBitmap(newwidth, newheight, Config.ARGB_8888);
    Canvas canvas       = new Canvas(output);
Run Code Online (Sandbox Code Playgroud)

我试过这个:

Log.e("w h", bitmap.getWidth()+" "+bitmap.getHeight());
if (bitmap.getWidth()<bitmap.getHeight()) canvas.rotate(-90);
Run Code Online (Sandbox Code Playgroud)

但这不起作用,所有图像大小为:*2560 1920像素(PORTRAIT和LANDSCAPE模式全部)

如何旋转LANDSCAPE图片?

谢谢莱斯利

Gun*_*son 219

如果使用数码相机或智能手机拍摄照片,则旋转通常存储在照片的Exif数据中,作为图像文件的一部分.您可以使用Android阅读图像的Exif元数据ExifInterface.

首先,创建ExifInterface:

ExifInterface exif = new ExifInterface(uri.getPath());
Run Code Online (Sandbox Code Playgroud)

接下来,找到当前的轮换:

int rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);  
Run Code Online (Sandbox Code Playgroud)

将exif旋转转换为度数:

int rotationInDegrees = exifToDegrees(rotation);
Run Code Online (Sandbox Code Playgroud)

哪里

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; }            
    return 0;    
 }
Run Code Online (Sandbox Code Playgroud)

然后使用图像的实际旋转作为参考点,使用a旋转图像Matrix.

Matrix matrix = new Matrix();
if (rotation != 0) {matrix.preRotate(rotationInDegrees);}
Run Code Online (Sandbox Code Playgroud)

您可以使用Bitmap.createBitmap以a Matrix为参数的方法创建新的旋转图像:

Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
Run Code Online (Sandbox Code Playgroud)

在哪里Matrix m举行新的轮换:

Bitmap adjustedBitmap = Bitmap.createBitmap(sourceBitmap, 0, 0, width, height, matrix, true);
Run Code Online (Sandbox Code Playgroud)

有关有用的源代码示例,请参阅本教程:

  • 谢谢你这么彻底的答复! (2认同)
  • @GunnarKarlsson我希望我能给你更多的投票! (2认同)
  • 它不适用于content:// uri (2认同)
  • 我收到一条错误消息,指出它不是文档E / JHEAD:无法打开'/ document / image:82297' (2认同)
  • 好答案,谢谢。@JamesTan如果出现FILE NOT FOUND异常,请使用“ private String getPath(Uri uri){String [] data = {MediaStore.Images.Media.DATA}; CursorLoader loader = new CursorLoader(this,uri,data,null,null ,null);游标cursor = loader.loadInBackground(); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst();返回cursor.getString(column_index);}“ (2认同)

Ege*_*glu 6

如果您使用Jetpack CameraX, 内部onImageCaptured方法,您可以访问由如下EXIF数据提供的旋转度数:imageProxy

image.imageInfo.rotationDegrees
Run Code Online (Sandbox Code Playgroud)

然后在设置图像时,您可以根据这个角度旋转图像


San*_*ias 5

最后一个答案在技术上是完美的,但我努力创建一个系统来管理图片、旋转、调整大小、缓存和加载到 ImageViews 中,我可以说这是一个地狱。即使完成了所有操作,它有时也会在某些设备中导致 OutOfMemory 崩溃。

我的观点是不要重新发明轮子,它有一个完美的设计。Google 本身鼓励您使用Glide。它在一行中工作,超级易于使用,体积和功能数量轻巧,默认情况下管理 EXIF,并且像魅力一样使用内存..它只是黑魔法编码;)

我不确定毕加索是否也管理 EXIF,但有一个对它们的快速介绍:

https://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en

我的建议:不要浪费你的时间并使用它们。您可以在一行中解决您的问题:

Glide.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
Run Code Online (Sandbox Code Playgroud)

  • 是的,但问题是,如果您已经解码/下采样了一点,例如或使用 jpeg 格式压缩。EXIF 不会保留,因此您需要将属性重置为新文件。 (4认同)