Skip to content

Commit c5b1694

Browse files
author
kazuho
committed
altered version of http://codezine.jp/a/article.aspx?aid=443 by okanohara-san with handling of eof optimized
git-svn-id: http://svn.coderepos.org/share/lang/cplusplus/range_coder@7043 d0d07461-0603-4401-acd4-de1884942a52
1 parent fd41e90 commit c5b1694

File tree

1 file changed

+137
-0
lines changed

1 file changed

+137
-0
lines changed

range_coder.hpp

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#ifndef __RANGE_CODER_HPP__
2+
#define __RANGE_CODER_HPP__
3+
4+
// original work by Daisuke Okanohara 2006/06/16
5+
6+
struct rc_type_t {
7+
enum {
8+
TOP = 1U << 24,
9+
TOPMASK = TOP - 1,
10+
};
11+
typedef unsigned int uint;
12+
typedef unsigned char byte;
13+
};
14+
15+
template <class Store> class rc_encoder_t : public rc_type_t {
16+
public:
17+
rc_encoder_t(Store *_store) : store(_store) {
18+
L = 0;
19+
R = 0xFFFFFFFF;
20+
buffer = 0;
21+
carryN = 0;
22+
counter = 0;
23+
start = true;
24+
}
25+
void encode(const uint low, const uint high, const uint total) {
26+
uint r = R / total;
27+
if (high < total) {
28+
R = r * (high-low);
29+
} else {
30+
R -= r * low;
31+
}
32+
uint newL = L + r*low;
33+
if (newL < L) {
34+
//overflow occured (newL >= 2^32)
35+
//buffer FF FF .. FF -> buffer+1 00 00 .. 00
36+
buffer++;
37+
for (;carryN > 0; carryN--) {
38+
store->push_back(buffer);
39+
buffer = 0;
40+
}
41+
}
42+
L = newL;
43+
while (R < TOP) {
44+
const byte newBuffer = (L >> 24);
45+
if (start) {
46+
buffer = newBuffer;
47+
start = false;
48+
} else if (newBuffer == 0xFF) {
49+
carryN++;
50+
} else {
51+
store->push_back(buffer);
52+
for (; carryN != 0; carryN--) {
53+
store->push_back(0xFF);
54+
}
55+
buffer = newBuffer;
56+
}
57+
L <<= 8;
58+
R <<= 8;
59+
}
60+
counter++;
61+
}
62+
void final() {
63+
store->push_back(buffer);
64+
for (; carryN != 0; carryN--) {
65+
store->push_back(0xFF);
66+
}
67+
uint t = L + R;
68+
while (1) {
69+
uint t8 = t >> 24, l8 = L >> 24;
70+
store->push_back(l8);
71+
if (t8 != l8) {
72+
break;
73+
}
74+
t <<= 8;
75+
L <<= 8;
76+
}
77+
}
78+
private:
79+
uint R;
80+
uint L;
81+
bool start;
82+
byte buffer;
83+
uint carryN;
84+
Store* store;
85+
uint counter;
86+
};
87+
88+
template <class Iterator, unsigned N> class rc_decoder_t : public rc_type_t {
89+
public:
90+
rc_decoder_t(const Iterator& _i, const Iterator _e) : iter(_i), iter_end(_e) {
91+
R = 0xFFFFFFFF;
92+
D = 0;
93+
for (int i = 0; i < 4; i++) {
94+
D = (D << 8) | next();
95+
}
96+
}
97+
uint decode(const uint total, const uint* cumFreq) {
98+
const uint r = R / total;
99+
const uint targetPos = std::min(total-1, D / r);
100+
101+
//find target s.t. cumFreq[target] <= targetPos < cumFreq[target+1]
102+
uint left = 0;
103+
uint right = N;
104+
while(left < right) {
105+
uint mid = (left+right)/2;
106+
if (cumFreq[mid+1] <= targetPos) left = mid+1;
107+
else right = mid;
108+
}
109+
110+
const uint target = left;
111+
const uint low = cumFreq[target];
112+
const uint high = cumFreq[target+1];
113+
114+
D -= r * low;
115+
if (high != total) {
116+
R = r * (high-low);
117+
} else {
118+
R -= r * low;
119+
}
120+
121+
while (R < TOP) {
122+
R <<= 8;
123+
D = (D << 8) | next();
124+
}
125+
126+
return target;
127+
}
128+
byte next() {
129+
return iter != iter_end ? (byte)*iter++ : 0xff;
130+
}
131+
private:
132+
uint R;
133+
uint D;
134+
Iterator iter, iter_end;
135+
};
136+
137+
#endif

0 commit comments

Comments
 (0)