【问题标题】:Getting the bytes[] / stream of an Image or ImageSource in Xamarin.Forms?在 Xamarin.Forms 中获取图像或 ImageSource 的字节 [] / 流?
【发布时间】:2014-11-14 07:29:36
【问题描述】:

我一直在深入研究 Xamarin.Forms.Labs,以了解有关如何访问和操作图像的更多信息。将图像保存到 Android/iOS 照片库可以正常工作,至少在用户交互的情况下从其中检索图像也是如此。

问题是我希望能够在程序内部保存一些文件。实际上保存文件本身似乎不是问题 - 我已经为此编写了一个 interface/DependencyService 解决方案。

我似乎无法使用 Xamarin.Forms Image 或 ImageSource 访问图像数据本身的字节 [] 或流。使用静态方法将流读入 ImageSource 相对简单,那么如何取出这些字节以便将文件保存在程序本身中?

为此:我现在正在开发一个应用程序,用户在该应用程序中拍摄/选择要包含在表单中的图片,并且表单最终会发布到网站。因此,能够实际保存图片,或访问数据本身以进行传输,是非常关键的。

【问题讨论】:

  • 在 Forms.Labs 中四处挖掘,我发现 MediaPicker 显然可以通过公开对从相机或文件库获取的任何媒体的流的访问来满足我的需要。这仍然让我想知道如何获取图像本身的流 - 特别是在这里我正在考虑 SignaturePad 图像 - 但至少这是进步,并且可能也有内置的解决方案。

标签: c# android ios xamarin


【解决方案1】:

一个非常老套的方法是为您的图像编写一个自定义渲染器。然后渲染器将从本机控件中获取byte[]/Stream。这是一个非常粗略的实现,没有任何错误处理来帮助您入门:

public class MyImage : Image
{
    public Func<byte[]> GetBytes { get; set; }
}

这是 iOS 渲染器:

public class MyImageRenderer : ImageRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
    {
        base.OnElementChanged(e);

        var newImage = e.NewElement as MyImage;
        if (newImage != null)
        {
            newImage.GetBytes = () =>
            {
                return this.Control.Image.AsPNG().ToArray();
            };
        }

        var oldImage = e.OldElement as MyImage;
        if (oldImage != null)
        {
            oldImage.GetBytes = null;
        }
    }
}

Android 涉及更多一点:

public class MyImageRenderer : ImageRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
    {
        base.OnElementChanged(e);

        var newImage = e.NewElement as MyImage;
        if (newImage != null)
        {
            newImage.GetBytes = () =>
            {
                var drawable = this.Control.Drawable;
                var bitmap = Bitmap.CreateBitmap(drawable.IntrinsicWidth, drawable.IntrinsicHeight, Bitmap.Config.Argb8888);
                drawable.Draw(new Canvas(bitmap));
                using (var ms = new MemoryStream())
                {
                    bitmap.Compress(Bitmap.CompressFormat.Png, 100, ms);
                    return ms.ToArray();
                }
            };
        }

        var oldImage = e.OldElement as MyImage;
        if (oldImage != null)
        {
            oldImage.GetBytes = null;
        }
    }
}

最后,用法很明显:

var bytes = myImage.GetBytes?.Invoke();

将想法扩展为支持流应该非常简单。明显的警告是表单控件 (MyImage) 保留了通过 GetBytes() 对其渲染器的引用,但这似乎是不可避免的。

【讨论】:

  • GetBytes 在渲染器中对我来说是空的:/ #Android
  • 你注册渲染器了吗? GetBytes 是您在OnElementChanged 中分配的函数,因此不应为空。
猜你喜欢
  • 2016-09-20
  • 2015-07-28
  • 2015-03-23
  • 1970-01-01
  • 1970-01-01
  • 2021-03-31
  • 1970-01-01
  • 2012-02-20
  • 1970-01-01
相关资源
最近更新 更多