目录
介绍
背景
演示应用程序
使用代码
读写标签
标签ID和图像文件目录(IFD)
标签类型
整数
数组标签
字符串
有理数
日期和时间
原始数据和字节顺序
移除标签
加载和保存EXIF数据
GPS数据
缩图图片
JPEG 和 TIFF 文件之间的差异
其他有用的方法
参考
- 下载源31.2 KB
几乎所有照片和智能手机相机都使用EXIF标准来存储有关图像的信息。EXIF数据由标签列表组成,每个标签存储有关图像的信息。例如,日期和时间是在拍摄图像时或拍摄图像的GPS位置时存储的。使用特殊的EXIF编辑器,可以在拍摄照片后添加说明文字。
本文介绍如何使用C#库在JPEG图像文件中读取和写入EXIF标签。尽管EXIF标记也可以存储在TIFF图像文件中,但此处未考虑。
背景有许多用于读取JPEG文件的EXIF标签的第三方库,.NET Framework还提供了用于访问EXIF标签的.NET类。但是大多数第三方库都无法将EXIF标签写入JPEG文件。在.NET Framework中,存在用于读取和写入EXIF标记的类。但是它们有很多开销,因此它们非常慢并且不是无损的,即,在加载JPEG图像时未压缩JPEG图像,而当使用新的或更改的EXIF标签保存JPEG图像时,将对其进行新的压缩。因此,我决定开发一个名为CompactExifLib的新库。
例如,从400张JPEG照片中读取了拍摄日期的EXIF标签,并测量了以毫秒为单位的时间,并将其记录在下表中:
WPF类BitmapMetadata
库CompactExifLib
速度因数
1774毫秒
40.2毫秒
44.1
在第一列中,使用.NET Framework的WPF类BitmapMetadata读取EXIF标记,在第二列中使用库CompactExifLib。如您所见,该库CompactExifLib比.NET Framework的库快44倍以上。
CompactExifLib库的好处:
- 速度非常快,因为可以使用基本文件读写方法直接访问EXIF标记
- 无损图像保存。保存EXIF标签时,JPEG图像矩阵完全不变。
- 完全用C#编写,不需要DLL
- 可以与Windows窗体和WPF应用程序一起使用
- 可与.NET Framework 4.0中的许多.NET版本一起使用
在下载包中,有一个演示应用程序,其中列出了JPEG图像文件的所有EXIF标签。
该CompactExifLib库由一个单个的.cs文件组成。因此,使用该库非常容易,只需将文件ExifData.cs添加到您的项目中,然后使用using命令插入名称空间CompactExifLib。该库中的主要类是保存图像文件的完整EXIF数据的ExifData类。例如,要读取照片“c:\temp\testimage.jpg”的日期,可以使用以下代码:
using CompactExifLib;
...
ExifData TestExif;
DateTime DateTaken;
try
{
TestExif = new ExifData(@"c:\temp\testimage.jpg");
if (TestExif.GetTagValue(ExifTag.DateTimeOriginal, out DateTaken))
{
// The date taken is now available in variable "DateTaken"
}
}
catch
{
// Error occurred while reading image file
}
ExifData构造函数的声明:
public ExifData(string FileNameWithPath, ExifLoadOptions Options = 0);
并从指定的图像文件加载EXIF数据。如果文件没有EXIF数据块,则返回一个空块。如果加载失败,则会引发异常。可能的原因是:
- 该文件不存在。
- 对文件的访问被拒绝。
- 该文件包含非法内容,例如,它不是有效的JPEG文件。
该ExifData构造函数将图像文件的EXIF数据完全复制在内存中,并立即关闭该文件。然后,对EXIF数据的存储副本执行所有读取和写入访问。当将EXIF数据写回图片文件时,必须调用ExifData的Save方法:
public void Save(string DestFileNameWithPath = null,
ExifSaveOptions SaveOptions = ExifSaveOptions.None);
如果参数NewFileNameWithPath为null或省略,则该Save方法将覆盖现有的图像文件。也可以通过在参数NewFileNameWithPath中传递文件名来将图像另存为新文件名。如果无法保存文件,该Save方法将引发异常。可能的原因是:
- 该文件被写保护。
- 对文件的访问被拒绝。
- 该文件不再可用,例如已被删除或已删除该卷。
- EXIF数据太大。EXIF数据的最大大小为65526字节。
关于加载和保存EXIF数据以及使用流的可能性的更详细的描述可以在下面的“加载和保存EXIF数据”部分中找到。
在以下示例代码中,更改了上一示例中图像的拍摄日期,然后将EXIF数据写回到图像文件中。
DateTaken.AddHours(2); // Add 2 hours to the time stamp
TestExif.SetTagValue(Exifag.DateTimeOriginal, DateTaken);
try
{
TestExif.Save();
}
catch
{
// Error occurred while writing image file
}
标签ID和图像文件目录(IFD)
标签由称为标签ID的16位值定义。以下示例代码显示了一些标签ID定义。
public enum ExifTagId
{
...
Orientation = 0x0112,
ImageDescription = 0x010E,
DateTimeOriginal = 0x9003,
...
}
但是标签ID不足以指定标签。另外,必须指定IFD。EXIF标签分为几个部分,称为图像文件目录(IFD)。如果要读取或写入标签,则必须指定正确的IFD。EXIF标准[EXIF2.32]中定义了应将哪个IFD用于标签。为了指定IFD,可以使用以下常量。
public enum ExifIfd
{
PrimaryData = 0,
PrivateData = 1,
GpsInfoData = 2,
Interoperability = 3,
ThumbnailData = 4
}
IFD PrimaryData是EXIF数据的主要IFD,它包含基本图像数据,而IFD PrivateData包含其他图像数据。IFD GpsInfoData存储拍摄图像的位置的GPS数据。Interoperability供内部使用,并且ThumbnailData存储缩略图的EXIF数据,缩略图是小的预览图像。
为了使指定EXIF标签更容易,这里有一些组合常量,它们的值的高16位包含IFD,低16位包含标签ID。
public enum ExifTag
{
...
Orientation = (ExifIfd.PrimaryData
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?


微信扫码登录