我怎样才能知道在Vista上运行C#时实际拍摄的图片?

时间:2008-10-07 19:43:12

标签: c#

在Windows XP中,“FileInfo.LastWriteTime”将返回拍摄照片的日期 - 无论文件在文件系统中移动多少次。

在Vista中,它会返回从相机复制照片的日期。

如何查看Vista中拍摄照片的时间?在Windows资源管理器中,此字段称为“采取日期”。

8 个答案:

答案 0 :(得分:91)

这里尽可能快速而干净。通过使用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。

下面的其他开源项目应该注意到这一点。处理数千个文件时,这是一个巨大的性能!

答案 1 :(得分:10)

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);

答案 2 :(得分:7)

自2002年以来,我一直保留simple open-source library,用于从图像/视频文件中提取元数据。

// 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倍。

图书馆提供了大量额外信息,例如相机设置(F-stop,ISO,快门速度,闪光模式,焦距......),图像属性(尺寸,像素配置)等等作为GPS位置,关键字,版权信息等

如果您只对元数据感兴趣,那么使用此库非常快,因为它不会解码图像(即位图)。如果存储空间足够快,您可以在几秒钟内扫描数千张图像。

ImageMetadataReader了解许多文件类型(JPEG,PNG,GIF,BMP,TIFF,PCX,WebP,ICO ......)。如果您知道您正在处理JPEG,并且想要Exif数据,那么您可以使用以下内容更快地完成此过程:

var directories = JpegMetadataReader.ReadMetadata(stream, new[] { new ExifReader() });

元数据提取器库可通过NuGetcode's on GitHub获得。感谢所有出色的贡献者,他们多年来改进了图书馆并提交了测试图像。

答案 3 :(得分:5)

使用WPF和C#,您可以使用BitmapMetadata类获取Date Taken属性:

MSDN - BitmapMetada

WPF and BitmapMetadata

答案 4 :(得分:2)

  

在Windows XP中“FileInfo.LastWriteTime”   将返回图片的日期   采取 - 无论多少次   文件在。中移动   文件系统。

我非常怀疑XP实际上是这么做的。您用于将图像从相机复制到硬盘的工具更可能是将文件修改日期重置为图像的拍摄日期。

答案 5 :(得分:1)

您必须检查图片中的EXIF信息。我不认为你拍摄照片时会知道普通的.Net功能。

可能会有点复杂......

答案 6 :(得分:1)

图像中将嵌入EXIF数据。如果您搜索EXIF和C#,网上会有大量示例。

答案 7 :(得分:0)

    //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;
        }
    }