''' 1〜16bitの指定のデータを詰めてbyteごとにcallbackを実行する。'''
class Bit2Byte:
def __init__(self, callback ):
self.bit32=0 # bit設定の作業用変数
self.bitcount=0 # 上記への記憶bit数。 8bit毎にcallback処理
self.callback=callback
#
def setdata(self, data, bitsize): # dataをbyte列に変換 ビット列構築用で使う。
'''bitsizeのビット数で、dataを記憶 1byte分に詰められたタイミングで callbackを呼ぶ'''
bitmask = (1<<bitsize)-1
if data > bitmask : raise Exception(f"{data} does not fit in {bitsize} bit")
self.bit32 |= data << self.bitcount
self.bitcount += bitsize
while self.bitcount >= 8:
callback(self.bit32 & 0x0ff)
self.bit32 >>= 8
self.bitcount-=8
#
def padding(self): # ビット列構築用で使う
''' bit_sizeサイズが、丁度byteに達するように0で埋める'''
if self.bitcount != 0:
self.setdata(0, 8-self.bitcount) # bit列をbyte列に変換
out=print
ba=bytearray()
def callback( bt ):
out( f"{bt:08b}", end=" ") # 01001000 10100010 00110000 の表示
ba.append(bt)
bb=Bit2Byte( callback )
for value in [ 8 , 9 , 10 , 12 ]: # 記憶対象のデータ群
bb.setdata(value,6) # valueを6bitで記憶
bb.setdata(13,6) # valueを6bitで記憶
bb.padding()
print(ba) # bytearray(b'H\xa20') の3byteで表示
''' byteのデータ群から指定のビット長を取り出す '''
class Byte2Bit:
def __init__(self, bytedata:bytes ): # 圧縮データを引数するコンストラクタ
self.byte_buf = bytearray(bytedata)
self.byte_buf_len=len(bytedata) # 上記のbit記憶数
self.bit32=0 # bit設定の作業用変数(0〜8)
self.bitcount=0 # 上記へのbit記憶数。
#
def getdata(self,bitsize): # ビット列復元用で使う
'''bitsizeのビット数の値を取り出して返す '''
rv = (self.byte_buf_len << 3) + self.bitcount - bitsize
if rv < 0 : return rv # 負の値(足りないビット数)
bitmask = (1<<bitsize)-1
while self.bitcount < bitsize and self.byte_buf_len>0:
byte0 = self.byte_buf.pop(0)
self.byte_buf_len-=1
self.bit32 |= byte0 << self.bitcount
self.bitcount += 8
val = self.bit32 & bitmask
self.bit32 >>= bitsize
self.bitcount -= bitsize
return val
#
def append(self, bytedata:bytes ): # 圧縮データを追加
for i in range( len( bytedata ) ):
self.byte_buf.append( bytedata[i] )
self.byte_buf_len+=1 # 上記のbit記憶数
a=[0b01001000, 0b10100010, 0b00110000, 0b00001101]
byt=Byte2Bit(bytearray( a ))
while True:
value=byt.getdata(6) # 6bit長データを取り出す。
if value < 0: break # 取り出せなない? (終了)
print( value ) # 取り出しデータの表示
# intのリストから、指定ビット幅で詰め込んだバイナリ列を生成
class ListToBytes:
def __init__(self, data_list: list, bit_depth:int ):
self.bit32=0 # bit設定の作業用変数
self.bitCount=0 # 上記への記憶bit数。 8bit毎に変換処理
self.bitSize=0 # データのビットサイズ
self.bit_depth=bit_depth # 変換するビット長
self.byte_buf = bytearray()
for value in data_list: # 記憶対象のデータ群
self.setdata(value,bit_depth) # valueを6bitで記憶
self.padding()
#
def setdata(self, data, bitSize): # bit列をbyte列に変換 ビット列構築用で使う。
'''bitsizeのビット数で、dataを記憶 1byte分に詰められたタイミングで byte_bufに追加'''
bitmask = (1<<bitSize)-1
if data > bitmask : raise Exception(f"{data} does not fit in {bitSize} bit")
self.bit32 |= data << self.bitCount
self.bitCount += bitSize
#print(f"{self.bit32:032b}")
while self.bitCount >= 8:
self.byte_buf.append(self.bit32 & 0x0ff)
self.bit32 >>= 8
self.bitCount-=8
#
def padding(self): # ビット列構築用で使う
''' bit_sizeサイズが、丁度byteに達するように0で埋める'''
if self.bitCount != 0:
self.setdata(0, 8-self.bitCount) # bit列をbyte列に変換
#
def debug_string(self):# 下位ビットからビット列を並べた文字列を取得
s=""
for v in self.byte_buf:s+=''.join(list(reversed(f"{v:08b}")))
return s
a=[1,3,7,15]
obj=ListToBytes(a, 8)
print(obj.byte_buf, obj.debug_string())
print(ListToBytes(a, 6).debug_string())
実行結果
bytearray(b'\x01\x03\x07\x0f') 10000000110000001110000011110000
100000110000111000111100