int deflate_process_huffman(char *buf, int pos, bitstream_t *bitstream, htree_t *htree_lit, htree_t *htree_dist) { htree_t *literal, *distance; do { literal = huffman_get_symbol(htree_lit, bitstream); if (literal->symbol < 256) { buf[pos++] = literal->symbol; } else if (literal->symbol > 256) { int extra = deflate_extra_bits_for_literal(literal->symbol); int length = read_bits(bitstream, extra); length += deflate_length_for_literal(literal->symbol); distance = huffman_get_symbol(htree_dist, bitstream); extra = deflate_extra_bits_for_distance(distance->symbol); int dist = read_bits(bitstream, extra); dist += deflate_length_for_distance(distance->symbol); for (int i = 0; i < length; i++) { buf[pos + i] = buf[pos - dist + i]; } pos += length; } } while (literal->symbol != 256); return pos; }
void deflate_parse_htrees(bitstream_t *bitstream, htree_t **htree_lit, htree_t **htree_dist) { int hlit = read_bits(bitstream, 5) + 257; int hdist = read_bits(bitstream, 5) + 1; int hclen = read_bits(bitstream, 4) + 4; int cl_order[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; int cl_lengths[19] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; for (int i = 0; i < hclen; i++) { cl_lengths[cl_order[i]] = read_bits(bitstream, 3); } htree_t *ht_cl = huffman_create_tree(19, cl_lengths); int tot = hlit + hdist; int *lengths = calloc(tot, sizeof(int)); int cur_len = 0; while (cur_len < tot) { htree_t *cur_cl = huffman_get_symbol(ht_cl, bitstream); int symbol = 0, repeats = 1; if (cur_cl->symbol == 16) { /* Symbol 16: Copy previous length 3-6 times. */ symbol = lengths[cur_len - 1]; repeats = read_bits(bitstream, 2) + 3; } else if (cur_cl->symbol == 17) { /* Symbol 17: Repeat 0 for 3-10 times. */ repeats = read_bits(bitstream, 3) + 3; } else if (cur_cl->symbol == 18) { /* Symbol 18: Repeat 0 for 11-138 times. */ repeats = read_bits(bitstream, 7) + 11; } else { /* Otherwise: Emit length. */ symbol = cur_cl->symbol; } for (int i = 0; i < repeats; i++) { lengths[cur_len++] = symbol; } } if (cur_len > tot) { printf("Error: Code tree lengths defined too far\n"); } /* We don't need the code length Huffman tree anymore. */ huffman_free_tree(ht_cl); int *lit_lengths = &lengths[0]; int *dist_lengths = &lengths[hlit]; *htree_lit = huffman_create_tree(hlit, lit_lengths); *htree_dist = huffman_create_tree(hdist, dist_lengths); /* Free the data arrays used to create the Huffman trees. */ free(lengths); }
int rle_get(io_buffer * input, rle_state * s) { // // Reverse the encoding performed by rle_bits. // unsigned char output_word = 0; int output_bits = 8; while (1) { if (s->run_length == 0) { s->running_digit = !s->running_digit; int run_length = huffman_get_symbol(&s->huffman[s->running_digit], input); if (run_length < 0) { return -1; } else if(run_length == s->huffman_length[s->running_digit]) { s->run_length = io_buffer_get(input, 24); } else { s->run_length = run_length; } } while (s->run_length > 0) { if (output_bits > s->run_length) { output_word = output_word << s->run_length; if (s->running_digit == 1) { output_word |= ones[s->run_length]; } output_bits -= s->run_length; s->run_length = 0; } else { output_word = output_word << output_bits; if (s->running_digit == 1) { output_word |= ones[output_bits]; } s->run_length -= output_bits; return output_word; } } } }