如何在保存图像时找到Generic GDI +错误的原因?

时间:2013-03-22 13:02:40

标签: c# .net image gdi+ system.drawing

拥有一个在加载和存储图像时可以使用多年的代码,我发现我有一个单独的图像打破了这段代码:

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

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

例外是:

  

发生System.Runtime.InteropServices.ExternalException

     

GDI +中发生了一般性错误。

     

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

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

enter image description here

(由于上图,上传到Stack Overflow后不再产生错误,我已经放the original image here

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

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

我的问题:

  • 你能想到任何阻碍.NET保存图像的特殊事物吗?
  • 有没有办法(除了惊慌失措)缩小这些错误?

10 个答案:

答案 0 :(得分:36)

虽然在保存图像时我仍然没有找到导致错误的原因,但我找到了一个适用的解决方法:

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);

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

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

saved image i2.jpg

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

答案 1 :(得分:13)

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

答案 2 :(得分:7)

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

答案 3 :(得分:4)

原因可能是图像被懒惰加载,并且当您尝试保存时,加载过程尚未完成。

按照this blog post中的说法(假设您在问题中链接的图片是德语)提供了一种可能的解决方案。此外,this SO question's接受的回答表明这是因为您尝试保存的图片文件被锁定。

修改
对于Ulysses Alves,来自链接的博客条目:如果使用Image.FromFile()加载图像,它将保持锁定状态,直到它被丢弃为止。这可以防止拨打Save()

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

上面的代码会抛出错误。

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

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

答案 4 :(得分:3)

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

以下是代码:

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

请尝试让我知道

答案 5 :(得分:3)

我找到了这个问题,是因为我也遇到了类似的错误,并且该文件实际上是长度为零的创建的(如果您没有看到任何文件,请先检查是否可以像其他文件一样写入文件夹)答案表明)。尽管我的代码略有不同(我使用stream从内存而不是从文件读取图像),但我认为我的回答可能会对遇到类似问题的任何人有所帮助。

这可能看起来违反直觉,但是直到完成图像后,您才能真正处置内存流。

不工作

Image patternImage;

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

patternImage.Save(patternFile, ImageFormat.Jpeg);

在处理完图像之前,请勿丢弃流。

作品

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

误导之处:

  • 错误消息并没有告诉您任何内容
  • 您可以看到图像属性,例如宽度和高度,但看不到 保存

答案 6 :(得分:1)

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

答案 7 :(得分:1)

只需将Visual Studio用作管理员,或以管理员身份运行由代码创建的应用程序,它就可以正常运行。 这是用户访问权限问题。 我面临同样的问题,并通过以管理员身份运行Visual Studio来解决了这个问题。

答案 8 :(得分:0)

在程序中打开

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();

答案 9 :(得分:-2)

关键信息:

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

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

使用:

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

将抛出错误:

  

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