Ejemplo n.º 1
0
def decompress(data: bytes) -> bytes:
    rdr = BinaryReader(data)
    wtr = BinaryWriter()
    compression_type = rdr.read_uint8()
    if compression_type == 0x24:
        blocksize = 4
    elif compression_type == 0x28:
        blocksize = 8
    else:
        raise Exception(
            "Tried to decompress something as huffman that isn't huffman")
    ds = rdr.read_uint24()
    if ds == 0:
        rdr.read_uint32()

    # Read the tree
    treesize = (rdr.read_uint8() + 1) * 2
    tree_end = (rdr.c - 1) + treesize
    rootNode = HuffTreeNode.from_rdr(rdr, False, 5, tree_end)
    rdr.c = tree_end

    # Decompress with the tree
    bitsleft = 0  # amount of bits left to read from {commands}
    current_size = 0
    currentNode = rootNode

    cashedbyte = -1

    while current_size < ds:
        # Find next refrence to commands node
        while not currentNode.is_data:
            if bitsleft == 0:
                data = rdr.read_uint32()
                bitsleft = 32

            bitsleft -= 1
            nextIsOne = (data & (1 << bitsleft)) != 0
            if nextIsOne:
                currentNode = currentNode.child1
            else:
                currentNode = currentNode.child0

        if blocksize == 8:
            current_size += 1
            wtr.write_uint8(currentNode.data)

        elif blocksize == 4:
            if cashedbyte < 0:
                cashedbyte = currentNode.data
            else:
                cashedbyte |= currentNode.data << 4
                wtr.write_uint8(cashedbyte)
                current_size += 1
                cashedbyte = -1
        currentNode = rootNode

    return wtr.data
Ejemplo n.º 2
0
    def from_rdr(cls,
                 rdr: BinaryReader,
                 is_data: bool,
                 relative_offset,
                 max_stream_pos,
                 parent=None):
        self = cls(is_data, parent=parent)
        if rdr.c >= max_stream_pos:
            return
        self.data = rdr.read_uint8()
        if not is_data:
            offset = self.data & 0x3F
            zeroIsData = (self.data & 0x80) > 0
            oneIsData = (self.data & 0x40) > 0

            # off AND NOT == off XOR (off AND 1)
            zeroRelOffset = (relative_offset ^
                             (relative_offset & 1)) + offset * 2 + 2

            currStreamPos = rdr.c

            rdr.c += (zeroRelOffset - relative_offset) - 1

            # Node after 0
            self.child0 = HuffTreeNode.from_rdr(rdr,
                                                zeroIsData,
                                                zeroRelOffset,
                                                max_stream_pos,
                                                parent=self)
            # Node after 1 directly located after the node after 0
            self.child1 = HuffTreeNode.from_rdr(rdr,
                                                oneIsData,
                                                zeroRelOffset + 1,
                                                max_stream_pos,
                                                parent=self)

            # reset stream
            rdr.c = currStreamPos
        return self