View difference between Paste ID: WQgc3LxT and 2yHPQjCQ
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
    buf = StringIO()
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)
41+
    root = [[None]*256]*(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]
49+
            last_index = root[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
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
57+
58
                code_size += 1
59
                # TODO: clean this up # Should be way nicer to calc.. to tired TODO: 
60
                root.extend( [ [None]*255 ] * ((1 << code_size) - (1 << (code_size-1))) )
61-
                root.extend( [ [ [None]*255 ] * ((1 << code_size) - (1 << (code_size-1))) ] )
61+
62
            next_code += 1
63
        else:
64
            writer.write_bits(clear_code, code_size)                
65
            code_size = code_bits +1
66
            next_code = eoi_code +1
67
            root = [[None]*265]*(1 << code_size)
68
            pass
69
                
70
    writer.write_bits(eoi_code, code_size)
71
    writer.finish()
72
    return buf.getvalue()