我正在尝试从图像读取字节,并从该图像获取所有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
时,如果我有一个字节序列,则会发生某些事情。
有什么想法吗?谢谢!
答案 0 :(得分:3)
有更好的方法将字节转换为整数:
int.from_bytes()
接受字节输入,并输入字节顺序参数:
>>> int.from_bytes(b"\xd4\x00", 'big')
54272
>>> int.from_bytes(b"\xd4\x00", 'little')
212
通过struct.unpack()
function,您可以按照一种模式将整个字节序列转换为整数:
>>> import struct
>>> struct.unpack('!4H', b'\xd4\x00\xd4\x00\xd4\x00\xd4\x00')
(54272, 54272, 54272, 54272)
array
module使您可以将表示同构整数数据的二进制数据有效地读取到内存结构中:
>>> 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 image plugins source code; Blizzard Mipmap image format header is read:
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))
后面是特定的属性分配。