繁体   English   中英

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

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

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

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 编码器参数)
在 System.Drawing.Image.Save(字符串文件名,ImageFormat 格式)
在 ...

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

在此处输入图片说明

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

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

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

我的问题:

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

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

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) 小。

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

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

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

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

编辑
对于 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")

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

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

不工作

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

什么是误导:

  • 错误消息并没有真正告诉你任何事情
  • 您可以看到图像属性,例如宽度和高度,但无法保存

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

这是代码:

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

请尝试让我知道

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

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

在程序中打开

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

关键信息:

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

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

使用:

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

将抛出错误:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM