从每两个字节获取整数值

时间:2018-10-17 09:09:59

标签: python byte

我正在尝试从图像读取字节,并从该图像获取所有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时,如果我有一个字节序列,则会发生某些事情。

有什么想法吗?谢谢!

1 个答案:

答案 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))

后面是特定的属性分配。