Reading metadata from images in WPF

2019-02-14 14:25发布

I'm aware that WPF allows you to use images that require WIC codecs to view (for the sake of argument, say a digital camera RAW file); however I can only see that it lets you show the image natively, but I can't see anyway of getting at the meta-data (for example, the exposure time).

It obviously can be done, as Windows Explorer shows it, but is this exposed through the .net API or do you reckon that it is just down to calling the native COM interfaces

2条回答
可以哭但决不认输i
2楼-- · 2019-02-14 14:45

Check out my Intuipic project. In particular, the BitmapOrientationConverter class, which reads metadata to determine the image's orientation:

using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
    BitmapFrame bitmapFrame = BitmapFrame.Create(fileStream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
    BitmapMetadata bitmapMetadata = bitmapFrame.Metadata as BitmapMetadata;

    if ((bitmapMetadata != null) && (bitmapMetadata.ContainsQuery(_orientationQuery)))
    {
        object o = bitmapMetadata.GetQuery(_orientationQuery);

        if (o != null)
        {
            //refer to http://www.impulseadventure.com/photo/exif-orientation.html for details on orientation values
            switch ((ushort) o)
            {
                case 6:
                    return 90D;
                case 3:
                    return 180D;
                case 8:
                    return 270D;
            }
        }
    }
}
查看更多
Fickle 薄情
3楼-- · 2019-02-14 14:47

Whilst WPF does provide these APIs, they're not very friendly and they're not particularly fast. I suspect they're doing a lot of interop.

I maintain a simple open-source library for extracting metadata from images and videos. It's 100% C# with no P/Invoke.

// 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 orientation
var orientation = subIfdDirectory?.GetInt(ExifDirectoryBase.TagOrientation);

switch (orientation)
{
    case 6:
        return 90D;
    case 3:
        return 180D;
    case 8:
        return 270D;
}

In my benchmarks, this is 17 times faster than the WPF API. If you only want Exif from JPEG, use the following and it's over 30 times faster:

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

The metadata-extractor library is available via NuGet and the code's on GitHub.

Credit is due to the many contributors who've helped the project since it started in 2002.

查看更多
登录 后发表回答