我想将一些二进制图像数据编码/压缩为序列(如果是位)。 (通常,此序列的长度不能完全适合整数个标准整数类型。)
如何在不浪费空间的情况下做到这一点? (我意识到,除非比特序列具有“漂亮”的长度,否则在最后总是必须有少量[<1字节]的剩余空间。)
FWIW,我估计,对于我想要编码的每个符号,最多需要3位。 Python有没有用于此类工作的内置工具?
答案 0 :(得分:6)
没有什么非常方便的内置,但有第三方模块,如bitstring和bitarray,这是为此设计的。
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个字节的比特阵列。