我想阅读JPEG-Header并进行分析。
根据{{3}},标题由一系列标记组成。每个标记都以FF xx
开头,其中xx
是特定的标记ID。
所以我的想法是简单地以二进制格式读取图像,并在二进制流中寻找相应的字符组合。这应该使我能够在相应的标记字段中拆分标题。
例如,当我读到图像的前20个字节时,这就是我收到的内容:
binary_data = open('picture.jpg','rb').read(20)
print(binary_data)
B' \ XFF \ XD8 \ XFF \ xe1- \ xfcExif \ X00 \ x00MM \ X00 * \ X00 \ X00 \ X00 \ X08'
我现在的问题是:
1)为什么python不会返回2个字节的大块(十六进制格式)。
我希望这样的事情:
b'\xff \xd8 \xff \xe1 \x-' ... and so on
。一些由' \ x'超过2个字节。
2)为什么返回的字符串中有-, M, *
之类的符号?那些不是十字形表示的字符我期望从一个字节字符串(只有:0-9,a-f,我认为)。
这两个观察都阻碍了我编写一个简单的解析器。 所以最终我的问题总结为: 如何在Python中正确读入和解析JPEG标头?
答案 0 :(得分:2)
您似乎过分担心您的二进制数据在控制台上的显示方式。别担心。
print(..)
适用于bytes
对象的默认内置基于字符串的表示只是“可打印的ASCII字符(除了少数例外),所有其他人作为逃脱的十六进制序列“。例外是半特殊字符,例如\
,"
和'
,这些字符可能会破坏字符串表示形式。但是这种替代表示不会以任何方式改变价值!
>>> a = bytes([1,2,4,92,34,39])
>>> a
b'\x01\x02\x04\\"\''
>>> a[0]
1
看看整个对象是如何打印的“好像”它是一个字符串,但它的各个元素仍然是完全正常的字节?
如果你有一个字节数组并且你不喜欢这个默认的外观,那么你可以自己编写。但是 - 为了清楚起见 - 这仍然与解析文件没有任何关系。
>>> binary_data = open('iaijiedc.jpg','rb').read(20)
>>> binary_data
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x02\x01\x00H\x00H\x00\x00'
>>> ''.join(['%02x%02x ' % (binary_data[2*i],binary_data[2*i+1]) for i in range(len(binary_data)>>1)])
'ffd8 ffe0 0010 4a46 4946 0001 0201 0048 0048 0000 '
为什么python不会返回2个字节的大块(十六进制格式)?
因为你没有询问。你要的是一系列bytes
,这就是你得到的。如果你想要两个字节的块,请在读取后进行转换。
上面的代码只打印数据;创建一个包含2字节字的新列表,循环并转换每2个字节或使用unpack
(实际上有几种方式):
>>> wd = [unpack('>H', binary_data[x:x+2])[0] for x in range(0,len(binary_data),2)]
>>> wd
[65496, 65504, 16, 19014, 18758, 1, 513, 72, 72, 0]
>>> [hex(x) for x in wd]
['0xffd8', '0xffe0', '0x10', '0x4a46', '0x4946', '0x1', '0x201', '0x48', '0x48', '0x0']
我在<
中使用little-endian说明符H
和unsigned short unpack
,因为(我假设)这些是表示JPEG 2字节代码的传统方法。如果您想从中获得,请查看文档。