40

在加载和存储图像时,我的代码可以工作很长时间,我发现我有一个图像破坏了这个代码:

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+ 中出现一般错误。

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

据我所知,这张照片没有什么特别之处。它的大小约为 250 像素,可以在 Windows Image Viewer 或 Paint.NET 中打开:

在此处输入图像描述

(由于上图,上传到 Stack Overflow 后就没有报错了,我把原图放在这里了

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

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

我的问题:

  • 你能想到什么特殊的东西会阻碍 .NET 保存图像吗?
  • 有没有办法(除了恐慌)来缩小这些错误的范围?
4

10 回答 10

55

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

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调用失败的错误部分被删除和/或规范化,从而使保存操作能够成功。

保存的图像 i2.jpg

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

于 2013-03-24T06:35:50.107 回答
20

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

于 2014-02-16T05:50:33.887 回答
9

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

于 2014-04-28T12:53:38.567 回答
5

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

遵循此博客文章中的内容(假设您在问题中链接的图片是德国人)提供了一个可能的解决方案。此外,这个 SO question's accepted answer 表明这是由于您尝试保存的图像文件已锁定。

编辑
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")
于 2013-03-22T13:03:55.580 回答
4

我发现这个问题是因为我也遇到了类似的错误,并且该文件实际上是用零长度创建的(如果您没有看到任何文件,请首先按照其他答案的建议检查写入文件夹的权限)。尽管我的代码略有不同(我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);
}

什么是误导:

  • 错误信息并没有真正告诉你任何事情
  • 您可以看到图像属性,例如宽度和高度,但无法保存
于 2018-12-25T00:09:58.227 回答
3

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

这是代码:

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

请尝试让我知道

于 2014-12-17T14:13:23.533 回答
3

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

于 2020-01-14T14:52:10.237 回答
1

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

于 2020-03-20T18:34:50.760 回答
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();
于 2017-07-23T14:14:56.777 回答
0

关键信息:

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

必须将图像转换为位图才能保存。

使用:

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

将抛出错误:

保存图像时出现一般 GDI+ 错误

于 2019-04-24T05:40:31.680 回答