我正在创建一个从图像中读取和打印元数据的程序,但我很难理解 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 值字节,所以我正在分析的图像文件一定有一些奇怪的东西!