我已经构建了一个程序,允许我通过System.Image.Drawing插入注释和图片标题。所以现在,我很难用添加了注释和标题的Jpeg文件覆盖现有的Jpeg文件,但是我在删除文件时遇到了错误,所以我不知道该如何处理该文件,因为我已经尝试过处理该文件,但由于我处理得太早,所以无法保存它,但我无法保存它,因为现有的文件名没有被删除,所以我现在有点卡在中间。
这是我的密码:
public string EditComment(string OriginalFilepath, string newFilename)
{
image = System.Drawing.Image.FromFile(OriginalFilepath);
PropertyItem propItem = image.PropertyItems[0];
using (var file = System.Drawing.Image.FromFile(OriginalFilepath))
{
propItem.Id = 0x9286; // this is the id for 'UserComment'
propItem.Type = 2;
propItem.Value = System.Text.Encoding.UTF8.GetBytes("HelloWorld\0");
propItem.Len = propItem.Value.Length;
file.SetPropertyItem(propItem);
PropertyItem propItem1 = file.PropertyItems[file.PropertyItems.Count() - 1];
file.Dispose();
image.Dispose();
string filepath = Filepath;
if (File.Exists(@"C:\Desktop\Metadata"))
{
System.IO.File.Delete(@"C:\Desktop\Metadata");
}
string newFilepath = filepath + newFilename;
file.Save(newFilepath, ImageFormat.Jpeg);//error appears here
return filepath;
}
}显示的错误如下:
“System.ArgumentException”类型的异常发生在System.Drawing.dll中,但未在用户代码中处理 附加信息:参数无效。
发布于 2018-02-02 09:41:31
问题是从文件中打开图像会锁定文件。您可以通过将文件读入一个字节数组,创建一个内存流,然后从该流打开图像来解决这个问题:
public string EditComment(string originalFilepath, string newFilename)
{
Byte[] bytes = File.ReadAllBytes(originalFilepath);
using (MemoryStream stream = new MemoryStream(bytes))
using (Bitmap image = new Bitmap(stream))
{
PropertyItem propItem = image.PropertyItems[0];
// Processing code
propItem.Id = 0x9286; // this is the id for 'UserComment'
propItem.Type = 2;
propItem.Value = System.Text.Encoding.UTF8.GetBytes("HelloWorld\0");
propItem.Len = propItem.Value.Length;
image.SetPropertyItem(propItem);
// Not sure where your FilePath comes from but I'm just
// putting it in the same folder with the new name.
String newFilepath;
if (newFilename == null)
newFilepath = originalFilePath;
else
newFilepath = Path.Combine(Path.GetDirectory(originalFilepath), newFilename);
image.Save(newFilepath, ImageFormat.Jpeg);
return newFilepath;
}
}确保您的不像在测试代码中那样在using块中释放图像对象。不仅using块确实存在,因此不需要手动处理,而且还很难将映像保存到内存中不再存在的磁盘中。类似地,您似乎两次从文件中打开图像。我只是假设所有这些都是为了解决问题而做的实验,但一定要把它们清理干净。
打开图像时要记住的基本规则如下:
Image创建的将在图像对象的生命周期内锁定该文件。对象,该对象防止文件被覆盖或删除,直到图像被释放。Image 将需要流在映像对象的整个生命周期内保持打开状态。创建的将需要流在映像对象的整个生命周期内保持打开状态。对象。与文件不同的是,没有什么能有效地执行此操作,但是在流关闭后,图像在保存、克隆或以其他方式操作时会出现错误。与一些人所认为的相反,对图像对象的基本.Clone()调用不会改变这种行为。克隆的对象仍然保留对原始源的引用。
注意,如果您实际上想要一个不包含在using块PixelFormat中的可用图像对象,那么有效地对原始图像进行完整的数据克隆。(注意:我认为这不适用于动画GIF文件)这样做后,您可以安全地释放原始文件,只需使用新的干净克隆版本。
实际上,还有一些其他的解决办法可以将图像取出来,但我看到的大多数方法都不是最优的。以下是解决锁定问题的两个最常见的有效解决方案:
Bitmap构造函数从从文件加载的图像中创建新的Bitmap(Image image)。这个新对象将没有指向该文件的链接,因此您可以自由地释放锁定该文件的对象。这是完美的,但它将图像的颜色深度更改为32位的ARGB,这可能是不想要的。但是,如果您只需要在UI上显示一个图像,这是一个很好的解决方案。MemoryStream,而不是在using块中创建,使流按需要打开。让溪流开放对我来说并不是个好主意。虽然有人说过,由于MemoryStream只是由一个简单的数组而不是外部资源支持,垃圾收集器显然可以很好地处理这种情况.我还看到一些人使用System.Drawing.ImageConverter从字节进行转换,但是我调查了这个过程的内部,它所做的实际上与这里的最后一个方法相同,该方法保留了一个内存流。
https://stackoverflow.com/questions/48579643
复制相似问题