📄 arithmetic_codec.cpp
字号:
x = M.distribution[s] * (length >> DM__LengthShift);
base += x; // update interval
length -= x; // no product needed
}
else {
x = M.distribution[s] * (length >>= DM__LengthShift);
base += x; // update interval
length = M.distribution[s+1] * length - x;
}
if (init_base > base) propagate_carry(); // overflow = carry
if (length < AC__MinLength) renorm_enc_interval(); // renormalization
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unsigned Arithmetic_Codec::decode(Static_Data_Model & M)
{
#ifdef _DEBUG
if (mode != 2) AC_Error("decoder not initialized");
#endif
unsigned s, n, x, y = length, m = M.first_tests[1];
unsigned z = M.distribution[m] * (length >>= DM__LengthShift);
if (z > value) { // first predefined test based on probabilities
n = m; // initialize search from bottom and define next test
y = z;
x = s = 0;
m = M.first_tests[0];
}
else { // initialize search from top and define next test
s = m;
x = z;
n = M.data_symbols;
m = M.first_tests[2];
}
if (n - s > 1) // if necessary finish with bisection search
do {
z = length * M.distribution[m];
if (z > value) {
n = m;
y = z; // value is smaller
}
else {
s = m;
x = z; // value is larger or equal
}
} while ((m = (s + n) >> 1) != s);
value -= x; // update interval
length = y - x;
if (length < AC__MinLength) renorm_dec_interval(); // renormalization
return M.data[s]; // return decoded data value
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Arithmetic_Codec::encode(unsigned data,
Adaptive_Data_Model & M)
{
#ifdef _DEBUG
if (mode != 1) AC_Error("encoder not initialized");
if (data >= M.data_symbols) AC_Error("invalid data symbol");
#endif
unsigned x, init_base = base, s = M.rank[data]; // symbol = rank
// compute products
if (s == M.most_probable_symbol) {
x = M.distribution[s] * (length >> DM__LengthShift);
base += x; // update interval
length -= x; // no product needed
}
else {
x = M.distribution[s] * (length >>= DM__LengthShift);
base += x; // update interval
length = M.distribution[s+1] * length - x;
}
if (init_base > base) propagate_carry(); // overflow = carry
if (length < AC__MinLength) renorm_enc_interval(); // renormalization
++M.symbol_count[s];
if (--M.symbols_until_update == 0) M.update(); // periodic model update
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unsigned Arithmetic_Codec::decode(Adaptive_Data_Model & M)
{
#ifdef _DEBUG
if (mode != 2) AC_Error("decoder not initialized");
#endif
unsigned s, n, x, y = length, m = M.first_tests[1];
unsigned z = M.distribution[m] * (length >>= DM__LengthShift);
if (z > value) { // first predefined test based on probabilities
n = m; // initialize search from bottom and define next test
y = z;
x = s = 0;
m = M.first_tests[0];
}
else { // initialize search from top and define next test
s = m;
x = z;
n = M.data_symbols;
m = M.first_tests[2];
}
if (n - s > 1) // if necessary finish with bisection search
do {
z = length * M.distribution[m];
if (z > value) {
n = m;
y = z; // value is smaller
}
else {
s = m;
x = z; // value is larger or equal
}
} while ((m = (s + n) >> 1) != s);
value -= x; // update interval
length = y - x;
if (length < AC__MinLength) renorm_dec_interval(); // renormalization
++M.symbol_count[s];
if (--M.symbols_until_update) return M.data[s]; // return decoded data
unsigned data = M.data[s]; // save data value before changes
M.update(); // periodic model update
return data; // return decoded data
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - Other Arithmetic_Codec implementations - - - - - - - - - - - - - - - -
Arithmetic_Codec::Arithmetic_Codec(void)
{
mode = buffer_size = 0;
new_buffer = code_buffer = 0;
}
Arithmetic_Codec::Arithmetic_Codec(unsigned max_code_bytes,
unsigned char * user_buffer)
{
mode = buffer_size = 0;
new_buffer = code_buffer = 0;
set_buffer(max_code_bytes, user_buffer);
}
Arithmetic_Codec::~Arithmetic_Codec(void)
{
delete [] new_buffer;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Arithmetic_Codec::set_buffer(unsigned max_code_bytes,
unsigned char * user_buffer)
{
// test for reasonable sizes
if ((max_code_bytes < 16) || (max_code_bytes > 0x1000000U))
AC_Error("invalid codec buffer size");
if (mode != 0) AC_Error("cannot set buffer while encoding or decoding");
if (user_buffer != 0) { // user provides memory buffer
buffer_size = max_code_bytes;
code_buffer = user_buffer; // set buffer for compressed data
delete [] new_buffer; // free anything previously assigned
new_buffer = 0;
return;
}
if (max_code_bytes <= buffer_size) return; // enough available
buffer_size = max_code_bytes; // assign new memory
delete [] new_buffer; // free anything previously assigned
if ((new_buffer = new unsigned char[buffer_size+16]) == 0) // 16 extra bytes
AC_Error("cannot assign memory for compressed data buffer");
code_buffer = new_buffer; // set buffer for compressed data
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Arithmetic_Codec::start_encoder(void)
{
if (mode != 0) AC_Error("cannot start encoder");
if (buffer_size == 0) AC_Error("no code buffer set");
mode = 1;
base = 0; // initialize encoder variables: interval and pointer
length = AC__MaxLength;
ac_pointer = code_buffer; // pointer to next data byte
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Arithmetic_Codec::start_decoder(void)
{
if (mode != 0) AC_Error("cannot start decoder");
if (buffer_size == 0) AC_Error("no code buffer set");
// initialize decoder: interval, pointer, initial code value
mode = 2;
length = AC__MaxLength;
ac_pointer = code_buffer + 3;
value = (unsigned(code_buffer[0]) << 24)|(unsigned(code_buffer[1]) << 16) |
(unsigned(code_buffer[2]) << 8)| unsigned(code_buffer[3]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Arithmetic_Codec::read_from_file(FILE * code_file)
{
unsigned shift = 0, code_bytes = 0;
int file_byte;
// read variable-length header with number of code bytes
do {
if ((file_byte = getc(code_file)) == EOF)
AC_Error("cannot read code from file");
code_bytes |= unsigned(file_byte & 0x7F) << shift;
shift += 7;
} while (file_byte & 0x80);
// read compressed data
if (code_bytes > buffer_size) AC_Error("code buffer overflow");
if (fread(code_buffer, 1, code_bytes, code_file) != code_bytes)
AC_Error("cannot read code from file");
start_decoder(); // initialize decoder
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unsigned Arithmetic_Codec::stop_encoder(void)
{
if (mode != 1) AC_Error("invalid to stop encoder");
mode = 0;
unsigned init_base = base; // done encoding: set final data bytes
if (length > 2 * AC__MinLength) {
base += AC__MinLength; // base offset
length = AC__MinLength >> 1; // set new length for 1 more byte
}
else {
base += AC__MinLength >> 1; // base offset
length = AC__MinLength >> 9; // set new length for 2 more bytes
}
if (init_base > base) propagate_carry(); // overflow = carry
renorm_enc_interval(); // renormalization = output last bytes
unsigned code_bytes = unsigned(ac_pointer - code_buffer);
if (code_bytes > buffer_size) AC_Error("code buffer overflow");
return code_bytes; // number of bytes used
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unsigned Arithmetic_Codec::write_to_file(FILE * code_file)
{
unsigned header_bytes = 0, code_bytes = stop_encoder(), nb = code_bytes;
// write variable-length header with number of code bytes
do {
int file_byte = int(nb & 0x7FU);
if ((nb >>= 7) > 0) file_byte |= 0x80;
if (putc(file_byte, code_file) == EOF)
AC_Error("cannot write compressed data to file");
header_bytes++;
} while (nb);
// write compressed data
if (fwrite(code_buffer, 1, code_bytes, code_file) != code_bytes)
AC_Error("cannot write compressed data to file");
return code_bytes + header_bytes; // bytes used
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -