2013-03-22 37 views
14

有了这样的加载和存储图像时的年龄工作的代码,我发现我有一个打破这个代码的单个图像如何在保存图像时找到Generic GDI +错误的原因?

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.External发生的异常

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

在System.Drawing.Image.Save(字符串文件名,ImageCodecInfo编码器,EncoderParameters encoderParams)
在System.Drawing.Image.Save(字符串文件名,格式的imageformat)
在...

就我所见,图像没有特别之处。它大小约为250像素,可以在例如Windows图像查看器或Paint.NET:

enter image description here

(由于上面的图片,上传到堆栈溢出不会产生错误了之后,我已经把the original image here

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

我对导致错误的原因确实无能为力。

我的问题:

  • 你能想到的会从保存图像阻碍.NET任何特别的东西?
  • 有没有什么办法(除了恐慌)来缩小这类错误?
+1

MSDN说从流加载的位图需要流保持存在,只要位图存在。 – 2015-11-11 00:14:00

+1

未解决您的问题:但是,如果路径不存在,则会发生同样的异常(我花了一段时间才弄清楚我有一个错字)。可能帮助别人。 – 2017-05-18 08:27:25

回答

27

虽然我还是没弄明白保存图像时,究竟是什么导致错误的原因,我发现了一个变通方法适用于:

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)更小的文件。

+4

构建一个新的位图(oldImage)也解决了我的问题... – esbenr 2013-12-20 08:51:57

+1

这也适用于我。之后,我不得不强制垃圾收集,原因是“内存异常”。 – user426364 2014-06-09 13:04:26

+1

为我工作 - 不知道为什么。只有与JPG图像(PNG等问题)的问题 – Darren 2015-04-09 19:56:13

3

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

以下说的this blog post(假设你是德国人,你在图片中链接了你的问题)提供了一个可能的解决方案。另外this SO question's接受的答案表明这是由于您试图保存的图像文件被锁定。

编辑
尤里西斯阿尔维斯,从链接的博客条目:如果您加载使用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") 
+1

我真的不明白为什么这个答案是downvoted ...也许有人可以解释? – 2013-03-22 13:41:01

+1

由于下来的选民没有留下评论,我们可能永远不会知道。 :) – 2015-11-11 00:10:47

+0

我找不到任何与此主题相关的链接帖子。您能否在您的答案中提供一个代码示例? – 2017-10-23 16:47:11

8

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

+1

谢谢。这个对我有用。 – 2014-05-29 00:15:44

+0

这就像90%的情况:-) – 2017-02-23 16:18:36

5

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

+1

这听起来像是一个糟糕的答案。 – 2014-04-28 13:35:21

+2

“确保服务器上的目标目录存在”是我的问题 – 2015-09-18 15:23:50

+2

@UweKeim - 在临时IDisposable对象上使用''只是确保在安全的情况下尽快调用GC。 – 2015-11-11 00:03:43

3

我的解决方案只是将文件保存

这里之前做,写临时含量(File.WriteAllText)是代码:

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

请尝试,让我知道

+1

如果您没有创建该文件的权限,我可以看到在哪里/哪里出现异常,哪里会发生变化。 :) :)但它会很奇怪,如果这解决了OP中的其他问题。 'bitmap.Freeze(); bitmap.Save(...);'或'var other = new Bitmap(bitmap); other.Save(...);'这两个函数确保在调用Save之前,保存的位图不会绑定到流。 – 2015-11-11 00:08:40

-1

在程序中打开

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

问题是,您无法保存在C:驱动器的根分区上。保存在其他地方,你不会有问题。

+0

在我看来,这是一个非常糟糕的答案。您是否阅读了我的整个问题? – 2017-10-07 12:26:40

相关问题