如何在Python中打包任意位序列?

时间:2011-02-21 12:45:22

标签: python memory bit-packing

我想将一些二进制图像数据编码/压缩为序列(如果是位)。 (通常,此序列的长度不能完全适合整数个标准整数类型。)

如何在不浪费空间的情况下做到这一点? (我意识到,除非比特序列具有“漂亮”的长度,否则在最后总是必须有少量[<1字节]的剩余空间。)

FWIW,我估计,对于我想要编码的每个符号,最多需要3位。 Python有没有用于此类工作的内置工具?

3 个答案:

答案 0 :(得分:6)

没有什么非常方便的内置,但有第三方模块,如bitstringbitarray,这是为此设计的。

from bitstring import BitArray
s = BitArray('0b11011')
s += '0b100'
s += 'uint:5=9'
s += [0, 1, 1, 0, 1]
...
s.tobytes()

要将3位数字序列(即范围0-> 7)连接在一起,您可以使用

>>> symbols = [0, 4, 5, 3, 1, 1, 7, 6, 5, 2, 6, 2]
>>> BitArray().join(BitArray(uint=x, length=3) for x in symbols)
BitArray('0x12b27eab2')
>>> _.tobytes()
'\x12\xb2~\xab '

一些相关问题:

答案 1 :(得分:3)

你试过用bz2简单地压缩整个序列吗?如果序列很长,你应该使用bz2.BZ2Compressor来允许分块处理,否则在整个事情上使用bz2.compress。压缩可能不太理想,但在处理稀疏数据时通常会非常接近。

希望有所帮助。

答案 2 :(得分:2)

由于您具有从符号到3位字符串的映射,因此bitarray可以很好地编码和解码符号列表以及从位数组中解码符号:

from bitarray import bitarray
from random import choice

symbols = {
    '0' : bitarray('000'),
    'a' : bitarray('001'),
    'b' : bitarray('010'),
    'c' : bitarray('011'),
    'd' : bitarray('100'),
    'e' : bitarray('101'),
    'f' : bitarray('110'),
    'g' : bitarray('111'),
}

seedstring = ''.join(choice(symbols.keys()) for _ in range(40))

# construct bitarray using symbol->bitarray mapping
ba = bitarray()
ba.encode(symbols, seedstring)

print seedstring
print ba

# what does bitarray look like internally?
ba_string = ba.tostring()
print repr(ba_string)
print len(ba_string)

打印:

egb0dbebccde0gfdfbc0d0ccfcg0acgg0ccfga00
bitarray('10111101000010001010101001101110010100... etc.
'\xbd\x08\xaanQ\xf4\xc9\x88\x1b\xcf\x82\xff\r\xee@'
15

您可以看到这个40个符号的列表(120位)被编码为15个字节的比特阵列。