📄 arith.cpp
字号:
// These objects implement arithmetic coding as described in
// Bell, Cleary, and Witten "Text Compression" Prentice Hall.
#include <iostream.h>
#include <iomanip.h>
#include <assert.h>
#include <math.h>
#include "global.h"
#include "BitIO.h"
#include "iHisto.h"
#include "Arith.h"
const int CodingValues::CodeValueBits = 16;
const long CodingValues::MaxFreq = ((long)1 << (CodeValueBits - 2)) - 1;
const long CodingValues::One = ((long)1 << CodeValueBits) - 1;
const long CodingValues::Qtr = One / 4 + 1;
const long CodingValues::Half = 2 * Qtr;
const long CodingValues::ThreeQtr = 3 * Qtr;
ArithEncoder::ArithEncoder(BitOut &bo) : output(bo)
{
low = 0;
high = One;
bitsToFollow = 0;
}
void
ArithEncoder::flush(void)
{
for (int i = 0; i < CodeValueBits; i++) {
if (low >= Half) {
bpf(1);
low -= Half;
} else {
bpf(0);
}
low = 2 * low;
}
output.flush();
}
void ArithEncoder::Encode(int count, int countLeft, int countTot)
{
// cerr << "Encode(" << count << ", " << countLeft << ", " << countTot << ")\n";
assert(count);
long range = high - low + 1;
high = low + (range * (countLeft + count)) / countTot - 1;
low = low + (range * countLeft) / countTot;
while (1) {
if (high < Half) {
bpf(0);
} else if (low >= Half) {
bpf(1);
low -= Half;
high -= Half;
} else if (low >= Qtr && high < ThreeQtr) {
bitsToFollow++;
low -= Qtr;
high -= Qtr;
} else {
break;
}
low = 2 * low;
high = 2 * high + 1;
}
}
ArithDecoder::ArithDecoder(BitIn &bi) : input(bi)
{
low = 0;
high = One;
value = 0;
for (int i = 0; i < CodeValueBits; i++) {
value = (value << 1) + input.input_bit();
}
}
int
ArithDecoder::Decode(iHistogram &h)
{
long range;
int cum;
int answer;
int ct, ctLeft, ctTotal;
ctTotal = h.TotalCount();
range = high - low + 1;
cum = (((long)(value - low) + 1) * ctTotal - 1) / range;
answer = h.Symbol(cum);
ct = h.Count(answer); ctLeft = h.LeftCount(answer);
// cerr << "Decoder : cum= " << cum << "-> " << answer << "\n";
// cerr << " ct = " << ct << " ctLeft = " << ctLeft << " ctTotal = " << ctTotal << "\n";
high = low + (range * (ctLeft + ct)) / ctTotal - 1;
low = low + (range * ctLeft) / ctTotal;
while (1) {
if (high < Half) {
;
} else if (low >= Half) {
value -= Half;
low -= Half;
high -= Half;
}
else if (low >= Qtr
&& high < ThreeQtr) {
value -= Qtr;
low -= Qtr;
high -= Qtr;
}
else break;
low = 2 * low;
high = 2 * high + 1;
value = 2 * value + input.input_bit();
}
return answer;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -