Mar*_*233 4 c# asp.net jpeg metadata
我已经建立了一个程序,可以通过它插入注释和图像的标题,System.Image.Drawing因此,我很难尝试用添加了注释和标题的文件覆盖现有的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;
}
}
Run Code Online (Sandbox Code Playgroud)
显示的错误是:
System.Drawing.dll中发生类型'System.ArgumentException'的异常,但未在用户代码中处理
附加信息:参数无效。
问题是从文件打开图像会锁定文件。通过将文件读入字节数组,从中创建一个内存流,然后从该流中打开图像,可以解决此问题:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
确保不要像using在测试代码中那样将图像对象放置在块内。该using块不仅完全存在,因此您不必手动处理,而且很难将映像保存到内存中不再存在的磁盘中。同样,您似乎两次从文件打开图像。我只是假设所有这些都是尝试解决该问题的实验,但是请确保将其清理干净。
打开图像时要记住的基本规则如下:
Image由文件创建的对象将在图像对象的生命周期内锁定文件,从而防止文件被覆盖或删除,直到处理完图像为止。Image从流创建的对象将需要流在图像对象的整个生命周期中保持打开状态。与文件不同,没有有效地强制执行此操作,但是在关闭流之后,在保存,克隆或进行其他操作时,映像将产生错误。与某些人的看法相反,.Clone()对图像对象的基本调用不会更改此行为。克隆的对象仍将保留对原始源的引用。
注意,如果您实际上想要一个不包含在using块中的可用图像对象,则可以使用LockBits并将Marshal.Copy图像对象的字节数据复制到具有相同尺寸和相同大小的新图像中PixelFormat,从而有效地完成的完整数据克隆。原始图像。(注意:我认为这不适用于GIF动画文件)之后,您可以安全地处置原始文件,而只需使用全新的干净克隆版本即可。
还有其他一些变通办法可以实际取出图像,但是我见过的大多数变通办法都不是最佳的。这些是锁定问题的两种最常见的其他有效解决方法:
Bitmap使用Bitmap(Image image)构造函数根据从文件加载的图像创建新图像。这个新对象将没有指向该文件的链接,从而使您可以自由处置锁定该文件的对象。这可以很好地工作,但是可以将图像的颜色深度更改为32位ARGB,这可能是不希望的。但是,如果只需要在UI上显示图像,这是一个很好的解决方案。MemoryStream按照我的代码所示创建一个,但不要在一个代码using块中创建一个,让流根据需要保持打开状态。在我看来,让流保持开放并不是一个好主意。尽管有人说过,由于a MemoryStream只是由一个简单的数组支持,而不是一些外部资源,所以垃圾收集器显然可以很好地处理这种情况。我也看到有人用它System.Drawing.ImageConverter来转换字节,但是我研究了该过程的内部,实际上它的作用与这里的最后一个方法相同,后者使内存流保持打开状态。
| 归档时间: |
|
| 查看次数: |
554 次 |
| 最近记录: |