Создание WPF BitmapImage из MemoryStream png, gif
У меня возникли проблемы с созданием BitmapImage
из MemoryStream
из байтов png и gif, полученных из веб-запроса. Кажется, что байты загружены отлично, и объект BitmapImage
создается без проблем, однако изображение на самом деле не отображается в моем пользовательском интерфейсе. Проблема возникает только тогда, когда загруженное изображение имеет тип png или gif (отлично работает для jpeg).
Вот код, который демонстрирует проблему:
var webResponse = webRequest.GetResponse();
var stream = webResponse.GetResponseStream();
if (stream.CanRead)
{
Byte[] buffer = new Byte[webResponse.ContentLength];
stream.Read(buffer, 0, buffer.Length);
var byteStream = new System.IO.MemoryStream(buffer);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.DecodePixelWidth = 30;
bi.StreamSource = byteStream;
bi.EndInit();
byteStream.Close();
stream.Close();
return bi;
}
Чтобы проверить, что веб-запрос правильно получил байты, я попробовал следующее, которое сохраняет байты в файл на диске, а затем загружает изображение с помощью UriSource
, а не StreamSource
и работает для всех типов изображений
var webResponse = webRequest.GetResponse();
var stream = webResponse.GetResponseStream();
if (stream.CanRead)
{
Byte[] buffer = new Byte[webResponse.ContentLength];
stream.Read(buffer, 0, buffer.Length);
string fName = "c:\\" + ((Uri)value).Segments.Last();
System.IO.File.WriteAllBytes(fName, buffer);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.DecodePixelWidth = 30;
bi.UriSource = new Uri(fName);
bi.EndInit();
stream.Close();
return bi;
}
Кто-нибудь получил свет, чтобы светить?
Ответы
Ответ 1
Добавьте bi.CacheOption = BitmapCacheOption.OnLoad
непосредственно после .BeginInit()
:
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
...
Без этого BitmapImage по умолчанию использует ленивую инициализацию, и к тому времени поток будет закрыт. В первом примере вы пытаетесь прочитать изображение из возможного собранного мусора закрытого или даже удаленного MemoryStream. Второй пример использует файл, который по-прежнему доступен.
Кроме того, не пишите
var byteStream = new System.IO.MemoryStream(buffer);
лучше
using (MemoryStream byteStream = new MemoryStream(buffer))
{
...
}
Ответ 2
Я использую этот код:
public static BitmapImage GetBitmapImage(byte[] imageBytes)
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = new MemoryStream(imageBytes);
bitmapImage.EndInit();
return bitmapImage;
}
Может быть, вы должны удалить эту строку:
bi.DecodePixelWidth = 30;