def uncompress_rle(data, nbits): data_uncompressed, i = [], 0 maskval, maskcnt = (1 << nbits) - 1, (0xFF >> nbits >> 1) << nbits while i < len(data): v = data[i] mv = v & maskval c = (v & maskcnt) >> nbits if v & 0b10000000: i += 1 c |= data[i] << (7 - nbits) data_uncompressed.extend([mv] * c) i += 1 return bytearray(data_uncompressed) def pack(data, nbits): data_packed, npacks = [], 8 // nbits ipack, val_packed = 0, 0 for k in range(len(data)): val_packed |= data[k] << (nbits * ipack) ipack = (ipack + 1) % npacks if not ipack or k + 1 >= len(data): data_packed.append(val_packed) val_packed = 0 return bytearray(data_packed) def compress_rle(data, nbits): size = len(data) maskcol = (1 << nbits) - 1 maskcnt = 0xFF >> nbits >> 1 rle = [] i = 0 val_cnt = 0 while i <= size: val_cour = None if i < size: val_cour = data[i] if i==0: val_prec = val_cour val_cnt += val_prec == val_cour if val_prec != val_cour or i==size: while val_cnt: vim = val_prec if val_cnt <= maskcnt: ic = val_cnt vim |= ic << nbits else: ic = min(val_cnt, (1<<(15-nbits))-1) rle.append(vim | ((ic & maskcnt) << nbits) | (1<<7)) vim = ic >> (7-nbits) val_cnt -= ic rle.append(vim) val_cnt = 1 val_prec = val_cour i += 1 return bytearray(rle) def compress_rle_img_cols(nbits, data, w, h): cols = [] for i in range(w): cols.append(compress_rle(data[i*h:(i+1)*h], nbits)) return tuple(cols)