Xamarin.Forms Xam.Plugin.Media在iOS上拍照

时间:2018-07-05 21:15:21

标签: ios plugins xamarin.forms

我在Forms应用程序中使用Xam.Plugin.Media拍照。 我将图像流(GetStream)转换为byte []并存储在数据库中。 然后,我将其用作图像源。 在Android和UWP上,其工作正常。 在iOS上,如果以人像模式拍摄照片,则所选的图像始终旋转90度。 稍后,我将其上传到服务器,该图像可以在其他设备上使用。 为此,我还尝试了GetStreamWithImageRotatedForExternalStorage,但在这种情况下,我根本看不到该图像。 流中有字节(我的DisplayAlert长度),但是图像不显示。

知道我可能在做什么错吗?

我的代码:-

private async Task TakePicture(WineDetails details)
{
    await CrossMedia.Current.Initialize();

    if (CrossMedia.Current.IsCameraAvailable && CrossMedia.Current.IsTakePhotoSupported)
    {
        var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
        {
            AllowCropping = true,
            PhotoSize = Plugin.Media.Abstractions.PhotoSize.Medium,
            SaveToAlbum = false,
            RotateImage = true                    
        });

        if (file == null)
            return;

        using (var ms = new MemoryStream())
        {
            var stream = file.GetStreamWithImageRotatedForExternalStorage();

            stream.CopyTo(ms);
            details.LabelImage = ms.ToArray();

            details.NotifyChange("ImageSource");
        }
    }
}

图像通过NotifyChange在页面中更新,看起来像这样: ImageSource.FromStream(()=>新的MemoryStream(this.LabelImage))

这在Android和UWP上的所有情况下均能正常工作,在iOS上使用GetStream可以正常工作(除非图像旋转不正确),但在iOS上不能使用GetStreamWithImageRotatedForExternalStorage来工作。

还有其他人使用此插件吗? 知道为什么GetStream返回旋转的图像吗? 知道为什么GetStreamWithImageRotatedForExternalStorage无法正常工作吗?

谢谢

更新:-

Changed SaveToAlbum = true,当我打开图库时,图像旋转了90度。 RotateImage = true会导致问题吗?我将尝试将其设置为false。 我仍然无法使用GetStreamWithImageRotatedForExternalStorage将图像源设置为图像的字节数组。

using (var ms = new MemoryStream())
{                    
     file.GetStreamWithImageRotatedForExternalStorage().CopyTo(ms);
     details.LabelImage = ms.ToArray();
}

使用字节数组获取图像

return ImageSource.FromStream(() => new MemoryStream(this.LabelImage));

这对我不起作用,GetStream可以正常工作。

更新:-

好的,RotateImage = false + GetStreamWithImageRotatedForExternalStorage允许我显示图像,但是在我的应用程序和图库中图像仍未正确旋转。

2 个答案:

答案 0 :(得分:2)

我正在使用this插件,该插件是相似的(如果不是同一件事-我知道James Montemagno最近将他的作品与Xamarin打包/捆绑在一起)。

如果您查看那里的问题面板,您会发现很多人遇到类似的问题(iOS上的图像旋转)。几乎每个“解决方案”都使用GetStreamWithImageRotatedForExternalStorage提及。

我的问题很相似-我无法在iOS模式下以人像模式拍摄照片,而没有其他(非iOS设备)旋转图像。我已经尝试了数周的时间来解决此问题,但是对插件的支持似乎非常有限。


最终,我不得不使用巨大解决方法来解决此问题-使用自FFImageLoading扩展的自定义渲染器来显示我们的图像和MetadataExtractor。然后,我们能够从流中提取EXIF数据,并将旋转变换应用于FFImageLoding图像控件。

旋转信息以一种奇怪的方式存储为字符串。这是我用来提取旋转信息,并以整数形式返回需要旋转的量的方法。请注意,对我而言,iOS能够正确正确显示图像,因此它仅返回Android设备的旋转更改。

    public static int GetImageRotationCorrection(byte[] image)
    {
        try
        {
            var directories = ImageMetadataReader.ReadMetadata(new MemoryStream(image));
            if (Device.Android == "Android")
            {
                foreach (var directory in directories)
                {
                    foreach (var tag in directory.Tags)
                    {
                        if (tag.Name == "Orientation")
                        {
                            if (tag.Description == "Top, left side(Horizontal / normal)")
                                return 0;
                            else if (tag.Description == "Left side, bottom (Rotate 270 CW)")
                                return 270;
                            else if (tag.Description == "Right side, top (Rotate 90 CW")
                                return 90;
                        }
                    }
                }
            }

            return 0;
        }
        catch (Exception ex)
        {
            return 0;
        }
    }

请注意,还有用于FFImage加载的图像的自定义渲染器。

public class RotatedImage : CachedImage
{
    public static BindableProperty MyRotationProperty = BindableProperty.Create(nameof(MyRotation), typeof(int), typeof(RotatedImage), 0, propertyChanged: UpdateRotation);

    public int MyRotation
    {
        get { return (int)GetValue(MyRotationProperty); }
        set { SetValue(MyRotationProperty, value); }
    }

    private static void UpdateRotation(BindableObject bindable, object oldRotation, object newRotation)
    {
        var _oldRotation = (int)oldRotation;
        var _newRotation = (int)newRotation;

        if (!_oldRotation.Equals(_newRotation))
        {
            var view = (RotatedImage)bindable;
            var transformations = new System.Collections.Generic.List<ITransformation>() {
                new RotateTransformation(_newRotation)
            };
            view.Transformations = transformations;
        }
    }
}

因此,在我的XAML中-我声明了RotatedImage而不是标准Image。使用自定义渲染器,我能够做到这一点,并使图像显示旋转正确的数量。

image.MyRotation = GetImageRotationCorrection(imageAsBytes)

这是完全不必要的解决方法-但这是我必须解决的长度。

我肯定会跟随这个问题,社区中可能有人可以帮助我们两个人!

答案 1 :(得分:2)

SaveMetaData标志导致旋转问题。 现在将其设置为false(默认为true)可以正确显示照片。

这是一个副作用,如果SaveToAlbum = true,则图像不再显示在图库中。

在使用GetStreamWithImageRotatedForExternalStorage时,即使使用FFImageLoading,仍然无法使用图像拍摄。