示例#1
0
        public static int ReadHuffmanCode(int alphabet_size, HuffmanCode[] tables, int table, BitReader br)
        {
            int  table_size = 0;
            byte simple_code_or_skip;

            byte[] code_lengths = new byte[alphabet_size];

            br.ReadMoreInput();

            /* simple_code_or_skip is used as follows:
             * 1 for simple code;
             * 0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */
            simple_code_or_skip = (byte)br.ReadBits(2);

            if (simple_code_or_skip == 1)
            {
                /* Read symbols, codes & code lengths directly. */
                int   max_bits_counter = alphabet_size - 1;
                int   max_bits         = 0;
                int[] symbols          = new int[4];
                int   num_symbols      = (int)br.ReadBits(2) + 1;

                while (max_bits_counter > 0)
                {
                    max_bits_counter >>= 1;
                    max_bits++;
                }

                for (int i = 0; i < num_symbols; i++)
                {
                    symbols[i] = (int)br.ReadBits(max_bits) % alphabet_size;
                    code_lengths[symbols[i]] = 2;
                }

                code_lengths[symbols[0]] = 1;

                switch (num_symbols)
                {
                case 1:
                    break;

                case 3:
                    if ((symbols[0] == symbols[1]) ||
                        (symbols[0] == symbols[2]) ||
                        (symbols[1] == symbols[2]))
                    {
                        throw new Exception("[ReadHuffmanCode] invalid symbols");
                    }
                    break;

                case 2:
                    if (symbols[0] == symbols[1])
                    {
                        throw new Exception("[ReadHuffmanCode] invalid symbols");
                    }

                    code_lengths[symbols[1]] = 1;
                    break;

                case 4:
                    if ((symbols[0] == symbols[1]) ||
                        (symbols[0] == symbols[2]) ||
                        (symbols[0] == symbols[3]) ||
                        (symbols[1] == symbols[2]) ||
                        (symbols[1] == symbols[3]) ||
                        (symbols[2] == symbols[3]))
                    {
                        throw new Exception("[ReadHuffmanCode] invalid symbols");
                    }

                    if (br.ReadBits(1) == 1)
                    {
                        code_lengths[symbols[2]] = 3;
                        code_lengths[symbols[3]] = 3;
                    }
                    else
                    {
                        code_lengths[symbols[0]] = 2;
                    }
                    break;
                }
            }
            else                  /* Decode Huffman-coded code lengths. */

            {
                byte[] code_length_code_lengths = new byte[CODE_LENGTH_CODES];
                int    space     = 32;
                int    num_codes = 0;

                for (int i = simple_code_or_skip; i < CODE_LENGTH_CODES && space > 0; i++)
                {
                    int    code_len_idx = kCodeLengthCodeOrder[i];
                    int    p            = 0;
                    ushort v;
                    br.FillBitWindow();
                    p += (int)(br.val_ >> br.bit_pos_) & 15;
                    HuffmanCode huff = Huffman.CodeLengthCodeLengths[p];
                    br.bit_pos_ += huff.Bits;
                    v            = huff.Value;
                    code_length_code_lengths[code_len_idx] = (byte)v;

                    if (v != 0)
                    {
                        space -= (32 >> v);
                        ++num_codes;
                    }
                }

                if (!(num_codes == 1 || space == 0))
                {
                    throw new Exception("[ReadHuffmanCode] invalid num_codes or space");
                }

                ReadHuffmanCodeLengths(code_length_code_lengths, alphabet_size, code_lengths, br);
            }

            table_size = Huffman.BuildHuffmanTable(tables, table, HUFFMAN_TABLE_BITS, code_lengths, alphabet_size);

            if (table_size == 0)
            {
                throw new Exception("[ReadHuffmanCode] Huffman.BuildHuffmanTable failed: ");
            }

            return(table_size);
        }
示例#2
0
        public static void ReadHuffmanCodeLengths(byte[] code_length_code_lengths, int num_symbols, byte[] code_lengths, BitReader br)
        {
            int symbol          = 0;
            int prev_code_len   = kDefaultCodeLength;
            int repeat          = 0;
            int repeat_code_len = 0;
            int space           = 32768;

            HuffmanCode[] table = new HuffmanCode[32];

            for (int i = 0; i < 32; i++)
            {
                table[i] = new HuffmanCode(0, 0);
            }

            Huffman.BuildHuffmanTable(table, 0, 5, code_length_code_lengths, CODE_LENGTH_CODES);

            while (symbol < num_symbols && space > 0)
            {
                int  p = 0;
                byte code_len;

                br.ReadMoreInput();
                br.FillBitWindow();
                p           += (int)((br.val_ >> br.bit_pos_) & 31);
                br.bit_pos_ += table[p].Bits;
                code_len     = (byte)table[p].Value;

                if (code_len < kCodeLengthRepeatCode)
                {
                    repeat = 0;

                    code_lengths[symbol++] = (byte)code_len;

                    if (code_len != 0)
                    {
                        prev_code_len = code_len;
                        space        -= 32768 >> code_len;
                    }
                }
                else
                {
                    int extra_bits = code_len - 14;
                    int old_repeat;
                    int repeat_delta;
                    int new_len = 0;

                    if (code_len == kCodeLengthRepeatCode)
                    {
                        new_len = prev_code_len;
                    }

                    if (repeat_code_len != new_len)
                    {
                        repeat          = 0;
                        repeat_code_len = new_len;
                    }

                    old_repeat = repeat;

                    if (repeat > 0)
                    {
                        repeat  -= 2;
                        repeat <<= extra_bits;
                    }

                    repeat      += (int)br.ReadBits(extra_bits) + 3;
                    repeat_delta = repeat - old_repeat;
                    if (symbol + repeat_delta > num_symbols)
                    {
                        throw new Exception("[ReadHuffmanCodeLengths] symbol + repeat_delta > num_symbols");
                    }

                    for (int x = 0; x < repeat_delta; x++)
                    {
                        code_lengths[symbol + x] = (byte)repeat_code_len;
                    }

                    symbol += repeat_delta;

                    if (repeat_code_len != 0)
                    {
                        space -= repeat_delta << (15 - repeat_code_len);
                    }
                }
            }

            if (space != 0)
            {
                throw new Exception("[ReadHuffmanCodeLengths] space = " + space);
            }

            for (; symbol < num_symbols; symbol++)
            {
                code_lengths[symbol] = 0;
            }
        }