1

我正在创建一个从图像中读取和打印元数据的程序,但我很难理解 JFIF 和 EXIF 标记结构。

根据 JFIF 的维基百科页面,JFIF 标记应如下所示:

FF E0 s1 s2 4A 46 49 46 00 ii ii jj XX XX YY YY xx yy

在哪里:

FF E0 是 JFIF 标记的开始

s1 和 s2 组合给出了段的大小(不包括 APP0 标记)

4A 46 49 46 00 是标识符(字面意思是 JFIF in ascii)

i 是 JFIF 的版本(2 个字节)

j 是 DPI 测量的密度单位

X 是水平 DPI

Y 是垂直 DPI

x 是水平缩略图 DPI

y 是垂直缩略图 DPI

但是,当通过我的程序运行图像时,我得到了这个:

ff e0 20 10 4a 46 49 46 20 1 1 20 20 48 20 48 20 20 ff e1

标记开始就在那里,但段大小看起来很好(0x2010??),因为 EXIF 数据的下一个标记仅在 15 个字节后开始!(FF E1)我认为没有打印 0x00 的十六进制值(因此为什么我的图像打印没有零的 JFIF 标识符)这可能会增加混乱,但即便如此,JFIF 版本 20 20 怎么样?

如果这里的任何人有任何查看图像元数据的经验,我将非常感谢您的帮助!我找不到很多可以非常清楚地分解 JFIF/EXIF 数据的资源。

如果您需要我在这里发布任何代码,那么我可以,尽管除了不将 0x00 值打印到控制台之外,它似乎按预期工作,所以我认为我的主要问题实际上是理解元数据

这是获取字节流然后将其转换为十六进制的代码:

fileLocation = Console.ReadLine();
var fileDataAsBytes = File.ReadAllBytes(fileLocation);
var headers = fileDataAsBytes
    .Select((b, i) => (b, i))
    .Where(tuple => tuple.b == 0xFF 
    && fileDataAsBytes[tuple.i + 1] == 0xE1)
    .Select(tuple => $"{tuple.i}: {tuple.b:x} 
    {fileDataAsBytes[tuple.i + 1]:x}");
Console.WriteLine(String.Join(",", headers));
DealWithMarkers(fileDataAsBytes);
DisplayAllConversions(fileDataAsBytes);

public static void DisplayAllConversions(byte[] fileDataAsBytes)
    {
        DisplayBytes(fileDataAsBytes);
        DisplayHex(fileDataAsBytes);
        DisplayString(fileDataAsBytes);
    }

public static void DisplayHex(byte[] fileDataAsBytes)
    {
        Console.WriteLine($"\n\n\n\t*\t*\t*\t(As Hex)\t*\t*\t*\n");
        for (int i = 0; (i < 1000) && (i < fileDataAsBytes.Length); i++)
        {
            Console.Write($"{fileDataAsBytes[i]:x} ");
        }
    }

我用不同的图像尝试了这个,它实际上正确地打印出 0 值字节,所以我正在分析的图像文件一定有一些奇怪的东西!

带有“不正确”0 字节的图像文件

具有“正确”0 字节的图像文件

4

0 回答 0