我正在尝试提取从CR2(原始图片的佳能格式)中拍摄图片的日期/时间。
我知道CR2 specification,我知道我可以使用Python struct模块从二进制缓冲区提取片段。
简言之,规范指出在标签0x0132 / 306
中,我可以找到长度为20的字符串——日期和时间。
我试图通过以下方式获取标签:
struct.unpack_from(20*'s', buffer, 0x0132)
但我知道
('\x00', '\x00', "'", '\x88, ...[and more crap])
有什么想法吗?
编辑
非常感谢您的努力!答案是惊人的,我学到了很多关于处理二进制数据的知识。
0x0132不是偏移量,而是日期的标记号。CR2或TIFF分别是基于目录的格式。你必须根据你正在寻找的(已知的)标签来查找条目。
编辑: 好的,首先,您必须读取文件数据是使用小端格式还是大端格式保存的。前八个字节指定头,头的前两个字节指定尾数。Python的struct模块允许您通过在格式字符串前面加上“<;”或“>;”来处理小数据和大数据。因此,假设
data
是包含CR2图像的缓冲区,您可以通过格式规范指出,第一个图像文件目录以相对于文件开头的偏移量开始,偏移量在头的最后4个字节中指定。因此,要获得第一个IFD的偏移量,可以使用类似于此的行:
你现在可以继续读第一本IFD了。您将在目录中指定的文件偏移量处找到条目数,该偏移量为两个字节宽。因此,您可以使用以下方法读取第一个IFD中的条目数:
字段项的长度为12字节,因此可以计算IFD的长度。在条目数*12字节后,还有一个4字节长的偏移量,告诉您在哪里查找下一个目录。这基本上就是你处理TIFF和CR2图像的方式。
这里的“魔力”是要注意,对于12字节字段条目中的每一个,前两个字节将是标记ID,这就是您寻找标记0x0132的地方。因此,如果您知道第一个IFD从文件中的IFD_偏移开始,您可以通过以下方式扫描第一个目录:
很明显,您需要将该解包重构为一个公共函数,并可能将整个格式包装成一个好的类,但这超出了本例的范围。您还可以通过将多个格式字符串组合成一个字符串来缩短解包过程,生成一个更大的元组,其中包含可以解包到不同变量中的所有字段,为了清楚起见,我省略了这些字段。
你考虑过你所说的IFD块之前应该(根据规范)的头吗?
我查看了规范,它说第一个IFD块跟在16字节的头后面。因此,如果我们读取字节16和17(偏移量0x10十六进制),我们应该得到第一个IFD块中的条目数。然后我们只需要搜索每个条目,直到找到一个匹配的标记id(在我读到它时),它给了我们日期/时间字符串的字节偏移量。
这对我有效:
我的示例文件的输出是:
[编辑]-一个经过修订/更彻底的示例
我发现来自https://github.com/ianare/exif-py的EXIF.py从.CR2文件读取EXIF数据。似乎是因为.CR2文件基于.TIFF文件EXIF.py是兼容的。
这个指纹:
相关问题 更多 >
编程相关推荐