Advertisement
Guest User

gif_lzw.py

a guest
Jul 31st, 2015
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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 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 = list()
  42.     for x in xrange(1 << code_size):
  43.         root.append([None]*256)
  44.     writer.write_bits(clear_code, code_size)
  45.    
  46.     i = 0
  47.     while i < len(data):
  48. #        print("now index #%i (%i)" % (i, data[i]))
  49.         last_index = data[i]
  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.             writer.write_bits(data[i], code_size)            
  54.             break
  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.             last_index = root[last_index][ data[o] ]
  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.         i = o
  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()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement