python - 从每两个字节获取 int 值
问题描述
我正在尝试从图像中读取字节,并从该图像中获取所有 int(16 位)值。解析图像标题后,我得到了像素值。当这对字节像 b"\xd4\x00" 时,我得到的值不正确。在这种情况下,它应该是 54272,而不是 3392。
这是代码的一部分:我使用生成器来获取字节:
import itertools
def osddef_generator(in_file):
with open(in_file, mode='rb') as f:
dat = f.read()
for byte in dat:
yield byte
def take_slice(in_generator, size):
return ''.join(str(chr(i)) for i in itertools.islice(in_generator, size))
def take_single_pixel(in_generator):
pix = itertools.islice(in_generator, 2)
hex_list = [hex(i) for i in pix]
hex_str = "".join(hex_list)[2:].replace("0x", '')
intval = int(hex_str, 16)
print("hex_list: ", hex_list)
print("hex_str: ", hex_str)
print("intval: ", intval)
在我使用该方法正确获取标题后take_slice
,我将使用该方法到达具有像素值的部分take_single_pixel
。在这里,我得到了不好的结果。这就是我得到的:
hex_list: ['0xd4', '0x0']
hex_str: d40
intval: 3392
但是应该解释的实际字节序列是:\xd4\x00
,等于54272
,所以我的hex_list = ['0xd4', '0x00']
和hex_str = d400
. 当我有一个字节序列,而第二个字节是\x00
.
有什么想法吗?谢谢!
解决方案
将字节转换为整数有更好的方法:
int.from_bytes()
接受字节输入和字节顺序参数:>>> int.from_bytes(b"\xd4\x00", 'big') 54272 >>> int.from_bytes(b"\xd4\x00", 'little') 212
该
struct.unpack()
函数允许您按照以下模式将一系列字节转换为整数:>>> import struct >>> struct.unpack('!4H', b'\xd4\x00\xd4\x00\xd4\x00\xd4\x00') (54272, 54272, 54272, 54272)
该
array
模块可让您有效地将表示同质整数数据的二进制数据读入内存结构:>>> array.array('H', fileobject)
但是,
array
不能告诉使用什么字节顺序。arr.byteswap()
如果机器顺序与文件顺序不匹配,您必须确定当前架构的字节顺序并调用反向顺序。
在读取图像数据时,几乎总是最好使用该struct
模块进行解析。然后,您通常会使用file.read()
特定大小的调用;如果标头由 10 个字节组成,请使用:
headerinfo = struct.unpack('<expected header pattern for 10 bytes>', f.read(10))
然后从那里去。例如,查看Pillow/PIL 图像插件源代码;以下是暴雪 Mipmap 图像格式标头的读取方式:
def _read_blp_header(self):
self._blp_compression, = struct.unpack("<i", self.fp.read(4))
self._blp_encoding, = struct.unpack("<b", self.fp.read(1))
self._blp_alpha_depth, = struct.unpack("<b", self.fp.read(1))
self._blp_alpha_encoding, = struct.unpack("<b", self.fp.read(1))
self._blp_mips, = struct.unpack("<b", self.fp.read(1))
self._size = struct.unpack("<II", self.fp.read(8))
if self.magic == b"BLP1":
# Only present for BLP1
self._blp_encoding, = struct.unpack("<i", self.fp.read(4))
self._blp_subtype, = struct.unpack("<i", self.fp.read(4))
self._blp_offsets = struct.unpack("<16I", self.fp.read(16 * 4))
self._blp_lengths = struct.unpack("<16I", self.fp.read(16 * 4))
因为struct.unpack()
总是返回元组,所以您可以将元组中的单个元素分配给name1, name2, ...
左侧大小的名称,包括single_name, =
提取单个结果的分配。
上面单独的一组读取调用也可以压缩为更少的调用:
comp, enc, adepth, aenc, mips, *size = struct.unpack("<i4b2I", self.fp.read(16))
if self.magic == b"BLP1":
# Only present for BLP1
enc, subtype = struct.unpack("<2i", self.fp.read(8))
其次是特定的属性分配。
推荐阅读
- c# - 当设置为 TestFixture 级别而不是测试级别时如何获取作者属性?
- python - 如何找到一个系列中多个组的总和?
- excel - 替换没有数组公式的 MAXIFS
- c++ - C++ [std::regex] 试图只匹配中间有空格的数字
- python-3.x - 在列表中查找列表索引的优雅方法?
- firebase - 使用颤振在 Firestore 中创建链接到用户 ID 的集合
- python - lighttpd:cgi-bin 中的简单 python 代码有效,但未处理表单
- excel - Excel单元格公式计算一个表中的键,如果它们在另一个表中的值是特定条件
- jquery - 提交表单返回 400 状态
- html - 如何让我网站上的用户 ping 特定的 IP 地址?