C# Image.Save(..) 抛出 GDI+ 异常,因为内存流已关闭

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/336387/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 23:43:27  来源:igfitidea点击:

Image.Save(..) throws a GDI+ exception because the memory stream is closed

c#imageexceptiongdi+

提问by Pure.Krome

i've got some binary data which i want to save as an image. When i try to save the image, it throws an exception if the memory stream used to create the image, was closed before the save. The reason i do this is because i'm dynamically creating images and as such .. i need to use a memory stream.

我有一些二进制数据,我想将其另存为图像。当我尝试保存图像时,如果用于创建图像的内存流在保存之前关闭,则会引发异常。我这样做的原因是因为我正在动态创建图像,因此..我需要使用内存流。

this is the code:

这是代码:

[TestMethod]
public void TestMethod1()
{
    // Grab the binary data.
    byte[] data = File.ReadAllBytes("Chick.jpg");

    // Read in the data but do not close, before using the stream.
    Stream originalBinaryDataStream = new MemoryStream(data);
    Bitmap image = new Bitmap(originalBinaryDataStream);
    image.Save(@"c:\test.jpg");
    originalBinaryDataStream.Dispose();

    // Now lets use a nice dispose, etc...
    Bitmap2 image2;
    using (Stream originalBinaryDataStream2 = new MemoryStream(data))
    {
        image2 = new Bitmap(originalBinaryDataStream2);
    }

    image2.Save(@"C:\temp\pewpew.jpg"); // This throws the GDI+ exception.
}

Does anyone have any suggestions to how i could save an image with the stream closed? I cannot rely on the developers to remember to close the stream after the image is saved. In fact, the developer would have NO IDEA that the image was generated using a memory stream (because it happens in some other code, elsewhere).

有没有人对我如何在关闭流的情况下保存图像有任何建议?我不能依赖开发人员记住在保存图像后关闭流。事实上,开发人员不知道图像是使用内存流生成的(因为它发生在其他一些代码中,别处)。

I'm really confused :(

我真的很困惑:(

采纳答案by Jon Skeet

As it's a MemoryStream, you really don't needto close the stream - nothing bad will happen if you don't, although obviously it's good practice to dispose anything that's disposable anyway. (See this questionfor more on this.)

因为它是一个 MemoryStream,所以你真的不需要关闭流 - 如果你不关闭不会什么不好的事情发生,尽管显然处理任何一次性的东西是一种很好的做法。(有关此问题的更多信息,请参阅此问题。)

However, you shouldbe disposing the Bitmap - and that will close the stream for you. Basically once you give the Bitmap constructor a stream, it "owns" the stream and you shouldn't close it. As the docs for that constructorsay:

但是,您应该处理位图 - 这将为您关闭流。基本上,一旦您为 Bitmap 构造函数提供了一个流,它就“拥有”了该流,您不应关闭它。正如该构造函数的文档所说:

You must keep the stream open for the lifetime of the Bitmap.

您必须在位图的生命周期内保持流打开。

I can't find any docs promising to close the stream when you dispose the bitmap, but you should be able to verify that fairly easily.

我找不到任何承诺在您处理位图时关闭流的文档,但您应该能够很容易地验证这一点。

回答by Brian Low

Copy the Bitmap. You have to keep the stream open for the lifetime of the bitmap.

复制位图。您必须在位图的整个生命周期内保持流打开。

When drawing an image: System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI

绘制图像时:System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI

    public static Image ToImage(this byte[] bytes)
    {
        using (var stream = new MemoryStream(bytes))
        using (var image = Image.FromStream(stream, false, true))
        {
            return new Bitmap(image);
        }
    }

    [Test]
    public void ShouldCreateImageThatCanBeSavedWithoutOpenStream()
    {
        var imageBytes = File.ReadAllBytes("bitmap.bmp");

        var image = imageBytes.ToImage();

        image.Save("output.bmp");
    }

回答by Rojzik

Perhaps it is worth mentioning that if the C:\Temp directory does not exist, it will also throw this exception even if your stream is still existent.

也许值得一提的是,如果 C:\Temp 目录不存在,即使您的流仍然存在,它也会抛出此异常。

回答by Houman

A generic error occurred in GDI+.May also result from incorrect save path! Took me half a day to notice that. So make sure that you have double checked the path to save the image as well.

GDI+ 中出现一般错误。也可能是因为保存路径不正确!我花了半天时间才注意到这一点。因此,请确保您也仔细检查了保存图像的路径。

回答by Yuri Perekupko

You can try to create another copy of bitmap:

您可以尝试创建位图的另一个副本:

using (var memoryStream = new MemoryStream())
{
    // write to memory stream here

    memoryStream.Position = 0;
    using (var bitmap = new Bitmap(memoryStream))
    {
        var bitmap2 = new Bitmap(bitmap);
        return bitmap2;
    }
}

回答by S.Roshanth

A generic error occurred in GDI+. It can occur because of image storing paths issues,I got this error because my storing path is too long, I fixed this by first storing the image in a shortest path and move it to the correct location with long path handling techniques.

GDI+ 中出现一般错误。它可能是由于图像存储路径问题而发生的,我收到此错误是因为我的存储路径太长,我通过首先将图像存储在最短路径中并使用长路径处理技术将其移动到正确位置来解决此问题。

回答by Vinothkumar

One strange solution which made my code to work. Open the image in paint and save it as a new file with same format(.jpg). Now try with this new file and it works. It clearly explains you that the file might be corrupted in someway. This can help only if your code has every other bugs fixed

一种奇怪的解决方案使我的代码正常工作。在paint中打开图像并将其另存为具有相同格式(.jpg)的新文件。现在尝试使用这个新文件,它可以工作。它清楚地向您解释了该文件可能以某种方式损坏。只有当您的代码修复了所有其他错误时,这才有帮助

回答by Morad Aktam

I had the same problem but actually the cause was that the application didn't have permission to save files on C. When I changed to "D:\.." the picture has been saved.

我遇到了同样的问题,但实际上原因是该应用程序没有在 C 上保存文件的权限。当我更改为“D:\..”时,图片已被保存。

回答by Jay K

This error occurred to me when I was trying from Citrix. The image folder was set to C:\ in the server, for which I do not have privilege. Once the image folder was moved to a shared drive, the error was gone.

当我从 Citrix 尝试时,我发生了这个错误。图像文件夹在服务器中设置为 C:\,我没有权限。将图像文件夹移动到共享驱动器后,错误就消失了。

回答by P.Lisa

I was getting this error, because the automated test I was executing, was trying to store snapshots into a folder that didn't exist. After I created the folder, the error resolved

我收到此错误,因为我正在执行的自动化测试试图将快照存储到不存在的文件夹中。创建文件夹后,错误解决了