我怎样才能知道一张照片是什么时候用运行在 Vista 上的 C# 实际拍摄的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/180030/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I find out when a picture was actually taken in C# running on Vista?
提问by sepang
In windows XP "FileInfo.LastWriteTime" will return the date a picture is taken - regardless of how many times the file is moved around in the filesystem.
在 Windows XP 中,“FileInfo.LastWriteTime”将返回拍摄照片的日期 - 无论文件在文件系统中移动了多少次。
In Vista it instead returns the date that the picture is copied from the camera.
在 Vista 中,它会返回从相机复制图片的日期。
How can I find out when a picture is taken in Vista? In windows explorer this field is referred to as "Date Taken".
如何知道在 Vista 中拍摄照片的时间?在 Windows 资源管理器中,此字段称为“拍摄日期”。
采纳答案by kDar
Here's as fast and clean as you can get it. By using FileStream, you can tell GDI+ not to load the whole image for verification. It runs over 10 × as fast on my machine.
这里尽可能快速和干净。通过使用 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);
}
}
And yes, the correct id is 36867, not 306.
是的,正确的 ID 是 36867,而不是 306。
The other Open Source projects below should take note of this. It is a hugeperformance hit when processing thousands of files.
下面的其他开源项目应该注意这一点。在处理数千个文件时,这是一个巨大的性能损失。
回答by DaveK
With WPF and C# you can get the Date Taken property using the BitmapMetadata class:
使用 WPF 和 C#,您可以使用 BitmapMetadata 类获取 Date Taken 属性:
回答by Miles
you'll have to check the EXIF information from the picture. I don't think with regular .Net functions you'll know when the picture was taken.
您必须检查图片中的 EXIF 信息。我不认为使用常规的 .Net 函数你会知道照片是什么时候拍摄的。
It might get a little complicated...
可能有点复杂……
回答by Paul Hammond
There will be EXIF data embedded in the image. There are a ton of examples on the web if you search for EXIF and C#.
图像中将嵌入 EXIF 数据。如果您搜索 EXIF 和 C#,网络上有大量示例。
回答by James Curran
In windows XP "FileInfo.LastWriteTime" will return the date a picture is taken - regardless of how many times the file is moved around in the filesystem.
在 Windows XP 中,“FileInfo.LastWriteTime”将返回拍摄照片的日期 - 无论文件在文件系统中移动了多少次。
I have great doubts XP was actually doing that. More likely the tool you used to copy the image from the camera to you hard disk was reseting the File Modified Date to the image's Date Taken.
我非常怀疑 XP 是否真的这样做了。更有可能的是,您用于将图像从相机复制到硬盘的工具是将文件修改日期重置为图像的拍摄日期。
回答by sepang
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);
回答by Peter Redei
//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;
}
}
回答by Drew Noakes
I maintained a simple open-source librarysince 2002 for extracting metadata from image/video files.
自 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);
In my benchmarks, this code runs over 12 times faster than Image.GetPropertyItem
, and around 17 times faster than the WPF JpegBitmapDecoder
/BitmapMetadata
API.
在我的基准测试中,此代码的运行Image.GetPropertyItem
速度比 WPF JpegBitmapDecoder
/ BitmapMetadata
API快12 倍以上,比 WPF / API快 17 倍左右。
There's a tonne of extra information available from the library such as camera settings (F-stop, ISO, shutter speed, flash mode, focal length, ...), image properties (dimensions, pixel configurations) and other things such as GPS positions, keywords, copyright info, etc.
库中提供了大量额外信息,例如相机设置(F-stop、ISO、快门速度、闪光模式、焦距等)、图像属性(尺寸、像素配置)以及 GPS 位置等其他信息、关键字、版权信息等。
If you're only interested in the metadata, then using this library is very fast as it doesn't decode the image (i.e. bitmap). You can scan thousands of images in a few seconds if you have fast enough storage.
如果您只对元数据感兴趣,那么使用这个库会非常快,因为它不解码图像(即位图)。如果您有足够快的存储空间,您可以在几秒钟内扫描数千张图像。
ImageMetadataReader
understands many files types (JPEG, PNG, GIF, BMP, TIFF, PCX, WebP, ICO, ...). If you knowthat you're dealing with JPEG, and you onlywant Exif data, then you can make the process even faster with the following:
ImageMetadataReader
了解许多文件类型(JPEG、PNG、GIF、BMP、TIFF、PCX、WebP、ICO 等)。如果您知道您正在处理 JPEG,并且您只需要 Exif 数据,那么您可以通过以下方式加快处理速度:
var directories = JpegMetadataReader.ReadMetadata(stream, new[] { new ExifReader() });
The metadata-extractorlibrary is available via NuGetand the code's on GitHub. Thanks to all the amazing contributors who have improved the library and submitted test images over the years.
该元数据提取库通过可用的NuGet和代码是在GitHub上。感谢所有出色的贡献者,他们多年来改进了库并提交了测试图像。