Вопрос по wpf, memorystream, bitmapimage, webrequest, image – Создание WPF BitmapImage из MemoryStream png, gif

26

У меня возникли проблемы с созданием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;
}

У кого-нибудь есть свет, чтобы сиять?

Ваш Ответ

2   ответа
47

добавлять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))
{
   ...
}
BitmapCacheOption.OnLoad хитрость важна. Я просто хотел бы добавить, что это должно быть междуBeginInit() а также .EndInit() Pieter Müller
@ PieterMüИлер: Очень полезная подсказка; кроме того, поток ещедолжен быть открытым при звонкеEndInit() как еще одно ограничение, на которое вы можете наткнуться. O. R. Mapper
11

public static BitmapImage GetBitmapImage(byte[] imageBytes)
{
   var bitmapImage = new BitmapImage();
   bitmapImage.BeginInit();
   bitmapImage.StreamSource = new MemoryStream(imageBytes);
   bitmapImage.EndInit();
   return bitmapImage;
}

Может быть, вам следует удалить эту строку:

bi.DecodePixelWidth = 30;
Но как насчет закрытия потока памяти, который вы создали: new MemoryStream (imageBytes) Я думаю, что изменение CacheOption лучше, должны ли такие потоки быть закрыты? Amer Sawan

Похожие вопросы