我怎样才能知道照片实际上是在 Vista 上运行的 C# 中拍摄的
本文关键字:运行 Vista 实际上 照片 | 更新日期: 2023-09-27 17:47:21
在Windows XP中,"FileInfo.LastWriteTime"将返回照片的拍摄日期 - 无论文件在文件系统中移动了多少次。
在 Vista 中,它会返回从相机复制图片的日期。
如何知道照片是在Vista中拍摄的?在 Windows 资源管理器中,此字段称为"拍摄日期"。
这是尽可能快速和干净的。通过使用 FileStream,您可以告诉 GDI+ 不要加载整个图像进行验证。它在我的机器上运行速度超过 10 ×。
//we init this once so that if the function is repeatedly called
//it isn't stressing the garbage man
private static Regex r = new Regex(":");
//retrieves the datetime WITHOUT loading the whole image
public static DateTime GetDateTakenFromImage(string path)
{
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
using (Image myImage = Image.FromStream(fs, false, false))
{
PropertyItem propItem = myImage.GetPropertyItem(36867);
string dateTaken = r.Replace(Encoding.UTF8.GetString(propItem.Value), "-", 2);
return DateTime.Parse(dateTaken);
}
}
是的,正确的id是36867,而不是306。
下面的其他开源项目应该注意这一点。在处理数千个文件时,这是一个巨大的性能下降。
自 2002 年以来,我维护了一个简单的开源库,用于从图像/视频文件中提取元数据。
// Read all metadata from the image
var directories = ImageMetadataReader.ReadMetadata(stream);
// Find the so-called Exif "SubIFD" (which may be null)
var subIfdDirectory = directories.OfType<ExifSubIfdDirectory>().FirstOrDefault();
// Read the DateTime tag value
var dateTime = subIfdDirectory?.GetDateTime(ExifDirectoryBase.TagDateTimeOriginal);
在我的基准测试中,此代码的运行速度比 Image.GetPropertyItem
快 12 倍以上,比 WPF JpegBitmapDecoder
/BitmapMetadata
API 快约 17 倍。
库中有大量额外的信息,例如相机设置(光圈,ISO,快门速度,闪光模式,焦距等),图像属性(尺寸,像素配置)以及其他内容,例如GPS位置,关键字,版权信息等。
如果您只对元数据感兴趣,那么使用此库非常快,因为它不会解码图像(即位图)。如果您有足够快的存储空间,您可以在几秒钟内扫描数千张图像。
ImageMetadataReader
理解许多文件类型(JPEG,PNG,GIF,BMP,TIFF,PCX,WebP,ICO等)。如果您知道您正在处理 JPEG,并且您只需要 Exif 数据,那么您可以通过以下方法加快该过程:
var directories = JpegMetadataReader.ReadMetadata(stream, new[] { new ExifReader() });
元数据提取器库可通过 NuGet 获得,代码位于 GitHub 上。感谢多年来改进库并提交测试图像的所有出色贡献者。
Image myImage = Image.FromFile(@"C:'temp'IMG_0325.JPG");
PropertyItem propItem = myImage.GetPropertyItem(306);
DateTime dtaken;
//Convert date taken metadata to a DateTime object
string sdate = Encoding.UTF8.GetString(propItem.Value).Trim();
string secondhalf = sdate.Substring(sdate.IndexOf(" "), (sdate.Length - sdate.IndexOf(" ")));
string firsthalf = sdate.Substring(0, 10);
firsthalf = firsthalf.Replace(":", "-");
sdate = firsthalf + secondhalf;
dtaken = DateTime.Parse(sdate);
使用 WPF 和 C#,可以使用 BitmapMetadata 类获取 Date Taken 属性:
MSDN - BitmapMetada
WPF 和位图元数据
在 Windows XP 中 "FileInfo.LastWriteTime" 将返回图片的日期 服用 - 无论多少次 文件在 文件系统。
我非常怀疑XP是否真的这样做了。 您用于将图像从相机复制到硬盘的工具更有可能是将文件修改日期重置为图像的拍摄日期。
你必须检查图片中的EXIF信息。我不认为使用常规的.Net功能,您会知道照片是何时拍摄的。
它可能会变得有点复杂...
图像中将嵌入EXIF数据。 如果你搜索EXIF和C#,网络上有很多例子。
//retrieves the datetime WITHOUT loading the whole image
public static DateTime GetDateTakenFromImage(string path)
{
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
using (Image myImage = Image.FromStream(fs, false, false))
{
PropertyItem propItem = null;
try
{
propItem = myImage.GetPropertyItem(36867);
}
catch { }
if (propItem != null)
{
string dateTaken = r.Replace(Encoding.UTF8.GetString(propItem.Value), "-", 2);
return DateTime.Parse(dateTaken);
}
else
return new FileInfo(path).LastWriteTime;
}
}