c# - 在 Xamarin.Forms 中获取 Image 或 ImageSource 的 bytes[]/stream?

标签 c# android ios xamarin

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

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

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

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

最佳答案

一个非常 hacky 的方法是为您的图像编写一个自定义渲染器。然后渲染器将从 native 控件获取 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() 保留对其渲染器的引用,但这似乎是不可避免的。

关于c# - 在 Xamarin.Forms 中获取 Image 或 ImageSource 的 bytes[]/stream?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25938386/

相关文章:

android - 在不消耗 MotionEvent 的情况下处理 Android 中的滑动/滚动

android - HttpClient 在 Android 和 iOS 上的处理方式不同?

ios - 如何更改 searchcontroller 中的 uitextfield 颜色?

c# - 方法的参数顺序(比如命名、参数、输入、输出、可选)是什么?

javascript - 如何创建函数以在后端验证下拉列表

c# - 从基类 C# 调用子类方法

android - 图像为白色时的 CollapsingToolbarLayout

java - Android 通过 HTTP 发送数据并接收正文响应

c# - Entity Framework - 多项目支持

ios - Firebird 和 Swift 兼容性?