数码相机拍摄的照片通常会存储一些元数据,目前主要采用Exif标准,Exif标准是可交换图像文件的缩写,是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。
c#从相机拍摄的照片中提取拍摄时间,会用到PropertyItem类,该类的ID属性代表数据项ID,表示到底该项指的时什么数据,比如拍摄时间、分辨率、宽度、高度、相机类型等等。该类的Value属性代表具体属性数值,为字节数组类型。
拍摄时间数据对应的ID=0x9003,拍摄时间数据Value存储为ASCII字符串,该字符串以null结尾(c#中用'\0'表示)。比如2018:08:01 14:12:12,最后一个字符是null(c#中表示为'\0')。
提取出来的时间字符串数组,可以用System.Text.Encoding.ASCII.GetString()转换为string类型。需要注意的时,需要把末尾的'\0'剔除掉,可以用Trim('\0')方法,也可以用TrimEnd('\0')方法。如果没有剔除,则后面无法转换为DateTime类型就会麻烦一些。(注:不是不可行,仅需要在时间格式字符串中增加‘\0'字符,如"yyyy:MM:dd HH:mm:ss\0",经测试是可以成功转换的)。
static void Main(string[] args)
{
try
{
// Create an Image object.
Image theImage = Image.FromFile("e:\\IMG_1227.JPG");
// Get the PropertyItems property from image.
PropertyItem[] propItems = theImage.PropertyItems;
//获取表示时间的属性项PropertyItem
PropertyItem propItem = theImage.GetPropertyItem(0x9003); //Id为0x9003表示拍照的时间
//获取时间的存储数值,该数值为字符串数组
Byte[] propItemValue = propItem.Value;
string dateTimeStr = System.Text.Encoding.ASCII.GetString(propItemValue).Trim('\0');
//说明:常见相机的metadata的数据符合Exif标准。Exif标准是可交换图像文件的缩写,是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。
//时间数据在metadata中存储为ASCII字符串,并以null结尾('\0'结尾)。比如2018:08:01 14:12:12,最后一个字符是null(c#中表示为'\0')。
//时间数据的日期与时间之间用一个空格隔开,总共占据20位。
//利用System.Text.Encoding.ASCII.GetString()方法将时间字符串数组转换为string的时候,末尾的'\0'是不会删除的,且通过无参数Trim()是无法剔除的,比如带有参数Trim('\0')
DateTime dt = DateTime.ParseExact(dateTimeStr, "yyyy:MM:dd HH:mm:ss",CultureInfo.InvariantCulture);
//CultureInfo.InvariantCulture指不针对特定的某个地区
//MM表示两位数的月份;mm表示两位数的分钟;HH表示24小时制的小时,如果用hh表示12小时制的小时
Console.WriteLine($"ID={Convert.ToString(propItem.Id,16)} DateTime={dt}");
//重新格式化时间
string newDTstr = dt.ToString("yyyy年MM月dd日 HH时mm分ss秒");
Console.WriteLine($"ID={Convert.ToString(propItem.Id, 16)} DateTime={newDTstr}");
theImage.Dispose();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
执行结果如下:
ID=9003 DateTime=2018/8/7 17:41:21
ID=9003 DateTime=2018年08月07日 17时41分21秒