显示从其URI检索到的图像

时间:2018-11-16 22:41:25

标签: c# wpf image type-conversion bitmapimage

尝试序列化包含BitmapSource字段的对象时遇到一些问题。

实际上,一开始我有一个ImageSource,但是它似乎不可序列化。 所以我试图使用关联的属性来存储一个字符串,并将图像转换为字符串或从字符串转换回图像。但是现在没有图像显示:-(

这是XAML图像标记:

<Image 
                        x:Name="bookCover"
                        Grid.Row="0"
                        Grid.RowSpan="1"
                        Grid.Column="0"
                        MaxWidth="200"
                        MaxHeight="320"
                        Margin="5"
                        Source="{Binding Image}" SizeChanged="bookCover_SizeChanged" >

                    </Image>

这是模型类中的Image属性和字段:

public string _image;

public BitmapSource Image
        {
            get => Base64ToImage(_image);
            set
            {
                _image =ImageToBase64(value);
                OnPropertyChanged("Image");
            }
        }

及其相关方法:

public static string ImageToBase64(BitmapSource bitmap)
        {

            var encoder = new JpegBitmapEncoder();
            var frame = BitmapFrame.Create(bitmap);
            encoder.Frames.Add(frame);
            using (var stream = new MemoryStream())
            {
                encoder.Save(stream);
                return Convert.ToBase64String(stream.ToArray());
            }
        }

        public static  BitmapSource Base64ToImage(string base64)
        {
            byte[] bytes = Convert.FromBase64String(base64);
            using (var stream = new MemoryStream(bytes))
            {
                return BitmapFrame.Create(stream);
            }

        }

在这里,我的程序通过URI从Internet检索图像并将其存储:

var myUri=new Uri(book0.LargeImage.URL);
bookToInsert.Image = new BitmapImage(myUri);

谢谢。

1 个答案:

答案 0 :(得分:1)

当从创建后立即关闭的流中创建BitmapSource时,必须设置BitmapCacheOption.OnLoad。否则,在实际使用BitmapSource之前,必须将流保持打开状态,例如显示在Image元素中。

public static BitmapSource Base64ToImage(string base64)
{
    using (var stream = new MemoryStream(Convert.FromBase64String(base64)))
    {
        return BitmapFrame.Create(
            stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
    }
}

一些注意事项:

  1. base64编码和解码似乎是不必要的。更好地序列化字节数组。
  2. 最初不要从URL创建BitmapImage。最好通过Web请求直接获取图像缓冲区。
  3. 您不仅可以将Image元素的Source属性绑定到ImageSource,还可以绑定到字符串,Uri或字节数组。因此,您的财产可以声明为byte[] Image

尝试这样更简单的视图模型:

public class ViewModel : INotifyPropertyChanged
{
    private byte[] image;

    public byte[] Image
    {
        get => image;
        set
        {
            image = value;
            OnPropertyChanged(nameof(Image));
        }
    }
}

并像这样设置Image属性:

var webClient = new WebClient();
viewModel.Image = webClient.DownloadData(book0.LargeImage.URL);

或异步:

var httpClient = new HttpClient();
viewModel.Image = await httpClient.GetByteArrayAsync(book0.LargeImage.URL);