【问题标题】:Xamarin save image from imageButtonXamarin 从 imageButton 保存图像
【发布时间】:2021-04-11 00:34:48
【问题描述】:

我有一个带有显示空白个人资料图片的图像按钮的页面。用户可以点击它,它会打开一个文件对话框以从他们的画廊中选择一张图片。选择图片后,用户会看到页面上的图像按钮上显示的图像。我这样设置图像源:

private async void ImgStudentImage_Clicked(object sender, EventArgs e)
{
    Stream stream = await DependencyService.Get<IPhotoPickerService>().GetImageStreamAsync();
    if (stream != null)
    {
        imgButton.Source = ImageSource.FromStream(() => stream);
    }

}

这一切都很好,但是当单击/点击保存按钮时我如何保存图像?我在想,单击保存按钮后,我可以使用类似的东西访问图像 p>

string pth = imgButton.Source.ToString();
std.Picture = File.ReadAllBytes(pth);

然后我可以将图像保存为字节数组,但 .Source.ToString() 返回“Xamarin.Forms.StreamingImageSource”并引发此错误:

System.IO.FileNotFoundException
Could not find file 'C:\Xamarin\DJB\DJB\DJB.UWP\bin\x86\Debug\AppX\Xamarin.Forms.StreamImageSource'.

有没有办法从 imageButton 中检索图像?

【问题讨论】:

    标签: c# xamarin.forms


    【解决方案1】:

    我花了很长时间才找到这个答案的解决方案,如果微软向 ImageButton 添加一个方法来检索图像,那就太好了。在搜索了一段时间后,对数据类型更加熟悉,并查看了最初从用户那里获取图像时已经拥有的数据,我决定基本上扩展 ImageButton 控件以具有字节数组属性,并将其设置为用户选择图像时的属性。这让我很容易使用。我可以简单地从 ImageButton 访问字节数组,而不是从 ImageButton 获取图像作为某种随机数据类型,这是我需要的最终数据类型。

    我是这样做的:在我从用户那里检索照片的方法中(改编自 Microsoft 示例的代码)

    private async void ImgStudentImage_Clicked(object sender, EventArgs e)
    {
        Stream stream = await DependencyService.Get<IPhotoPickerService>().GetImageStreamAsync();
        if (stream != null)
        {
            imgButton.Source = ImageSource.FromStream(() => stream);
        }
    }
    

    服务返回一个流对象。流对象很有用,但使用起来有些笨拙。您可以看到我在此处的表单(页面)上分配了图像,但是当我尝试用它做任何其他事情时,图片会在表单上消失!所以我不能将流分配给 ImageButton 然后使用流创建一个字节数组 - 相当痛苦。解决方法是将流转换为字节数组并将该字节数组保存在我的 ExtendedImageButton 中,然后从存储在图像按钮中的字节数组中检索图像。傻吧?但它有效。所以我的 on_click 方法现在看起来像这样:

    private async void ImgStudentImage_Clicked(object sender, EventArgs e)
    {
        Stream stream = await DependencyService.Get<IPhotoPickerService>().GetImageStreamAsync();
        if (stream != null)
        {
            MemoryStream ms = new MemoryStream();
            stream.CopyTo(ms); //this line causes the image on the form to disappear, no matter where the line is placed in code. Creating a copy of the stream doesn't solve the problem either.
            imgButton.SourceAsByteArray = ms.ToArray();
            imgButton.Source = Converters.ByteArrayToImageSource(imgButton.SourceAsByteArray);
        }
    }
    

    我的 ExtendedImageButton 非常简单:

    using Xamarin.Forms;
    
    namespace MyNameSpace.Controls
    {
        class ExtendedImageButton : ImageButton
        {
            public byte[] SourceAsByteArray { get; set; }
    
        }
    }
    

    如您所见,我刚刚添加了字节数组的属性。我将此文件存储在我的 Controls 文件夹中。在我的 xaml 中,我使用了这个参考和标签:

    xmlns:controls="clr-namespace:MyAppName.Controls"
    <controls:ExtendedImageButton />
    

    我需要一种将字节数组转换回图像源的方法:

    public static ImageSource ByteArrayToImageSource(byte[] byteArr)
    {
        Stream stream = new MemoryStream(byteArr);
        return ImageSource.FromStream(() => stream);
    }
    

    我将此方法保存在一个名为“Converters”的类文件中。

    最后,在我想从 ImageButton 中检索图像的代码中,我只需使用以下代码:

    userPicture = imgButton.SourceAsByteArray;
    

    其中 userPicture 当然是一个字节数组变量。

    【讨论】:

      【解决方案2】:

      到目前为止,纯 XF 无法做到这一点,您只需将此图像转换为其各自的本机类型,然后将它们转换为您想要的类型。

      例如,在 Android 中,您会执行以下操作:

      public static async Task<Bitmap> GetBitmapFromImageSourceAsync(ImageSource source, Context context)
      {
          var handler = GetHandler(source);
          var returnValue = (Bitmap)null;
          returnValue = await handler.LoadImageAsync(source, context);
          return returnValue;
      }
      

      您可以查看我的博客here 以获得完整的解决方案。

      请注意,该博客没有从本机类型转换的 byte[],但可以在 Stack 和 Xamarin 论坛上轻松获得。

      如有疑问,请随时回复

      祝你好运。

      【讨论】:

        【解决方案3】:

        遇到了同样的问题。如果我将源复制到内存流,则不会显示图像,因为复制到方法将流的位置设置为最后一位。 你只需要把它放在0上;

        private async void ImgStudentImage_Clicked(object sender, EventArgs e)
        {
            Stream stream = await DependencyService.Get<IPhotoPickerService>().GetImageStreamAsync();
            if (stream != null)
            {
                MemoryStream ms = new MemoryStream();
                stream.CopyTo(ms); 
                stream.Position = 0;
                source = ImageSource.FromStream(() => stream);
               
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2014-09-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-11
          • 1970-01-01
          • 2020-04-27
          • 1970-01-01
          相关资源
          最近更新 更多