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); }
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; } }