SHOW:
|
|
- or go back to the newest paste.
1 | class BitWriter(): | |
2 | def __init__(self, consumer): | |
3 | self.consumer = consumer | |
4 | self.bit_buffer = 0 | |
5 | self.bit_buffer_len = 0 | |
6 | ||
7 | def write_bits(self, value, bits): | |
8 | # TODO catch invalid parameter | |
9 | self.bit_buffer |= value << self.bit_buffer_len | |
10 | self.bit_buffer_len += bits | |
11 | while self.bit_buffer_len >= 8: | |
12 | self.consumer.write(chr(self.bit_buffer & 0xff)) | |
13 | self.bit_buffer >>= 8 | |
14 | self.bit_buffer_len -= 8 | |
15 | ||
16 | def finish(self): | |
17 | if self.bit_buffer_len > 0: | |
18 | self.consumer.write(chr(self.bit_buffer & 0xff)) | |
19 | ||
20 | def lzw_encode_default(data, code_bits): | |
21 | """ | |
22 | @data: bytes (in py3) or something iterable with ints <= 255 | |
23 | @code_bits: the minimum_lzw_size (size of code in bits at start = code_bits +1) | |
24 | data should contain the frames pixel index data. | |
25 | The result is a string (or byte in py3). | |
26 | TODO: replace StringIO with BytesIo | |
27 | """ | |
28 | MAX_DICT_SIZE = 4096 | |
29 | - | print(data[:50]) |
29 | + | |
30 | writer = BitWriter(buf) | |
31 | ||
32 | if code_bits < 2 or code_bits > 8: | |
33 | raise Exception("Invalid code size"); | |
34 | ||
35 | code_size = code_bits +1 | |
36 | clear_code = 1 << code_bits | |
37 | eoi_code = clear_code +1 | |
38 | next_code = eoi_code +1 | |
39 | # We could use lists or arrays or something more memory friendly here i guess ? | |
40 | # Also we don't really need to recreate all the lists. Zeroing all fields should be enough ? | |
41 | root = [[None]*265]*(1 << code_size) | |
42 | writer.write_bits(clear_code, code_size) | |
43 | ||
44 | i = 1 | |
45 | last_index = data[0] | |
46 | while i < len(data) -1: | |
47 | # Loop till we find an unknown sequence | |
48 | while i < len(data) -1 and not root[last_index][data[i]] is None: | |
49 | last_index = data[i] | |
50 | i += 1 | |
51 | ||
52 | writer.write_bits(last_index, code_size) | |
53 | root[last_index][data[i]] = next_code | |
54 | ||
55 | #// Add new dictionary entry | |
56 | if next_code < MAX_DICT_SIZE: | |
57 | #// But we must update the size and code bits for the decoder's sake | |
58 | if (next_code & (next_code - 1)) == 0: #// Is a power of 2 | |
59 | code_size += 1 | |
60 | # TODO: clean this up # Should be way nicer to calc.. to tired TODO: | |
61 | root.extend( [ [ [None]*255 ] * ((1 << code_size) - (1 << (code_size-1))) ] ) | |
62 | #print("increase code size to", self.codeBits) | |
63 | next_code += 1 | |
64 | else: | |
65 | writer.write_bits(clear_code, code_size) | |
66 | code_size = code_bits +1 | |
67 | next_code = eoi_code +1 | |
68 | root = [[None]*265]*(1 << code_size) | |
69 | pass | |
70 | ||
71 | writer.write_bits(eoi_code, code_size) | |
72 | writer.finish() | |
73 | return buf.getvalue() |