отобразить изображение, полученное из его URI - PullRequest
0 голосов
/ 17 ноября 2018

У меня возникли проблемы при попытке сериализации объекта, содержащего поле 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 и сохраняет его:

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

спасибо.

1 Ответ

0 голосов
/ 17 ноября 2018

Когда вы создаете 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. Не создавать изначально BitmapImage из URL.Лучше напрямую получить буфер изображения с помощью веб-запроса.
  3. Вы можете привязать свойство Source элемента Image не только к 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);
...