Skip to content

Commit ea908d8

Browse files
committed
add huffman decoder
1 parent df9cc22 commit ea908d8

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

huff_dec.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* @file huff_dec.c
3+
* @author Fabjan Sukalia <[email protected]>
4+
* @date 2016-02-03
5+
*/
6+
7+
#include <stdlib.h>
8+
#include <assert.h>
9+
#include "bit_reader.h"
10+
#include "huff_dec.h"
11+
12+
struct huff_dec {
13+
uint8_t max_bits; /* num_entries = 1 << num_bits; */
14+
uint8_t min_bits;
15+
16+
/* high byte: symbol; low byte: num_bits; invalid code if num_bits = 0 */
17+
uint16_t *entries;
18+
};
19+
20+
struct huff_dec *huff_gen_dec(uint8_t code_len[restrict 16], uint8_t symbols[restrict])
21+
{
22+
assert(code_len != NULL);
23+
assert(symbols != NULL);
24+
25+
uint8_t num_sym = 0;
26+
uint8_t max_bits = 0;
27+
uint8_t min_bits = 0;
28+
29+
for (int i = 0; i < 16; i++) {
30+
num_sym += code_len[i];
31+
max_bits = (code_len[i] != 0) ? i + 1 : max_bits;
32+
min_bits = (min_bits == 0 && code_len[i] != 0) ? i + 1 : min_bits;
33+
}
34+
35+
uint8_t num_entries = 1 << max_bits;
36+
37+
struct huff_dec *dec = calloc(1, sizeof(*dec));
38+
dec->max_bits = max_bits;
39+
dec->min_bits = min_bits;
40+
dec->entries = malloc(sizeof(uint16_t) * num_entries);
41+
42+
uint8_t sym_index = 0;
43+
size_t index = 0;
44+
45+
uint16_t times = 1 << max_bits;
46+
for (int i = 0; i < 16; i++) {
47+
times >>= 1;
48+
49+
for (int j = 0; j < code_len[i]; j++) {
50+
uint8_t symbol = symbols[sym_index];
51+
sym_index++;
52+
53+
for (uint16_t t = 0; t < times; t++) {
54+
dec->entries[index] = (symbol << 8) | (i + 1);
55+
index++;
56+
}
57+
}
58+
}
59+
60+
return dec;
61+
}
62+
63+
bool huff_decode_all(struct huff_dec *dec, struct bit_reader *reader, FILE *out, uint32_t num_sym)
64+
{
65+
assert(dec != NULL);
66+
assert(reader != NULL);
67+
assert(out != NULL);
68+
69+
uint16_t sym;
70+
if (!bit_reader_next_bits(reader, &sym, dec->max_bits)) {
71+
fprintf(stderr, "Error while reading input\n");
72+
return false;
73+
}
74+
75+
const uint16_t mask = (1 << dec->max_bits) - 1;
76+
77+
for (uint32_t i = 0; i < num_sym; i++) {
78+
uint16_t entry = dec->entries[sym & mask];
79+
uint8_t symbol = (entry >> 8) & 0xFF;
80+
uint8_t len = entry & 0xFF;
81+
assert(len <= dec->max_bits);
82+
83+
fwrite(&symbol, 1, 1, out);
84+
85+
if (i == num_sym - 1)
86+
break;
87+
88+
uint16_t tmp;
89+
if (!bit_reader_next_bits(reader, &tmp, len)) {
90+
fprintf(stderr, "Error while reading input\n");
91+
return false;
92+
}
93+
sym = ((sym << len) | tmp) & mask;
94+
}
95+
96+
return true;
97+
}
98+
99+
void huff_destroy(struct huff_dec *dec)
100+
{
101+
assert(dec != NULL);
102+
103+
free(dec->entries);
104+
free(dec);
105+
}
106+

huff_dec.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* @file huff_dec.h
3+
* @author Fabjan Sukalia <[email protected]>
4+
* @date 2016-02-03
5+
* @brief Huffman tree generation and decoding.
6+
*/
7+
8+
#ifndef HUFF_DEC_H
9+
#define HUFF_DEC_H
10+
11+
#include <stdint.h>
12+
#include <stdbool.h>
13+
#include <stdio.h>
14+
#include "bit_reader.h"
15+
16+
struct huff_dec;
17+
18+
struct huff_dec *huff_gen_dec(uint8_t code_len[restrict 16], uint8_t symbols[restrict]);
19+
bool huff_decode_all(struct huff_dec *tree, struct bit_reader *reader, FILE *out, uint32_t num_sym);
20+
void huff_destroy(struct huff_dec *tree);
21+
22+
#endif
23+

0 commit comments

Comments
 (0)