View difference between Paste ID: WUjg39bK and WQgc3LxT
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).
25+
    The result is a string (or bytes 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]*256]*(1 << code_size)
41+
    root = list()
42
    for x in xrange(1 << code_size):
43
        root.append([None]*256)
44-
    i = 1
44+
45-
    last_index = data[0]
45+
46-
    while i < len(data) -1:
46+
    i = 0
47
    while i < len(data):
48-
        while i < len(data) -1 and not root[last_index][data[i]] is None:
48+
#        print("now index #%i (%i)" % (i, data[i]))
49-
            last_index = root[last_index][data[i]]
49+
        last_index = data[i]
50-
            i += 1
50+
        o = i + 1
51
        # If we are reading the last byte just write it out as it is.
52
        if o >= len(data):
53-
        root[last_index][data[i]] = next_code
53+
            writer.write_bits(data[i], code_size)            
54
            break
55-
        # Add new dictionary entry
55+
56
        # Loop till we find an unknown sequence
57
#        print("Do we know %i -> %i ?" % (last_index, data[o]))
58
        while (o < len(data) -1 and not root[last_index][ data[o] ] is None):
59
#            print("Known %i -> %i" % (last_index, root[last_index][ data[o] ]))
60-
                root.extend( [ [None]*255 ] * ((1 << code_size) - (1 << (code_size-1))) )
60+
            last_index = root[last_index][ data[o] ]
61-
                #print("increase code size to", self.codeBits)
61+
            o += 1
62
#            print("Do we know %i -> %i ?" % (last_index, data[o]))
63
            
64
#        print("Create chain from %i to %i (%i)" % (last_index, data[o], next_code))
65
        root[last_index][data[o]] = next_code
66
        writer.write_bits(last_index, code_size)
67-
            root = [[None]*265]*(1 << code_size)
67+
        i = o
68-
            pass
68+
69
        #// Add new dictionary entry
70
        if next_code < MAX_DICT_SIZE:
71
            if (next_code & (next_code - 1)) == 0:  #// Is a power of 2
72
                code_size += 1
73
                # TODO: clean this up # Should be way nicer to calc.. to tired TODO: 
74
                for x in xrange((1 << code_size) - (1 << (code_size-1))):
75
                    root.append([None]*256)
76
#                 print("increase code size to", self.codeBits)
77
            next_code += 1
78
        else:
79
            writer.write_bits(clear_code, code_size)                
80
            code_size = code_bits +1
81
            next_code = eoi_code +1
82
            root = list()
83
            for x in xrange(1 << code_size):
84
                root.append([None]*256)
85
                
86
    writer.write_bits(eoi_code, code_size)
87
    writer.finish()
88
    return buf.getvalue()