在 C# 中从 JPEG、XMP 或 EXIF 读取数据元数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2280948/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:59:37  来源:igfitidea点击:

Reading data metadata from JPEG, XMP or EXIF in C#

c#metadatajpegexifxmp

提问by tsvallender

I've been looking around for a decent way of reading metadata (specifically, the date taken) from JPEG files in C#, and am coming up a little short. Existing information, as far as I can see, shows code like the following;

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

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

But in my ignorance I have no idea what bit of metadata GetQuery() will return, or what to pass it.

但由于我的无知,我不知道 GetQuery() 会返回什么元数据,或者传递什么。

I want to attempt reading XMP first, falling back to EXIF if XMP does not exist. Is there a simple way of doing this?

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

Thanks.

谢谢。

采纳答案by tsvallender

The following seems to work nicely, but if there's something bad about it, I'd appreciate any comments.

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

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

回答by plinth

My companymakes a .NET toolkitthat includes XMP and EXIF parsers.

我的公司制作了一个包含 XMP 和 EXIF 解析器的 .NET工具包

The typical process is something like this:

典型的流程是这样的:

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

for EXIF you would do this:

对于 EXIF,你会这样做:

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

obviously, frameIndex would be 0 for JPEG.

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

回答by muruge

I think what you are doing is a good solution because the System.DateTaken handler automatically apply Photo metadata policiesof falling back to other namespaces to find if a value exist.

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

回答by Drew Noakes

I've ported my long-time open-source Java library to .NET recently, and it supports XMP, Exif, ICC, JFIF and many more types of metadata across a range of image formats. It will definitely achieve what you're after.

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

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

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

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

This library also supports XMP data, via a C# port of Adobe's XmpCore library for Java.

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

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

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

回答by bbsimonbb

If you're struggling with XMP jn jpeg, this works. It's not called brutal for nothing!

如果您正在为 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;
    }
}