【问题标题】:Reading data metadata from JPEG, XMP or EXIF in C#在 C# 中从 JPEG、XMP 或 EXIF 读取数据元数据
【发布时间】:2010-02-17 13:26:50
【问题描述】:

我一直在寻找一种从 C# 中的 JPEG 文件中读取元数据(特别是拍摄日期)的体面方法,但我发现有点短。据我所知,现有信息显示如下代码;

BitmapMetadata bmd = (BitmapMetadata)frame.Metadata;
string a1 = (string)bmd.GetQuery("/app1/ifd/exif:{uint=36867}");

但在我的无知中,我不知道 GetQuery() 将返回什么元数据,或者传递什么。

我想先尝试读取 XMP,如果 XMP 不存在则回退到 EXIF。有没有一种简单的方法可以做到这一点?

谢谢。

【问题讨论】:

  • 您对 IPTC 元数据不感兴趣吗? Jpeg 文件可以包含三种不同类型的元数据,其中可以包括拍摄日期字段。

标签: c# metadata jpeg exif xmp


【解决方案1】:

以下似乎工作得很好,但如果有什么不好的地方,我会很感激任何 cmets。

    public string GetDate(FileInfo f)
    {
        using(FileStream fs = new FileStream(f.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            BitmapSource img = BitmapFrame.Create(fs);
            BitmapMetadata md = (BitmapMetadata)img.Metadata;
            string date = md.DateTaken;
            Console.WriteLine(date);
            return date;
        }
    }

【讨论】:

  • 在微软实现BitmapMetaData.DateTaken 的人是个完美的白痴! 1. 为什么是stringget 的最后一行是DateTime.ToString()set 的第一行是Convert.ToDateTime()。和 2.:get 返回特定于文化的字符串,set 期望不区分文化的字符串。微软有质量管理吗???
  • @springy76,实际上你有点不公平。在 Exif 数据中,日期表示为字符串。有些相机使用与其他相机不同的格式,因此不能保证 MS 可以编写代码来成功解析它遇到的任何日期字符串。至少它将原始字符串传递给您,以便您可以调试正在发生的事情。
  • @Lijo,我不知道BitmapMetadata 是否提供 GPS 数据,但如果您愿意,可以轻松使用my library
  • @tsvallender,您应该处置FileStream 对象。
  • @DrewNoakes 不,我不是:使用 Reflector/ILSpy/JustDecompile/DotPeek 并自己查看BitmapMetaData.DateTaken:WIC 已经为此提供了二进制日期时间值(System.Runtime.InteropServices.ComTypes .FILETIME 结构计算自 1601 年 1 月 1 日以来 100 纳秒间隔的数量),但是这个属性完全搞砸了(请重新阅读我已经写过的内容)。
【解决方案2】:

我最近将我长期使用的开源 Java 库移植到 .NET,它支持 XMP、Exif、ICC、JFIF 和多种图像格式中的更多类型的元数据。它一定会实现你所追求的。

https://github.com/drewnoakes/metadata-extractor-dotnet

var directories = ImageMetadataReader.ReadMetadata(imagePath);
var subIfdDirectory = directories.OfType<ExifSubIfdDirectory>().FirstOrDefault();
var dateTime = subIfdDirectory?.GetDescription(ExifDirectoryBase.TagDateTime);

该库还支持 XMP 数据,通过用于 Java 的 Adob​​e XmpCore 库的 C# 端口。

https://github.com/drewnoakes/xmp-core-dotnet

【讨论】:

  • 如果你需要原始的捕获日期,最后一行应该是string dateTime = subIfdDirectory?.GetDescription(ExifDirectoryBase.TagDateTimeOriginal); 或者你可以在DateTime中使用它来获取它?对象DateTime? dateTime = subIfdDirectory?.GetDateTime(ExifDirectoryBase.TagDateTimeOriginal);
  • @drew-noakes 那东西可以处理 Picassa 区域/人脸数据绘制吗?我可以确认他的库确实可以很好地满足您在此处要求的基础知识。
  • @twobob 我使用 Picasa 已经有一段时间了,但我相信它会将元数据存储在自己的数据库或附属文件中。 MetadatExtractor 尚不支持边车文件,但如果实现得体,我会接受拉取请求。
  • 您好。我使用了下面的 BrutXmp 的一个变体,只是把它全部撕掉了。 (可以选择将数据存储在 jpgs 中,它在选项中,并将以前外部存储的数据写入文件 - 也在选项中)这样做,没有库支持。是的,Unity3d)参考:gist.github.com/twobob/ea6cb3b7c7d83c1b62513bcd67c0d39c
  • 其实,这个问题stackoverflow.com/questions/23595560/… 也很有用,如果有人希望沿着我现在意识到的元提取器路线走下去
【解决方案3】:

如果您在使用 XMP jn jpeg 时遇到问题,那么这很有效。这不是白白说的残酷!

public class BrutalXmp
{
    public XmlDocument ExtractXmp(byte[] jpegBytes)
    {
        var asString = Encoding.UTF8.GetString(jpegBytes);
        var start = asString.IndexOf("<x:xmpmeta");
        var end = asString.IndexOf("</x:xmpmeta>") + 12;
        if (start == -1 || end == -1)
            return null;
        var justTheMeta = asString.Substring(start, end - start);
        var returnVal = new XmlDocument();
        returnVal.LoadXml(justTheMeta);
        return returnVal;
    }
}

【讨论】:

  • 这非常适合支持非常有限的情况。非常感谢这一点。只需应用GetElementsByTagName("rdf:Description") 并小心一点,就可以提取 Picassa3 人脸区域数据。最高职位。
  • 有时我想知道为什么通常的框架不提供这样简单的东西。在不阅读完整流的情况下做类似事情的任何提示?
  • 为了获取所有元数据(不仅是 xmp),此选项有效:codeproject.com/Articles/66328/…
【解决方案4】:

我认为您正在做的是一个很好的解决方案,因为 System.DateTaken 处理程序会自动应用 Photo metadata policies 回退到其他命名空间以查找值是否存在。

【讨论】:

    【解决方案5】:

    我的company 制作了一个包含 XMP 和 EXIF 解析器的 .NET toolkit

    典型的流程是这样的:

    XmpParser parser = new XmpParser();
    System.Xml.XmlDocument xml = (System.Xml.XmlDocument)parser.ParseFromImage(stream, frameIndex);
    

    对于 EXIF,你会这样做:

    ExitParser parser = new ExifParser();
    ExifCollection exif = parser.ParseFromImage(stream, frameIndex);
    

    显然,对于 JPEG,frameIndex 将为 0。

    【讨论】:

    猜你喜欢
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 2017-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多