-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmtfrle.c
130 lines (109 loc) · 3.4 KB
/
mtfrle.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#define DICTIONARY_SIZE 258
#define RLE true
static uint16_t runA = 0;
static uint16_t runB = 1;
static uint16_t EOFF = 257;
uint32_t mtf_encode(uint8_t *arr_in, uint32_t arr_in_length, uint16_t *arr_out) {
uint8_t dictionary[DICTIONARY_SIZE];
for (int i = 0; i < DICTIONARY_SIZE; i++) {
dictionary[i] = i;
}
int index;
uint16_t c;
int offset = 0;
for (int i = 0; i < arr_in_length; i++) {
c = arr_in[i];
// Search dictionary for item
for (int j = 0; j < DICTIONARY_SIZE; j++) {
if (c == dictionary[j]) {
index = j;
break;
}
}
// Run length encode 0
if (index == 0 && RLE) {
uint32_t k = 1;
while (i + k < arr_in_length && c == arr_in[i + k]) {
k++;
}
uint32_t bits_required = floor(log2(k + 1));
uint32_t k_other = k + 1 - (1 << bits_required);
//printf("k = %d, k2 = %d: ", k, kkk);
for (int j = 0; j < bits_required; j++) {
if ((k_other >> j) & 1) {
// Bit is 1
arr_out[i + j - offset] = runB;
//printf("%d", runB);
} else {
// Bit is 0
arr_out[i + j - offset] = runA;
//printf("%d", runA);
}
}
//printf("\n");
offset += k - bits_required;
i += k - 1;
} else {
// Replace with arr value
arr_out[i - offset] = index + 1;
// Move the value to the front of the list
for (int j = index; j > 0; j--) {
dictionary[j] = dictionary[j - 1];
}
dictionary[0] = c;
}
}
if (offset == 0) {
printf("ERROR.. Nothing was compressed.. can't add EOF");
return 0;
}
arr_out[arr_in_length - offset] = EOFF;
return arr_in_length - offset + 1;
}
uint32_t mtf_decode(uint16_t *arr_in, uint32_t arr_in_length, uint8_t *arr_out) {
int offset = 0;
uint8_t dictionary[DICTIONARY_SIZE];
for (int i = 0; i < DICTIONARY_SIZE; i++) {
dictionary[i] = i;
}
uint8_t c;
int index;
for (int i = 0; i < arr_in_length; i++) {
index = arr_in[i];
if ((index == runA || index == runB) && RLE) {
int s = 0;
if (index == runB) {
s = 1;
}
int k = 1;
while (i + k < arr_in_length && ((index = arr_in[i + k]) == runA || index == runB)) {
if (index == runB) {
s = s + (1 << k);
}
k++;
}
s = s + (1 << k) - 1;
for (int j = 0; j < s; j++) {
arr_out[i + offset + j] = dictionary[0];
}
offset += s - k;
i += k - 1;
} else {
index = index - 1;
// Get value
c = dictionary[index];
arr_out[i + offset] = c;
// Move array forward
for (int j = index; j > 0; j--) {
dictionary[j] = dictionary[j - 1];
}
dictionary[0] = c;
}
}
return arr_in_length + offset - 1;
}