从流加载图像而不保持流打开

时间:2010-10-02 11:29:20

标签: c# image stream out-of-memory

是否可以使用System.Drawing.Image的FromStream方法而不必在图像的生命周期内保持流打开?

我有一个应用程序,它使用Image.FromStreamAssembly.GetManifestResourceStream的组合从资源文件加载一堆工具栏图形。

我遇到的问题是在Windows 7上工作正常,在Windows XP上,如果禁用链接到其中一个图像的用户界面元素,应用程序将崩溃。在Windows 7上,图像以灰度渲染。在XP上,它因内存不足而崩溃。

经过一连串的脱毛后,我终于将其追踪到了图像的初始加载状态。当然,如果我创建任何实现IDisposable的对象也在同一个方法中被销毁,我将其包装在using语句中,例如

using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
{
   image = Image.FromStream(resourceStream);
}

如果删除using语句以便不处理流,则应用程序不再在XP上崩溃。但我现在有一堆“孤儿”流 - 图像存储在命令类中,这些图像在处理时正确处理图像,但原始流不是。

我检查了FromStream的文档,确认了流需要保持打开状态。为什么这个没有在Windows 7开发系统上崩溃和烧毁是一个谜!

我真的不希望这个流停留,并且我当然不希望存储对此流以及图像的引用,以便稍后可以处理它。我只需要一次流,所以我想摆脱它:)

是否可以创建图像然后在那里杀死流?

4 个答案:

答案 0 :(得分:19)

需要打开流的原因是following

  

GDI +,因此 System.Drawing 命名空间可以推迟原始图像位的解码,直到图像需要这些位。另外,即使在图像被解码之后,GDI +也可以确定丢弃用于大位图的存储器并且稍后重新解码更有效。因此,GDI +必须能够在位图图像对象的生命周期内访问图像的源位。

记录的解决方法是使用Graphics.DrawImage创建非索引图像,或者从原始图像创建索引Bitmap,如下所述:

  

<强> Bitmap and Image constructor dependencies

答案 1 :(得分:3)

根据Image.FromStream的文档,在使用图像时,流必须保持打开状态。因此,即使关闭工作(并且没有什么可说的,在流处理之前你不能关闭流,就流对象本身而言),它可能不是一个非常可靠的方法。

您可以将图像复制到另一个图像对象,然后使用它。但是,这可能比仅保持流打开更加占用内存。

答案 2 :(得分:0)

您可以将流保存到临时文件并使用Image.FromFile方法。或者只是不嵌入图像,将其保存为文件并在运行时从该文件加载。

答案 3 :(得分:0)

我相信这会对某人有所帮助:)。

我将它用于我的dataGridView_SelectionChanged:

private void dataGridViewAnzeige_SelectionChanged(object sender, EventArgs e)
{
    var imageAsByteArray = File.ReadAllBytes(path);
    pictureBox1.Image = byteArrayToImage(imageAsByteArray);
}

public Image byteArrayToImage(byte[] byteArrayIn)
{
    MemoryStream ms = new MemoryStream(byteArrayIn);
    Image returnImage = Image.FromStream(ms);
    return returnImage;
}