Ejemplo n.º 1
0
 def createFields(self):
     dictionary = {}
     self.nbits = self.startbits
     CLEAR_CODE = 2**self.nbits
     END_CODE = CLEAR_CODE + 1
     compress_code = CLEAR_CODE + 2
     obuf = []
     output = []
     while True:
         if compress_code >= 2**self.nbits:
             self.nbits += 1
         code = Bits(self, "code[]", self.nbits)
         if code.value == CLEAR_CODE:
             if compress_code == 2**(self.nbits - 1):
                 # this fixes a bizarre edge case where the reset code could
                 # appear just after the bits incremented. Apparently, the
                 # correct behaviour is to express the reset code with the
                 # old number of bits, not the new...
                 code = Bits(self, "code[]", self.nbits - 1)
             self.nbits = self.startbits + 1
             dictionary = {}
             compress_code = CLEAR_CODE + 2
             obuf = []
             code._description = "Reset Code (LZW code %i)" % code.value
             yield code
             continue
         elif code.value == END_CODE:
             code._description = "End of Information Code (LZW code %i)" % code.value
             yield code
             break
         if code.value < CLEAR_CODE:  # literal
             if obuf:
                 chain = obuf + [code.value]
                 dictionary[compress_code] = chain
                 compress_code += 1
             obuf = [code.value]
             output.append(code.value)
             code._description = "Literal Code %i" % code.value
         elif code.value >= CLEAR_CODE + 2:
             if code.value in dictionary:
                 chain = dictionary[code.value]
                 code._description = "Compression Code %i (found in dictionary as %s)" % (
                     code.value, rle_repr(chain))
             else:
                 chain = obuf + [obuf[0]]
                 code._description = "Compression Code %i (not found in dictionary; guessed to be %s)" % (
                     code.value, rle_repr(chain))
             dictionary[compress_code] = obuf + [chain[0]]
             compress_code += 1
             obuf = chain
             output += chain
         code._description += "; Current Decoded Length %i" % len(output)
         yield code
     padding = paddingSize(self.current_size, 8)
     if padding:
         yield NullBits(self, "padding[]", padding)
Ejemplo n.º 2
0
 def createFields(self):
     for i in range(20):
         yield Bits(self, "pretree_lengths[]", 4)
     pre_tree = build_tree(
         [self['pretree_lengths[%d]' % x].value for x in range(20)])
     if not hasattr(self.root, "lzx_tree_lengths_" + self.name):
         self.lengths = [0] * self.num_elements
         setattr(self.root, "lzx_tree_lengths_" + self.name, self.lengths)
     else:
         self.lengths = getattr(self.root, "lzx_tree_lengths_" + self.name)
     i = 0
     while i < self.num_elements:
         field = HuffmanCode(self, "tree_code[]", pre_tree)
         if field.realvalue <= 16:
             self.lengths[i] = (self.lengths[i] - field.realvalue) % 17
             field._description = "Literal tree delta length %i (new length value %i for element %i)" % (
                 field.realvalue, self.lengths[i], i)
             i += 1
             yield field
         elif field.realvalue == 17:
             field._description = "Tree Code 17: Zeros for 4-19 elements"
             yield field
             extra = Bits(self, "extra[]", 4)
             zeros = 4 + extra.value
             extra._description = "Extra bits: zeros for %i elements (elements %i through %i)" % (
                 zeros, i, i + zeros - 1)
             yield extra
             self.lengths[i:i + zeros] = [0] * zeros
             i += zeros
         elif field.realvalue == 18:
             field._description = "Tree Code 18: Zeros for 20-51 elements"
             yield field
             extra = Bits(self, "extra[]", 5)
             zeros = 20 + extra.value
             extra._description = "Extra bits: zeros for %i elements (elements %i through %i)" % (
                 zeros, i, i + zeros - 1)
             yield extra
             self.lengths[i:i + zeros] = [0] * zeros
             i += zeros
         elif field.realvalue == 19:
             field._description = "Tree Code 19: Same code for 4-5 elements"
             yield field
             extra = Bits(self, "extra[]", 1)
             run = 4 + extra.value
             extra._description = "Extra bits: run for %i elements (elements %i through %i)" % (
                 run, i, i + run - 1)
             yield extra
             newfield = HuffmanCode(self, "tree_code[]", pre_tree)
             assert newfield.realvalue <= 16
             newfield._description = "Literal tree delta length %i (new length value %i for elements %i through %i)" % (
                 newfield.realvalue, self.lengths[i], i, i + run - 1)
             self.lengths[i:i + run] = [
                 (self.lengths[i] - newfield.realvalue) % 17
             ] * run
             i += run
             yield newfield
Ejemplo n.º 3
0
 def createFields(self):
     dictionary = {}
     self.nbits = self.startbits
     CLEAR_CODE = 2 ** self.nbits
     END_CODE = CLEAR_CODE + 1
     compress_code = CLEAR_CODE + 2
     obuf = []
     output = []
     while True:
         if compress_code >= 2 ** self.nbits:
             self.nbits += 1
         code = Bits(self, "code[]", self.nbits)
         if code.value == CLEAR_CODE:
             if compress_code == 2 ** (self.nbits - 1):
                 # this fixes a bizarre edge case where the reset code could
                 # appear just after the bits incremented. Apparently, the
                 # correct behaviour is to express the reset code with the
                 # old number of bits, not the new...
                 code = Bits(self, "code[]", self.nbits - 1)
             self.nbits = self.startbits + 1
             dictionary = {}
             compress_code = CLEAR_CODE + 2
             obuf = []
             code._description = "Reset Code (LZW code %i)" % code.value
             yield code
             continue
         elif code.value == END_CODE:
             code._description = "End of Information Code (LZW code %i)" % code.value
             yield code
             break
         if code.value < CLEAR_CODE:  # literal
             if obuf:
                 chain = obuf + [code.value]
                 dictionary[compress_code] = chain
                 compress_code += 1
             obuf = [code.value]
             output.append(code.value)
             code._description = "Literal Code %i" % code.value
         elif code.value >= CLEAR_CODE + 2:
             if code.value in dictionary:
                 chain = dictionary[code.value]
                 code._description = "Compression Code %i (found in dictionary as %s)" % (
                 code.value, rle_repr(chain))
             else:
                 chain = obuf + [obuf[0]]
                 code._description = "Compression Code %i (not found in dictionary; guessed to be %s)" % (
                 code.value, rle_repr(chain))
             dictionary[compress_code] = obuf + [chain[0]]
             compress_code += 1
             obuf = chain
             output += chain
         code._description += "; Current Decoded Length %i" % len(output)
         yield code
     padding = paddingSize(self.current_size, 8)
     if padding:
         yield NullBits(self, "padding[]", padding)
Ejemplo n.º 4
0
 def createFields(self):
     for i in xrange(20):
         yield Bits(self, "pretree_lengths[]", 4)
     pre_tree = build_tree([self['pretree_lengths[%d]' % x].value for x in xrange(20)])
     if not hasattr(self.root, "lzx_tree_lengths_" + self.name):
         self.lengths = [0] * self.num_elements
         setattr(self.root, "lzx_tree_lengths_" + self.name, self.lengths)
     else:
         self.lengths = getattr(self.root, "lzx_tree_lengths_" + self.name)
     i = 0
     while i < self.num_elements:
         field = HuffmanCode(self, "tree_code[]", pre_tree)
         if field.realvalue <= 16:
             self.lengths[i] = (self.lengths[i] - field.realvalue) % 17
             field._description = "Literal tree delta length %i (new length value %i for element %i)" % (
                 field.realvalue, self.lengths[i], i)
             i += 1
             yield field
         elif field.realvalue == 17:
             field._description = "Tree Code 17: Zeros for 4-19 elements"
             yield field
             extra = Bits(self, "extra[]", 4)
             zeros = 4 + extra.value
             extra._description = "Extra bits: zeros for %i elements (elements %i through %i)" % (
             zeros, i, i + zeros - 1)
             yield extra
             self.lengths[i:i + zeros] = [0] * zeros
             i += zeros
         elif field.realvalue == 18:
             field._description = "Tree Code 18: Zeros for 20-51 elements"
             yield field
             extra = Bits(self, "extra[]", 5)
             zeros = 20 + extra.value
             extra._description = "Extra bits: zeros for %i elements (elements %i through %i)" % (
             zeros, i, i + zeros - 1)
             yield extra
             self.lengths[i:i + zeros] = [0] * zeros
             i += zeros
         elif field.realvalue == 19:
             field._description = "Tree Code 19: Same code for 4-5 elements"
             yield field
             extra = Bits(self, "extra[]", 1)
             run = 4 + extra.value
             extra._description = "Extra bits: run for %i elements (elements %i through %i)" % (run, i, i + run - 1)
             yield extra
             newfield = HuffmanCode(self, "tree_code[]", pre_tree)
             assert newfield.realvalue <= 16
             newfield._description = "Literal tree delta length %i (new length value %i for elements %i through %i)" % (
                 newfield.realvalue, self.lengths[i], i, i + run - 1)
             self.lengths[i:i + run] = [(self.lengths[i] - newfield.realvalue) % 17] * run
             i += run
             yield newfield
Ejemplo n.º 5
0
 def createFields(self):
     field = HuffmanCode(self, "dc_data", self.dc_tree)
     field._description = "DC Code %i (Huffman Code %i)" % (
         field.realvalue, field.value) + field._description
     yield field
     if field.realvalue != 0:
         extra = Bits(self, "dc_data_extra", field.realvalue)
         if extra.value < 2**(field.realvalue - 1):
             corrected_value = extra.value + (-1 << field.realvalue) + 1
         else:
             corrected_value = extra.value
         extra._description = "Extra Bits: Corrected DC Value %i" % corrected_value
         yield extra
     data = []
     while len(data) < 63:
         field = HuffmanCode(self, "ac_data[]", self.ac_tree)
         value_r = field.realvalue >> 4
         if value_r:
             data += [0] * value_r
         value_s = field.realvalue & 0x0F
         if value_r == value_s == 0:
             field._description = "AC Code Block Terminator (0, 0) (Huffman Code %i)" % field.value + \
                 field._description
             yield field
             return
         field._description = "AC Code %i, %i (Huffman Code %i)" % (
             value_r, value_s, field.value) + field._description
         yield field
         if value_s != 0:
             extra = Bits(self,
                          "ac_data_extra[%s" % field.name.split('[')[1],
                          value_s)
             if extra.value < 2**(value_s - 1):
                 corrected_value = extra.value + (-1 << value_s) + 1
             else:
                 corrected_value = extra.value
             extra._description = "Extra Bits: Corrected AC Value %i" % corrected_value
             data.append(corrected_value)
             yield extra
         else:
             data.append(0)
Ejemplo n.º 6
0
 def createFields(self):
     field = HuffmanCode(self, "dc_data", self.dc_tree)
     field._description = "DC Code %i (Huffman Code %i)" % (
         field.realvalue, field.value) + field._description
     yield field
     if field.realvalue != 0:
         extra = Bits(self, "dc_data_extra", field.realvalue)
         if extra.value < 2 ** (field.realvalue - 1):
             corrected_value = extra.value + (-1 << field.realvalue) + 1
         else:
             corrected_value = extra.value
         extra._description = "Extra Bits: Corrected DC Value %i" % corrected_value
         yield extra
     data = []
     while len(data) < 63:
         field = HuffmanCode(self, "ac_data[]", self.ac_tree)
         value_r = field.realvalue >> 4
         if value_r:
             data += [0] * value_r
         value_s = field.realvalue & 0x0F
         if value_r == value_s == 0:
             field._description = "AC Code Block Terminator (0, 0) (Huffman Code %i)" % \
                                  field.value + field._description
             yield field
             return
         field._description = "AC Code %i, %i (Huffman Code %i)" % (
             value_r, value_s, field.value) + field._description
         yield field
         if value_s != 0:
             extra = Bits(self, "ac_data_extra[%s" %
                          field.name.split('[')[1], value_s)
             if extra.value < 2 ** (value_s - 1):
                 corrected_value = extra.value + (-1 << value_s) + 1
             else:
                 corrected_value = extra.value
             extra._description = "Extra Bits: Corrected AC Value %i" % corrected_value
             data.append(corrected_value)
             yield extra
         else:
             data.append(0)
Ejemplo n.º 7
0
 def createFields(self):
     values = [[], []]
     for i in (0, 1):
         yield Bits(self, "blue[]", 5)
         yield Bits(self, "green[]", 6)
         yield Bits(self, "red[]", 5)
         values[i] = [
             self["red[%i]" % i].value, self["green[%i]" % i].value,
             self["blue[%i]" % i].value
         ]
     if values[0] > values[1] or self.dxt2_mode:
         values += interp_avg(values[0], values[1], 3)
     else:
         values += interp_avg(values[0], values[1], 2)
         values.append(None)  # transparent
     for i in range(16):
         pixel = Bits(self, "pixel[%i][%i]" % divmod(i, 4), 2)
         color = values[pixel.value]
         if color is None:
             pixel._description = "Transparent"
         else:
             pixel._description = "RGB color: %s" % color_name(
                 color, [5, 6, 5])
         yield pixel
Ejemplo n.º 8
0
 def createFields(self):
     values = []
     yield UInt8(self, "alpha_val[0]", "First alpha value")
     values.append(self["alpha_val[0]"].value)
     yield UInt8(self, "alpha_val[1]", "Second alpha value")
     values.append(self["alpha_val[1]"].value)
     if values[0] > values[1]:
         values += interp_avg(values[0], values[1], 7)
     else:
         values += interp_avg(values[0], values[1], 5)
         values += [0, 255]
     for i in range(16):
         pixel = Bits(self, "alpha[%i][%i]" % divmod(i, 4), 3)
         alpha = values[pixel.value]
         pixel._description = "Alpha value: %i" % alpha
         yield pixel
Ejemplo n.º 9
0
 def createFields(self):
     yield Bit(self, "final", "Is this the final block?")  # BFINAL
     yield Enum(Bits(self, "compression_type", 2),  # BTYPE
                {0: "None", 1: "Fixed Huffman", 2: "Dynamic Huffman", 3: "Reserved"})
     if self["compression_type"].value == 0:  # no compression
         padding = paddingSize(self.current_size + self.absolute_address, 8)  # align on byte boundary
         if padding:
             yield PaddingBits(self, "padding[]", padding)
         yield Int16(self, "len")
         yield Int16(self, "nlen", "One's complement of len")
         if self["len"].value != ~self["nlen"].value:
             raise ParserError("len must be equal to the one's complement of nlen!")
         if self["len"].value:  # null stored blocks produced by some encoders (e.g. PIL)
             yield RawBytes(self, "data", self["len"].value, "Uncompressed data")
         return
     elif self["compression_type"].value == 1:  # Fixed Huffman
         length_tree = {}  # (size, huffman code): value
         distance_tree = {}
         for i in xrange(144):
             length_tree[(8, i + 48)] = i
         for i in xrange(144, 256):
             length_tree[(9, i + 256)] = i
         for i in xrange(256, 280):
             length_tree[(7, i - 256)] = i
         for i in xrange(280, 288):
             length_tree[(8, i - 88)] = i
         for i in xrange(32):
             distance_tree[(5, i)] = i
     elif self["compression_type"].value == 2:  # Dynamic Huffman
         yield Bits(self, "huff_num_length_codes", 5, "Number of Literal/Length Codes, minus 257")
         yield Bits(self, "huff_num_distance_codes", 5, "Number of Distance Codes, minus 1")
         yield Bits(self, "huff_num_code_length_codes", 4, "Number of Code Length Codes, minus 4")
         code_length_code_lengths = [0] * 19  # confusing variable name...
         for i in self.CODE_LENGTH_ORDER[:self["huff_num_code_length_codes"].value + 4]:
             field = Bits(self, "huff_code_length_code[%i]" % i, 3, "Code lengths for the code length alphabet")
             yield field
             code_length_code_lengths[i] = field.value
         code_length_tree = build_tree(code_length_code_lengths)
         length_code_lengths = []
         distance_code_lengths = []
         for numcodes, name, lengths in (
                 (self["huff_num_length_codes"].value + 257, "length", length_code_lengths),
                 (self["huff_num_distance_codes"].value + 1, "distance", distance_code_lengths)):
             while len(lengths) < numcodes:
                 field = HuffmanCode(self, "huff_%s_code[]" % name, code_length_tree)
                 value = field.realvalue
                 if value < 16:
                     prev_value = value
                     field._description = "Literal Code Length %i (Huffman Code %i)" % (value, field.value)
                     yield field
                     lengths.append(value)
                 else:
                     info = {16: (3, 6, 2),
                             17: (3, 10, 3),
                             18: (11, 138, 7)}[value]
                     if value == 16:
                         repvalue = prev_value
                     else:
                         repvalue = 0
                     field._description = "Repeat Code %i, Repeating value (%i) %i to %i times (Huffman Code %i)" % (
                     value, repvalue, info[0], info[1], field.value)
                     yield field
                     extrafield = Bits(self, "huff_%s_code_extra[%s" % (name, field.name.split('[')[1]), info[2])
                     num_repeats = extrafield.value + info[0]
                     extrafield._description = "Repeat Extra Bits (%i), total repeats %i" % (
                     extrafield.value, num_repeats)
                     yield extrafield
                     lengths += [repvalue] * num_repeats
         length_tree = build_tree(length_code_lengths)
         distance_tree = build_tree(distance_code_lengths)
     else:
         raise ParserError("Unsupported compression type 3!")
     while True:
         field = HuffmanCode(self, "length_code[]", length_tree)
         value = field.realvalue
         if value < 256:
             field._description = "Literal Code %r (Huffman Code %i)" % (chr(value), field.value)
             yield field
             self.uncomp_data += chr(value)
         if value == 256:
             field._description = "Block Terminator Code (256) (Huffman Code %i)" % field.value
             yield field
             break
         elif value > 256:
             info = self.LENGTH_SYMBOLS[value]
             if info[2] == 0:
                 field._description = "Length Code %i, Value %i (Huffman Code %i)" % (value, info[0], field.value)
                 length = info[0]
                 yield field
             else:
                 field._description = "Length Code %i, Values %i to %i (Huffman Code %i)" % (
                 value, info[0], info[1], field.value)
                 yield field
                 extrafield = Bits(self, "length_extra[%s" % field.name.split('[')[1], info[2])
                 length = extrafield.value + info[0]
                 extrafield._description = "Length Extra Bits (%i), total length %i" % (extrafield.value, length)
                 yield extrafield
             field = HuffmanCode(self, "distance_code[]", distance_tree)
             value = field.realvalue
             info = self.DISTANCE_SYMBOLS[value]
             if info[2] == 0:
                 field._description = "Distance Code %i, Value %i (Huffman Code %i)" % (value, info[0], field.value)
                 distance = info[0]
                 yield field
             else:
                 field._description = "Distance Code %i, Values %i to %i (Huffman Code %i)" % (
                 value, info[0], info[1], field.value)
                 yield field
                 extrafield = Bits(self, "distance_extra[%s" % field.name.split('[')[1], info[2])
                 distance = extrafield.value + info[0]
                 extrafield._description = "Distance Extra Bits (%i), total length %i" % (extrafield.value, distance)
                 yield extrafield
             self.uncomp_data = extend_data(self.uncomp_data, length, distance)
Ejemplo n.º 10
0
 def createFields(self):
     yield Bits(self, "block_type", 3)
     yield Bits(self, "block_size", 24)
     self.uncompressed_size = self["block_size"].value
     self.compression_level = self.root.compr_level
     self.window_size = self.WINDOW_SIZE[self.compression_level]
     self.block_type = self["block_type"].value
     curlen = len(self.parent.uncompressed_data)
     if self.block_type in (1, 2):  # Verbatim or aligned offset block
         if self.block_type == 2:
             for i in xrange(8):
                 yield Bits(self, "aligned_len[]", 3)
             aligned_tree = build_tree([self['aligned_len[%d]' % i].value for i in xrange(8)])
         yield LZXPreTreeEncodedTree(self, "main_tree_start", 256)
         yield LZXPreTreeEncodedTree(self, "main_tree_rest", self.window_size * 8)
         main_tree = build_tree(self["main_tree_start"].lengths + self["main_tree_rest"].lengths)
         yield LZXPreTreeEncodedTree(self, "length_tree", 249)
         length_tree = build_tree(self["length_tree"].lengths)
         current_decoded_size = 0
         while current_decoded_size < self.uncompressed_size:
             if (curlen + current_decoded_size) % 32768 == 0 and (curlen + current_decoded_size) != 0:
                 padding = paddingSize(self.address + self.current_size, 16)
                 if padding:
                     yield PaddingBits(self, "padding[]", padding)
             field = HuffmanCode(self, "main_code[]", main_tree)
             if field.realvalue < 256:
                 field._description = "Literal value %r" % chr(field.realvalue)
                 current_decoded_size += 1
                 self.parent.uncompressed_data += chr(field.realvalue)
                 yield field
                 continue
             position_header, length_header = divmod(field.realvalue - 256, 8)
             info = self.POSITION_SLOTS[position_header]
             if info[2] == 0:
                 if info[0] == 0:
                     position = self.parent.r0
                     field._description = "Position Slot %i, Position [R0] (%i)" % (position_header, position)
                 elif info[0] == 1:
                     position = self.parent.r1
                     self.parent.r1 = self.parent.r0
                     self.parent.r0 = position
                     field._description = "Position Slot %i, Position [R1] (%i)" % (position_header, position)
                 elif info[0] == 2:
                     position = self.parent.r2
                     self.parent.r2 = self.parent.r0
                     self.parent.r0 = position
                     field._description = "Position Slot %i, Position [R2] (%i)" % (position_header, position)
                 else:
                     position = info[0] - 2
                     self.parent.r2 = self.parent.r1
                     self.parent.r1 = self.parent.r0
                     self.parent.r0 = position
                     field._description = "Position Slot %i, Position %i" % (position_header, position)
             else:
                 field._description = "Position Slot %i, Positions %i to %i" % (
                 position_header, info[0] - 2, info[1] - 2)
             if length_header == 7:
                 field._description += ", Length Values 9 and up"
                 yield field
                 length_field = HuffmanCode(self, "length_code[]", length_tree)
                 length = length_field.realvalue + 9
                 length_field._description = "Length Code %i, total length %i" % (length_field.realvalue, length)
                 yield length_field
             else:
                 field._description += ", Length Value %i (Huffman Code %i)" % (length_header + 2, field.value)
                 yield field
                 length = length_header + 2
             if info[2]:
                 if self.block_type == 1 or info[2] < 3:  # verbatim
                     extrafield = Bits(self, "position_extra[%s" % field.name.split('[')[1], info[2])
                     position = extrafield.value + info[0] - 2
                     extrafield._description = "Position Extra Bits (%i), total position %i" % (
                     extrafield.value, position)
                     yield extrafield
                 else:  # aligned offset
                     position = info[0] - 2
                     if info[2] > 3:
                         extrafield = Bits(self, "position_verbatim[%s" % field.name.split('[')[1], info[2] - 3)
                         position += extrafield.value * 8
                         extrafield._description = "Position Verbatim Bits (%i), added position %i" % (
                         extrafield.value, extrafield.value * 8)
                         yield extrafield
                     if info[2] >= 3:
                         extrafield = HuffmanCode(self, "position_aligned[%s" % field.name.split('[')[1],
                                                  aligned_tree)
                         position += extrafield.realvalue
                         extrafield._description = "Position Aligned Bits (%i), total position %i" % (
                         extrafield.realvalue, position)
                         yield extrafield
                 self.parent.r2 = self.parent.r1
                 self.parent.r1 = self.parent.r0
                 self.parent.r0 = position
             self.parent.uncompressed_data = extend_data(self.parent.uncompressed_data, length, position)
             current_decoded_size += length
     elif self.block_type == 3:  # Uncompressed block
         padding = paddingSize(self.address + self.current_size, 16)
         if padding:
             yield PaddingBits(self, "padding[]", padding)
         else:
             yield PaddingBits(self, "padding[]", 16)
         self.endian = LITTLE_ENDIAN
         yield UInt32(self, "r[]", "New value of R0")
         yield UInt32(self, "r[]", "New value of R1")
         yield UInt32(self, "r[]", "New value of R2")
         self.parent.r0 = self["r[0]"].value
         self.parent.r1 = self["r[1]"].value
         self.parent.r2 = self["r[2]"].value
         yield RawBytes(self, "data", self.uncompressed_size)
         self.parent.uncompressed_data += self["data"].value
         if self["block_size"].value % 2:
             yield PaddingBits(self, "padding", 8)
     else:
         raise ParserError("Unknown block type %d!" % self.block_type)
Ejemplo n.º 11
0
 def createFields(self):
     yield Bit(self, "final", "Is this the final block?")  # BFINAL
     yield Enum(
         Bits(self, "compression_type", 2),  # BTYPE
         {
             0: "None",
             1: "Fixed Huffman",
             2: "Dynamic Huffman",
             3: "Reserved"
         })
     if self["compression_type"].value == 0:  # no compression
         padding = paddingSize(self.current_size + self.absolute_address,
                               8)  # align on byte boundary
         if padding:
             yield PaddingBits(self, "padding[]", padding)
         yield Int16(self, "len")
         yield Int16(self, "nlen", "One's complement of len")
         if self["len"].value != ~self["nlen"].value:
             raise ParserError(
                 "len must be equal to the one's complement of nlen!")
         if self["len"].value:  # null stored blocks produced by some encoders (e.g. PIL)
             yield RawBytes(self, "data", self["len"].value,
                            "Uncompressed data")
         return
     elif self["compression_type"].value == 1:  # Fixed Huffman
         length_tree = {}  # (size, huffman code): value
         distance_tree = {}
         for i in xrange(144):
             length_tree[(8, i + 48)] = i
         for i in xrange(144, 256):
             length_tree[(9, i + 256)] = i
         for i in xrange(256, 280):
             length_tree[(7, i - 256)] = i
         for i in xrange(280, 288):
             length_tree[(8, i - 88)] = i
         for i in xrange(32):
             distance_tree[(5, i)] = i
     elif self["compression_type"].value == 2:  # Dynamic Huffman
         yield Bits(self, "huff_num_length_codes", 5,
                    "Number of Literal/Length Codes, minus 257")
         yield Bits(self, "huff_num_distance_codes", 5,
                    "Number of Distance Codes, minus 1")
         yield Bits(self, "huff_num_code_length_codes", 4,
                    "Number of Code Length Codes, minus 4")
         code_length_code_lengths = [0] * 19  # confusing variable name...
         for i in self.CODE_LENGTH_ORDER[:self["huff_num_code_length_codes"]
                                         .value + 4]:
             field = Bits(self, "huff_code_length_code[%i]" % i, 3,
                          "Code lengths for the code length alphabet")
             yield field
             code_length_code_lengths[i] = field.value
         code_length_tree = build_tree(code_length_code_lengths)
         length_code_lengths = []
         distance_code_lengths = []
         for numcodes, name, lengths in (
             (self["huff_num_length_codes"].value + 257, "length",
              length_code_lengths),
             (self["huff_num_distance_codes"].value + 1, "distance",
              distance_code_lengths)):
             while len(lengths) < numcodes:
                 field = HuffmanCode(self, "huff_%s_code[]" % name,
                                     code_length_tree)
                 value = field.realvalue
                 if value < 16:
                     prev_value = value
                     field._description = "Literal Code Length %i (Huffman Code %i)" % (
                         value, field.value)
                     yield field
                     lengths.append(value)
                 else:
                     info = {
                         16: (3, 6, 2),
                         17: (3, 10, 3),
                         18: (11, 138, 7)
                     }[value]
                     if value == 16:
                         repvalue = prev_value
                     else:
                         repvalue = 0
                     field._description = "Repeat Code %i, Repeating value (%i) %i to %i times (Huffman Code %i)" % (
                         value, repvalue, info[0], info[1], field.value)
                     yield field
                     extrafield = Bits(
                         self, "huff_%s_code_extra[%s" %
                         (name, field.name.split('[')[1]), info[2])
                     num_repeats = extrafield.value + info[0]
                     extrafield._description = "Repeat Extra Bits (%i), total repeats %i" % (
                         extrafield.value, num_repeats)
                     yield extrafield
                     lengths += [repvalue] * num_repeats
         length_tree = build_tree(length_code_lengths)
         distance_tree = build_tree(distance_code_lengths)
     else:
         raise ParserError("Unsupported compression type 3!")
     while True:
         field = HuffmanCode(self, "length_code[]", length_tree)
         value = field.realvalue
         if value < 256:
             field._description = "Literal Code %r (Huffman Code %i)" % (
                 chr(value), field.value)
             yield field
             self.uncomp_data += chr(value)
         if value == 256:
             field._description = "Block Terminator Code (256) (Huffman Code %i)" % field.value
             yield field
             break
         elif value > 256:
             info = self.LENGTH_SYMBOLS[value]
             if info[2] == 0:
                 field._description = "Length Code %i, Value %i (Huffman Code %i)" % (
                     value, info[0], field.value)
                 length = info[0]
                 yield field
             else:
                 field._description = "Length Code %i, Values %i to %i (Huffman Code %i)" % (
                     value, info[0], info[1], field.value)
                 yield field
                 extrafield = Bits(
                     self, "length_extra[%s" % field.name.split('[')[1],
                     info[2])
                 length = extrafield.value + info[0]
                 extrafield._description = "Length Extra Bits (%i), total length %i" % (
                     extrafield.value, length)
                 yield extrafield
             field = HuffmanCode(self, "distance_code[]", distance_tree)
             value = field.realvalue
             info = self.DISTANCE_SYMBOLS[value]
             if info[2] == 0:
                 field._description = "Distance Code %i, Value %i (Huffman Code %i)" % (
                     value, info[0], field.value)
                 distance = info[0]
                 yield field
             else:
                 field._description = "Distance Code %i, Values %i to %i (Huffman Code %i)" % (
                     value, info[0], info[1], field.value)
                 yield field
                 extrafield = Bits(
                     self, "distance_extra[%s" % field.name.split('[')[1],
                     info[2])
                 distance = extrafield.value + info[0]
                 extrafield._description = "Distance Extra Bits (%i), total length %i" % (
                     extrafield.value, distance)
                 yield extrafield
             self.uncomp_data = extend_data(self.uncomp_data, length,
                                            distance)
Ejemplo n.º 12
0
 def createFields(self):
     yield Bits(self, "block_type", 3)
     yield Bits(self, "block_size", 24)
     self.uncompressed_size = self["block_size"].value
     self.compression_level = self.root.compr_level
     self.window_size = self.WINDOW_SIZE[self.compression_level]
     self.block_type = self["block_type"].value
     curlen = len(self.parent.uncompressed_data)
     if self.block_type in (1, 2):  # Verbatim or aligned offset block
         if self.block_type == 2:
             for i in range(8):
                 yield Bits(self, "aligned_len[]", 3)
             aligned_tree = build_tree(
                 [self['aligned_len[%d]' % i].value for i in range(8)])
         yield LZXPreTreeEncodedTree(self, "main_tree_start", 256)
         yield LZXPreTreeEncodedTree(self, "main_tree_rest",
                                     self.window_size * 8)
         main_tree = build_tree(self["main_tree_start"].lengths +
                                self["main_tree_rest"].lengths)
         yield LZXPreTreeEncodedTree(self, "length_tree", 249)
         length_tree = build_tree(self["length_tree"].lengths)
         current_decoded_size = 0
         while current_decoded_size < self.uncompressed_size:
             if (curlen + current_decoded_size) % 32768 == 0 and (
                     curlen + current_decoded_size) != 0:
                 padding = paddingSize(self.address + self.current_size, 16)
                 if padding:
                     yield PaddingBits(self, "padding[]", padding)
             field = HuffmanCode(self, "main_code[]", main_tree)
             if field.realvalue < 256:
                 field._description = "Literal value %r" % chr(
                     field.realvalue)
                 current_decoded_size += 1
                 self.parent.uncompressed_data += chr(field.realvalue)
                 yield field
                 continue
             position_header, length_header = divmod(
                 field.realvalue - 256, 8)
             info = self.POSITION_SLOTS[position_header]
             if info[2] == 0:
                 if info[0] == 0:
                     position = self.parent.r0
                     field._description = "Position Slot %i, Position [R0] (%i)" % (
                         position_header, position)
                 elif info[0] == 1:
                     position = self.parent.r1
                     self.parent.r1 = self.parent.r0
                     self.parent.r0 = position
                     field._description = "Position Slot %i, Position [R1] (%i)" % (
                         position_header, position)
                 elif info[0] == 2:
                     position = self.parent.r2
                     self.parent.r2 = self.parent.r0
                     self.parent.r0 = position
                     field._description = "Position Slot %i, Position [R2] (%i)" % (
                         position_header, position)
                 else:
                     position = info[0] - 2
                     self.parent.r2 = self.parent.r1
                     self.parent.r1 = self.parent.r0
                     self.parent.r0 = position
                     field._description = "Position Slot %i, Position %i" % (
                         position_header, position)
             else:
                 field._description = "Position Slot %i, Positions %i to %i" % (
                     position_header, info[0] - 2, info[1] - 2)
             if length_header == 7:
                 field._description += ", Length Values 9 and up"
                 yield field
                 length_field = HuffmanCode(self, "length_code[]",
                                            length_tree)
                 length = length_field.realvalue + 9
                 length_field._description = "Length Code %i, total length %i" % (
                     length_field.realvalue, length)
                 yield length_field
             else:
                 field._description += ", Length Value %i (Huffman Code %i)" % (
                     length_header + 2, field.value)
                 yield field
                 length = length_header + 2
             if info[2]:
                 if self.block_type == 1 or info[2] < 3:  # verbatim
                     extrafield = Bits(
                         self,
                         "position_extra[%s" % field.name.split('[')[1],
                         info[2])
                     position = extrafield.value + info[0] - 2
                     extrafield._description = "Position Extra Bits (%i), total position %i" % (
                         extrafield.value, position)
                     yield extrafield
                 else:  # aligned offset
                     position = info[0] - 2
                     if info[2] > 3:
                         extrafield = Bits(
                             self, "position_verbatim[%s" %
                             field.name.split('[')[1], info[2] - 3)
                         position += extrafield.value * 8
                         extrafield._description = "Position Verbatim Bits (%i), added position %i" % (
                             extrafield.value, extrafield.value * 8)
                         yield extrafield
                     if info[2] >= 3:
                         extrafield = HuffmanCode(
                             self, "position_aligned[%s" %
                             field.name.split('[')[1], aligned_tree)
                         position += extrafield.realvalue
                         extrafield._description = "Position Aligned Bits (%i), total position %i" % (
                             extrafield.realvalue, position)
                         yield extrafield
                 self.parent.r2 = self.parent.r1
                 self.parent.r1 = self.parent.r0
                 self.parent.r0 = position
             self.parent.uncompressed_data = extend_data(
                 self.parent.uncompressed_data, length, position)
             current_decoded_size += length
     elif self.block_type == 3:  # Uncompressed block
         padding = paddingSize(self.address + self.current_size, 16)
         if padding:
             yield PaddingBits(self, "padding[]", padding)
         else:
             yield PaddingBits(self, "padding[]", 16)
         self.endian = LITTLE_ENDIAN
         yield UInt32(self, "r[]", "New value of R0")
         yield UInt32(self, "r[]", "New value of R1")
         yield UInt32(self, "r[]", "New value of R2")
         self.parent.r0 = self["r[0]"].value
         self.parent.r1 = self["r[1]"].value
         self.parent.r2 = self["r[2]"].value
         yield RawBytes(self, "data", self.uncompressed_size)
         self.parent.uncompressed_data += self["data"].value
         if self["block_size"].value % 2:
             yield PaddingBits(self, "padding", 8)
     else:
         raise ParserError("Unknown block type %d!" % self.block_type)