【问题标题】:Camera capture image rotate to portrait - Xamarin android相机捕获图像旋转为纵向 - Xamarin android
【发布时间】:2020-10-10 23:21:18
【问题描述】:

我有一个 xamarin.android 项目,它有一个自定义相机预览。每当我初始化相机时,它都会以横向默认打开。所以我像这样从SurfaceChanged 方法改变了方向。

private int setCameraDisplayOrientation(Activity mContext, int v)
        {
            var degrees = 0;
            var orientation =0;

            Display display = mContext.GetSystemService(Context.WindowService).JavaCast<IWindowManager>().DefaultDisplay;

            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.GetCameraInfo(v, info);
            var rotation = windowManager.DefaultDisplay.Rotation;

            DisplayMetrics dm = new DisplayMetrics();
            display.GetMetrics(dm);
            int width = dm.WidthPixels;
            int height = dm.HeightPixels;

            //Natural orientation is portrait
            if ((rotation == SurfaceOrientation.Rotation0 || rotation == SurfaceOrientation.Rotation180) && height > width ||
                (rotation == SurfaceOrientation.Rotation90 || rotation == SurfaceOrientation.Rotation270) && width > height)
            {
                switch (rotation)
                {
                    case SurfaceOrientation.Rotation0:
                        degrees = 90;
                        break;
                    case SurfaceOrientation.Rotation90:
                        degrees = 0;
                        break;
                    case SurfaceOrientation.Rotation180:
                        degrees = 270;
                        break;
                    case SurfaceOrientation.Rotation270:
                        degrees = 180;
                        break;
                }
            }
            
            return (degrees);
        }

它工作正常。它将纵向排列前后摄像头。

问题

当我拍摄照片时,在某些设备中,它会以横向模式存储在某些设备中,它会存储纵向。无论如何,我都希望图像处于纵向模式。为了做到这一点,我尝试获取图像的Exif 数据并相应地将其旋转到纵向模式。但在三星、VIVO 等某些设备中,方向值变为“0”。我不知道如何处理该值。如果我 PreRotate 90 ,那么有些设备会解决这个问题,而有些设备会向上保存照片。

**Managing Rotation**

 Android.Graphics.Bitmap loadAndResizeBitmap(string filePath)
    {

        Android.Graphics.Bitmap resizedBitmap = Android.Graphics.BitmapFactory.DecodeFile(filePath);
        ExifInterface exif = null;
        try
        {
            exif = new ExifInterface(filePath);
            string orientation = exif.GetAttribute(ExifInterface.TagOrientation);

            Android.Graphics.Matrix matrix = new Android.Graphics.Matrix();
            switch (orientation)
            {
                case "1":
                    matrix.PreRotate(-90);
                    resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
                    matrix.Dispose();
                    matrix = null;
                    break;
                case "3":
                    matrix.PreRotate(180);
                    resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
                    matrix.Dispose();
                    matrix = null;
                    break;
                case "4":
                    matrix.PreRotate(180);
                    resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
                    matrix.Dispose();
                    matrix = null;
                    break;
                case "5":
                    matrix.PreRotate(90);
                    resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
                    matrix.Dispose();
                    matrix = null;
                    break;
                case "6": // portrait
                    matrix.PreRotate(90);
                    resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
                    matrix.Dispose();
                    matrix = null;
                    break;
                case "7":
                    matrix.PreRotate(-90);
                    resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
                    matrix.Dispose();
                    matrix = null;
                    break;
                case "8":
                    matrix.PreRotate(-90);
                    resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
                    matrix.Dispose();
                    matrix = null;
                    break;
                case "0":
                    matrix.PreRotate(-90);
                    resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
                    matrix.Dispose();
                    matrix = null;
                    break;
            }

            return resizedBitmap;

        }

        catch (IOException ex)
        {
            return null;
        }

    }

我从Xamarin.Andoid Image rotation 得到这个想法。但不知何故,我无法传达它。会有什么问题?我应该传递 Stream 而不是文件路径吗?是因为surfaceview旋转吗?无论如何,如何在任何设备上制作捕获的图像肖像?任何帮助表示赞赏。

【问题讨论】:

  • 就我个人而言,我从未见过涵盖所有 Android 设备上所有相机方向问题的单一解决方案。最大的(IHO)是一些手机有旋转传感器,一些使用“自动定位”,为了避免这些问题,你必须在捕获之前检查方向并使用相机参数来旋转方向。
  • @SushiHangover 您好,感谢您的回复。你能解释一下吗?我应该使用相机方向保存图像 exif 数据吗?
  • 有很多基于 Java/Kotlin 的解决方案展示了如何正确完成此操作。我个人使用 react-native 扩展作为我的 goto 源,因为他们的开发者社区非常庞大,并且知道他们的 react-native-camera 插件可以正确处理这个问题,因为我已经借用了许多 Java 来转换为 C#,如果你搜索在该插件的问题中,您会找到对正确处理方向的代码更正的引用(当然,如果您需要 100% 的合规性,您还必须针对每个型号的手机进行特殊情况)
  • 你用的是哪个金块?
  • @Blu 你的意思是 xamarin.forms 版本?

标签: xamarin xamarin.forms xamarin.android


【解决方案1】:

仅适用于 Xamarin.Android,使用依赖服务在共享项目中调用它

由此获取图像的旋转角度。

public int GetImageRotation(string filePath)
        {
            try
            {
                ExifInterface ei = new ExifInterface(filePath);
                Orientation orientation = (Orientation)ei.GetAttributeInt(ExifInterface.TagOrientation, (int)Orientation.Undefined);
                switch (orientation)
                {
                    case Orientation.Rotate90:
                        return 90;
                    case Orientation.Rotate180:
                        return 180;
                    case Orientation.Rotate270:
                        return 270;
                    default:
                        return 0;
                }
            }
            catch(Exception ex)
            {
                return 0;
            }
        }

现在根据你得到的角度值旋转图像。

我对流而不是实际文件执行操作并以字节数组的形式返回。

public byte[] RotateImage(System.IO.Stream imageStream, string filePath)
        {
            int rotationDegrees = GetImageRotation(filePath)
            byte[] byteArray = new byte[imageStream.Length];
            try
            {
                imageStream.Read(byteArray, 0, (int)imageStream.Length);

                Bitmap originalImage = BitmapFactory.DecodeByteArray(byteArray, 0, byteArray.Length);
                Matrix matrix = new Matrix();
                matrix.PostRotate((float)rotationDegrees);

                Bitmap rotatedBitmap = Bitmap.CreateBitmap(originalImage, 0, 0, originalImage.Width,
                    originalImage.Height, matrix, true);

                using (MemoryStream ms = new MemoryStream())
                {
                    rotatedBitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, ms);
                    return ms.ToArray();
                }
            }
            catch(Exception ex)
            {
                return byteArray;
            }
        }

让我知道它是否有效。

【讨论】:

  • 好的,希望它也对你有用。 (三星 Galaxy s7、s8、s9 有问题……上面的代码修复了它)
  • 嗨,有一个疑问。我应该在“ ExifInterface ei = new ExifInterface(fileName);”中传递文件路径或文件名吗?是文件名吗?
  • 文件路径...不好意思,我下线了,你试过了吗?有没有用?
  • 嗨,我测试了你的代码。但是现在图像被保存在向左旋转 90 度。 :(
  • 这与我的表面视图旋转有什么关系吗?
猜你喜欢
  • 2021-05-11
  • 2020-02-11
  • 1970-01-01
  • 2011-11-19
  • 1970-01-01
  • 2013-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多