从内存流创建WPF BitmapImage的方法(png、gif)

32

我正在尝试从一个包含来自Web请求的PNG和GIF字节的MemoryStream创建BitmapImage,但遇到了一些问题。 字节似乎已经成功下载,并且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个回答

51

.BeginInit()之后直接添加bi.CacheOption = BitmapCacheOption.OnLoad

BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
...
Without this, BitmapImage will use lazy initialization by default, which will cause the stream to be closed. In the first example, you may be attempting to read an image from a MemoryStream that has been closed or disposed (marked out), leading to potential issues. The second example uses a file that is still available.
var byteStream = new System.IO.MemoryStream(buffer);
更好
using (MemoryStream byteStream = new MemoryStream(buffer))
{
   ...
}

6
“BitmapCacheOption.OnLoad”技巧很重要。我只想补充一点,它应该放在“BeginInit()”和“EndInit()”之间。 - Pieter Müller
1
@PieterMüller:非常有用的提示;此外,在调用EndInit()时,流仍然必须保持打开状态,这是你可能会遇到的另一个限制。 - O. R. Mapper

14

我正在使用这段代码:

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

也许你应该删除这一行:

bi.DecodePixelWidth = 30;

1
但是关于通过以下方式创建的内存流如何关闭: new MemoryStream(imageBytes) 我认为更改CacheOption更好,这样的流应该关闭吗? - Amer Sawan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接