C# 保存图像时如何找到通用 GDI+ 错误的原因?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15571022/
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-10 17:13:50  来源:igfitidea点击:

How to find reason for Generic GDI+ error when saving an image?

c#.netimagegdi+system.drawing

提问by Uwe Keim

Having a code that works for ages when loading and storing images, I discovered that I have one single imagethat breaks this code:

有一个在加载和存储图像时可以使用很长时间的代码,我发现我有一个破坏此代码的单个图像

const string i1Path = @"c:\my\i1.jpg";
const string i2Path = @"c:\my\i2.jpg";

var i = Image.FromFile(i1Path);
i.Save(i2Path, ImageFormat.Jpeg);

The exception is:

例外是:

System.Runtime.InteropServices.ExternalException occurred

A generic error occurred in GDI+.

at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(String filename, ImageFormat format)
at ...

System.Runtime.InteropServices.ExternalException 发生

GDI+ 中出现一般错误。

在 System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
在 System.Drawing.Image.Save(String filename, ImageFormat format)
在 ...

As far as I can see, there is nothing special about the image. It is approx 250 pixels in size and can be opened in e.g. Windows Image Viewer or Paint.NET:

就我所见,图像没有什么特别之处。它的大小约为 250 像素,可以在例如 Windows Image Viewer 或 Paint.NET 中打开:

enter image description here

在此处输入图片说明

(Since the image above, after being uploaded to Stack Overflow does not produce the error anymore, I've put the original image here)

(因为上图上传到Stack Overflow后不再报错,我把原图放在这里

What I discovered is that upon calling the Savemethod, the destination image file is being created with zero bytes.

我发现在调用Save方法时,目标图像文件是用零字节创建的。

I am really clueless on what causes the error.

我真的对导致错误的原因一无所知。

My questions:

我的问题:

  • Can you think of any special thing that would hinder .NET from saving the image?
  • Is there any way (beside panicing) to narrow down these kind of errors?
  • 你能想到任何会阻碍 .NET 保存图像的特殊事情吗?
  • 有没有办法(除了恐慌)缩小这些错误的范围?

采纳答案by Uwe Keim

While I still did not find out the reason what exactly caused the error when saving the image, I found a workaround to apply:

虽然我仍然没有找出保存图像时究竟是什么导致错误的原因,但我找到了一个解决方法:

const string i1Path = @"c:\my\i1.jpg";
const string i2Path = @"c:\my\i2.jpg";

var i = Image.FromFile(i1Path);

var i2 = new Bitmap(i);
i2.Save(i2Path, ImageFormat.Jpeg);

I.e. by copying the image internally into a Bitmapinstance and saving this image instead of the original image, the error disappeared.

即通过将图像内部复制到Bitmap实例中并保存此图像而不是原始图像,错误消失了。

I'm assuming that by copying it, the erroneous parts the caused the original Savecall to fail are being removed an/or normalized, thus enabling the save operation to succeed.

我假设通过复制它,导致原始Save调用失败的错误部分被删除和/或规范化,从而使保存操作成功。

saved image i2.jpg

保存的图像 i2.jpg

Interestingly, the so stored image has a smaller file on disk (16 kB) than its original source (26 kB).

有趣的是,如此存储的图像在磁盘上的文件 (16 kB) 比其原始源 (26 kB) 小。

回答by Thorsten Dittmar

The reason may be that the image is loaded lazily and the loading process is not yet finished when you try to save it.

原因可能是图像加载延迟,尝试保存时加载过程尚未完成。

Following what's said in this blog post(assuming you're German by the picture you linked in your question) provides a possible solution. Also this SO question'saccepted answer indicates this is due to the fact the image file you're trying to save to is locked.

按照这篇博文中所说(假设你在问题中链接的图片是德国人)提供了一个可能的解决方案。此外,此问题已接受的答案表明这是由于您尝试保存的图像文件已被锁定。

EDIT
For Ulysses Alves, from the linked blog entry: If you load an image using Image.FromFile()it remains locked until it is disposed of. This prevents calls to Save().

编辑
尤利西斯·阿尔维斯,来自链接的博客条目:如果您使用Image.FromFile()它加载图像,则在它被处理之前保持锁定状态。这可以防止调用Save().

pictureBox1.Image = Image.FromFile("C:\test\test1.jpg");
pictureBox1.Image.Save("C:\test\test2.jpg");

The above code throws an error.

上面的代码抛出一个错误。

To make it work, you need to copy the image. The following code works:

要使其工作,您需要复制图像。以下代码有效:

pictureBox1.Image = Image.FromFile("C:\test\test1.jpg");
Image copy = pictureBox1.Image;
copy.Save("C:\test\test2.jpg")

回答by Shadmehr Vadoodi

First of all make sure, that the desired folder has Read/Write permissions. Changing the permissions solved this problem for me.

首先确保所需的文件夹具有读/写权限。更改权限为我解决了这个问题。

回答by Azarsa

Solution is here, you must dispose image object to release the memory on the server. Try use usingstatement. Make sure destination directory on server exists too.

解决方案在这里,您必须处理图像对象以释放服务器上的内存。尝试使用using语句。确保服务器上的目标目录也存在。

回答by mr.baby123

my solution was to make, write temp content (File.WriteAllText) just before saving the file

我的解决方案是在保存文件之前制作,写入临时内容(File.WriteAllText)

Here is the code:

这是代码:

var i = Image.FromFile(i1Path);
File.WriteAllText(i2Path, "empty");  // <---- magic goes here
i.Save(i2Path, ImageFormat.Jpeg);

Please try and let me know

请尝试让我知道

回答by Konstant

Open in the program

在程序中打开

const string i1Path = @"c:\my\i1.jpg";

const string i2Path = @"c:\my\i2.jpg";

var i = Image.FromFile(i1Path);

i.Save(i2Path, ImageFormat.Jpeg);

i.Dispose();

回答by Mike Keskinov

I found this question because I also faced the similar error and the file was actually created with zero length(if you don't see any file, first check the permissions to write into folder as other answers suggest). Although my code was slightly different (I use streamto read the image from memory, not from file), I think my answer may be helpful to anyone facing similar problem.

我发现这个问题是因为我也遇到了类似的错误,并且文件实际上是用零长度创建的(如果您没有看到任何文件,请首先检查写入文件夹的权限,如其他答案所建议的那样)。尽管我的代码略有不同(我stream过去常常从内存中读取图像,而不是从文件中读取图像),但我认为我的回答可能对任何面临类似问题的人有所帮助。

It may looks counter-intuitive, but you can't really dispose memory stream until you finish with image.

它可能看起来违反直觉,但在完成 image 之前,您无法真正处理内存流。

NOT WORKING:

不工作

Image patternImage;

using (var ms = new MemoryStream(patternBytes)) {
    patternImage = new Bitmap(ms);
}

patternImage.Save(patternFile, ImageFormat.Jpeg);

Just don't dispose the stream until you done with image.

在完成图像之前不要处理流。

WORKS:

作品

using (var ms = new MemoryStream(patternBytes)) {
    patternImage = new Bitmap(ms);
    patternImage.Save(patternFile, ImageFormat.Jpeg);
}

What is misleading:

什么是误导:

  • Error message doesn't really tell you anything
  • You can see the image properties, like width and height, but can't save it
  • 错误消息并没有真正告诉你任何事情
  • 您可以看到图像属性,例如宽度和高度,但无法保存

回答by Rusty Nail

Key Information:

关键信息:

// Using System.Drawing.Imaging:
new Bitmap(image).Save(memoryStream, ImageFormat.Jpeg);

You MUSTCast the Image to a Bitmap to Save it.

必须将图像投射到位图才能保存它。

Using:

使用:

// Using System.Drawing.Imaging:
image.Save(memoryStream, ImageFormat.Jpeg);

WILL throw the Error:

将抛出错误:

Generic GDI+ error when saving an image

保存图像时出现通用 GDI+ 错误

回答by Ashish Kumar Jaryal

In my case I have accidentally deleted the directory where image was getting stored.

就我而言,我不小心删除了存储图像的目录。

回答by Suhail Abdul Rehman Chougule

Just use the visual studio as administrator or run the application created by the code as administrator it should work smoothly. It is user access rights issue. I faced the same and resolved it by running visual studio as administrator.

只需以管理员身份使用visual studio或以管理员身份运行由代码创建的应用程序,它应该可以顺利运行。这是用户访问权限问题。我遇到了同样的问题,并通过以管理员身份运行 Visual Studio 解决了这个问题。