예제 #1
0
            internal bool getValue(LinkedListNode <byte> code, out int value)
            {
                value = data;
                if (code == null)
                {
                    return(node0 == null && node1 == null && data >= 0);
                }

                if (code.Value > 1)
                {
                    throw new Exception(String.Format("the list should be a list of bytes < 2. got:{0:g}", code.Value));
                }

                byte         c = code.Value;
                bool         retVal;
                HuffTreeNode n = c == 0 ? node0 : node1;

                retVal = n != null && n.getValue(code.Previous, out value);
                return(retVal);
            }
예제 #2
0
        public override byte[] Decompress(byte[] buffer, int offset)
        {
            BinaryReader br = new BinaryReader(new MemoryStream(buffer, offset, buffer.Length - offset));

            byte firstByte = br.ReadByte();
            int  dataSize  = firstByte & 0x0F;

            if (dataSize != 8 && dataSize != 4)
            {
                throw new Exception(string.Format("Unhandled Huffman dataSize {0:x}", dataSize));
            }

            int decomp_size = 0;

            for (int i = 0; i < 3; i++)
            {
                decomp_size |= br.ReadByte() << (i * 8);
            }

            byte treeSize = br.ReadByte();

            HuffTreeNode.maxInpos = 4 + (treeSize + 1) * 2;

            HuffTreeNode rootNode = new HuffTreeNode();

            rootNode.parseData(br);

            br.BaseStream.Position = 4 + (treeSize + 1) * 2;
            uint[] indata = new uint[(br.BaseStream.Length - br.BaseStream.Position) / 4];
            for (int i = 0; i < indata.Length; i++)
            {
                indata[i] = br.ReadUInt32();
            }

            long curr_size = 0;

            decomp_size *= dataSize == 8 ? 1 : 2;
            byte[] outdata = new byte[decomp_size];

            int               idx     = -1;
            string            codestr = "";
            LinkedList <byte> code    = new LinkedList <byte>();
            int               value;

            while (curr_size < decomp_size)
            {
                try
                {
                    string newstr = uint_to_bits(indata[++idx]);
                    codestr += newstr;
                }
                catch (IndexOutOfRangeException e)
                {
                    throw new IndexOutOfRangeException("not enough data.", e);
                }
                while (codestr.Length > 0)
                {
                    code.AddFirst(byte.Parse(codestr[0] + ""));
                    codestr = codestr.Remove(0, 1);
                    if (rootNode.getValue(code.Last, out value))
                    {
                        try
                        {
                            outdata[curr_size++] = (byte)value;
                        }
                        catch (IndexOutOfRangeException ex)
                        {
                            if (code.First.Value != 0)
                            {
                                throw ex;
                            }
                        }
                        code.Clear();
                    }
                }
            }

            br.Close();

            byte[] realout;
            if (dataSize == 4)
            {
                realout = new byte[decomp_size / 2];
                for (int i = 0; i < decomp_size / 2; i++)
                {
                    if ((outdata[i * 2] & 0xF0) > 0 || (outdata[i * 2 + 1] & 0xF0) > 0)
                    {
                        throw new Exception("first 4 bits of data should be 0 if dataSize = 4");
                    }
                    realout[i] = (byte)((outdata[i * 2] << 4) | outdata[i * 2 + 1]);
                }
            }
            else
            {
                realout = outdata;
            }

            return(realout);
        }