Reading-in 二进制 JPEG-Header (在 Python 中)
Reading-in a binary JPEG-Header (in Python)
我想读一个JPEG-Header并分析它。
根据 Wikipedia,header 由一系列标记组成。每个标记都以 FF xx
开头,其中 xx
是特定的 Marker-ID.
所以我的想法是简单地读入二进制格式的图像,然后在二进制流中寻找相应的character-combinations。这应该使我能够在相应的 marker-fields.
中拆分 header
例如,当我读入图像的前 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 不是 return 我很好的 2 字节块(在 hex-format 中)。
我希望这样的事情:
b'\xff \xd8 \xff \xe1 \x-' ... and so on
。一些由 '\x' 分隔的块比 2 个字节长得多。
2) 为什么returned字符串中有-, M, *
这样的符号?这些不是我期望从字节字符串中得到的十六进制表示的字符(我认为只有:0-9,a-f)。
这两个观察都阻碍了我编写一个简单的解析器。
所以最终我的问题总结为:
如何正确 read-in 并在 Python 中解析 JPEG Header?
您似乎过于担心您的二进制数据在您的控制台 上的表示方式。别担心。
default built-in string-based print(..)
应用于 bytes
对象的表示只是 "printable ASCII characters as such (except a few exceptions), all others as an escaped hex sequence" .例外情况是 semi-special 个字符,例如 \
、"
和 '
,它们可能会弄乱字符串表示形式。但是这种替代表示不会以任何方式更改值!
>>> a = bytes([1,2,4,92,34,39])
>>> a
b'\x01\x02\x04\"\''
>>> a[0]
1
看看整个对象是如何打印的'as if'它是一个字符串,但它的各个元素仍然是完全正常的字节?
如果你有一个字节数组并且你不喜欢这个默认的外观,那么你可以自己写一个。但是——为清楚起见——这仍然与解析文件没有任何关系。
>>> 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 '
Why does python not return me nice chunks of 2 bytes (in hex-format)?
因为你不问它。您要求的是 bytes
的序列,这就是您得到的。想要大块的two-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']
我在 unpack
中使用 little-endian 说明符 <
和无符号短 H
,因为(我假设)这些是表示 JPEG 2 的常规方法-字节代码。如果你想从中得到,请查看文档。
我想读一个JPEG-Header并分析它。
根据 Wikipedia,header 由一系列标记组成。每个标记都以 FF xx
开头,其中 xx
是特定的 Marker-ID.
所以我的想法是简单地读入二进制格式的图像,然后在二进制流中寻找相应的character-combinations。这应该使我能够在相应的 marker-fields.
中拆分 header例如,当我读入图像的前 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 不是 return 我很好的 2 字节块(在 hex-format 中)。
我希望这样的事情:
b'\xff \xd8 \xff \xe1 \x-' ... and so on
。一些由 '\x' 分隔的块比 2 个字节长得多。
2) 为什么returned字符串中有-, M, *
这样的符号?这些不是我期望从字节字符串中得到的十六进制表示的字符(我认为只有:0-9,a-f)。
这两个观察都阻碍了我编写一个简单的解析器。 所以最终我的问题总结为: 如何正确 read-in 并在 Python 中解析 JPEG Header?
您似乎过于担心您的二进制数据在您的控制台 上的表示方式。别担心。
default built-in string-based print(..)
应用于 bytes
对象的表示只是 "printable ASCII characters as such (except a few exceptions), all others as an escaped hex sequence" .例外情况是 semi-special 个字符,例如 \
、"
和 '
,它们可能会弄乱字符串表示形式。但是这种替代表示不会以任何方式更改值!
>>> a = bytes([1,2,4,92,34,39])
>>> a
b'\x01\x02\x04\"\''
>>> a[0]
1
看看整个对象是如何打印的'as if'它是一个字符串,但它的各个元素仍然是完全正常的字节?
如果你有一个字节数组并且你不喜欢这个默认的外观,那么你可以自己写一个。但是——为清楚起见——这仍然与解析文件没有任何关系。
>>> 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 '
Why does python not return me nice chunks of 2 bytes (in hex-format)?
因为你不问它。您要求的是 bytes
的序列,这就是您得到的。想要大块的two-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']
我在 unpack
中使用 little-endian 说明符 <
和无符号短 H
,因为(我假设)这些是表示 JPEG 2 的常规方法-字节代码。如果你想从中得到,请查看文档。