使用 MetadataExtractor GetDescription 获取方向时出现问题

Problem obtaining Orientation using MetadataExtractor GetDescription

Objective

我想“纠正”图像的方向。我的计划是从与图像一起存储的 Exif 数据中提取方向,并使用它来通知图像的重新定位。

问题

可能是我,但对于这个特定的 Exif 属性,GetDescription(或 GetString)只是 returns null;我尝试过的所有其他属性 (x15) return 一个值。在下面的示例代码(控制台应用程序)中,“方法 1”使用首选且高效的 GetDescription 方法来获取图像方向,而“方法 2”使用低效的 foreach 循环来遍历目录和搜索方向的标签。

using MetadataExtractor;
using MetadataExtractor.Formats.Exif;

string Filename = @"D:\Users\Simon\OneDrive\My Stuff\My Source\TestFuelPriceTracker\Originals\IMG_8490.jpg";

IEnumerable<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(Filename);

// Approach 1
var subIfdDirectory = directories.OfType<ExifSubIfdDirectory>().FirstOrDefault();
var Orientation1 = subIfdDirectory?.GetDescription(ExifDirectoryBase.TagOrientation);
Console.WriteLine($"Approach 1: Orientation = \"{Orientation1}\"");

// Approach 2
foreach (var directory in directories)
{
    foreach (var tag in directory.Tags)
    {
        switch (tag.Name)
        {
            case "Orientation":
                Console.WriteLine($"Approach 2: Orientation = \"{tag.Description}\"");
                break;
        }
    }
}

// Approach 3
var Orientation2 = directories
    .OfType<ExifSubIfdDirectory>()
    .FirstOrDefault(s => string.Equals(s?.GetDescription(ExifDirectoryBase.TagOrientation), "Orientation", StringComparison.OrdinalIgnoreCase));
Console.WriteLine($"Approach 3: Orientation = \"{Orientation2}\"");

当运行时,我得到以下结果...

Approach 1: Orientation = ""
Approach 2: Orientation = "Top, left side (Horizontal / normal)"
Approach 3: Orientation = ""

方法 2 表明方向信息实际上存在于图像中。请注意,我尝试了很多图像,但我遇到了同样的问题。不确定这是否相关,但所有图像都是在 iPhone 12.

上拍摄的

根据@aybe 的建议添加的方法 3。

环境

我在 Windows 11 Professional 机器上使用 Visual Studio 2022,所有软件都已修补到最新版本。框架是 .NET 6。MetadataExtractor 版本 2.7.2.

您的代码永远不会工作,因为它正在比较标签的整数值,这当然永远不会匹配 "Orientation"

这可行,但由于某些图像不一定具有我所说的标签,因此可能会失败,可能值得考虑从其他标签或图像尺寸计算方向作为后备解决方案。

private static void GetOrientation(Stream stream)
{
    var directories = ImageMetadataReader.ReadMetadata(stream);

    if (TryGetOrientationTag(directories, out var result))
    {
    }
    else
    {
        throw new NotImplementedException("Compute orientation from image size instead");
    }
}

private static bool TryGetOrientationTag(IEnumerable<Directory> directories, out string result)
{
    result = null!;

    foreach (var directory in directories)
    {
        switch (directory)
        {
            case ExifDirectoryBase e:
                foreach (var tag in e.Tags)
                {
                    if (tag.Type is not ExifDirectoryBase.TagOrientation || tag.Description is null)
                        continue;

                    result = tag.Description;
                    return true;
                }

                break;
            case IptcDirectory i:
                foreach (var tag in i.Tags)
                {
                    if (tag.Type is not IptcDirectory.TagImageOrientation || tag.Description is null)
                        continue;

                    result = tag.Description;
                    return true;
                }

                break;
        }
    }

    return false;
}

建议的最终解决方案是...

IEnumerable<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(Filename);
var ifd0Directory = directories.OfType<ExifIfd0Directory>().FirstOrDefault();
int Orientation = -1;
if (ifd0Directory != null) {
    Orientation = ifd0Directory.TryGetInt32(ExifDirectoryBase.TagOrientation, out int value) ? value : -1;
}

如果成功,它 returns 一个从 1 到 8 的整数值,如果有问题,则为 -1。对于任何感兴趣的人,这些数字的含义将在以下文章中详细讨论...

JPEG Image Orientation and Exif

我还会向您指出以下麻省理工学院的论文,其中捕获了每个 Exif 标签的数据类型;还有很多其他有用的信息...

Description of Exif file format