在 Xamarin.Forms 中获取图像或 ImageSource 的字节 [] / 流?

Posted

技术标签:

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

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

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

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

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

【问题讨论】:

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

以上是关于在 Xamarin.Forms 中获取图像或 ImageSource 的字节 [] / 流?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Xamarin.Forms.Map 中获取当前位置或移动到当前位置

在 Xamarin.Forms 中将图像裁剪为正方形

Xamarin.forms 使用 php 将图像上传到服务器目录

Xamarin.Forms 图像未从源显示

如何在 Xamarin Forms 中打开图像并将其与 Emgu Cv/OpenCvSharp 一起使用?

Xamarin.Forms:获取列表视图的所有单元格/项目