您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 0浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

CompactExifLib:访问JPEG文件中的EXIF标签

寒冰屋 发布时间:2021-05-31 23:42:26 ,浏览量:0

目录

介绍

背景

演示应用程序

使用代码

读写标签

标签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             
关注
打赏
1665926880
查看更多评论
0.1725s