use std::io::Read;
use crate::decoders;
use crate::models;
const DEFAULT_BITS: u32 = 16;
const DEFAULT_CONTEXTS: u32 = 1;
const DEFAULT_BITS_HIGH: u32 = 8;
const DEFAULT_RANGE: u32 = 0;
pub const DEFAULT_DECOMPRESS_CONTEXTS: u32 = 0;
const COMPRESS_ONLY_K: bool = false;
#[derive(Clone)]
pub struct IntegerDecompressor {
k: u32,
contexts: u32,
bits_high: u32,
corr_bits: u32,
corr_range: u32,
corr_min: i32,
m_bits: Vec<models::ArithmeticModel>,
m_corrector0: models::ArithmeticBitModel,
m_corrector: Vec<models::ArithmeticModel>,
}
impl IntegerDecompressor {
pub fn new(bits: u32, contexts: u32, bits_high: u32, mut range: u32) -> Self {
let mut corr_bits: u32;
let corr_range: u32;
let corr_min: i32;
if range != 0 {
corr_bits = 0;
corr_range = range;
while range != 0 {
range >>= 1;
corr_bits += 1;
}
if corr_range == 1u32 << (corr_bits - 1) {
corr_bits -= 1;
}
corr_min = -(corr_range as i32 / 2);
} else if bits != 0 && (bits < 32) {
corr_bits = bits;
corr_range = 1u32 << bits;
corr_min = -(corr_range as i32 / 2);
} else {
corr_bits = 32;
corr_range = 0;
corr_min = std::i32::MIN;
}
Self {
k: 0,
contexts,
bits_high,
corr_bits,
corr_range,
corr_min,
m_bits: vec![],
m_corrector0: models::ArithmeticBitModel::new(),
m_corrector: vec![],
}
}
pub fn k(&self) -> u32 {
self.k
}
pub fn init(&mut self) {
if self.m_bits.is_empty() {
for _i in 0..self.contexts {
self.m_bits
.push(models::ArithmeticModel::new(self.corr_bits + 1, false, &[]));
}
if !COMPRESS_ONLY_K {
for i in 1..=self.corr_bits {
let v = if i <= self.bits_high {
1 << i
} else {
1 << self.bits_high
};
self.m_corrector
.push(models::ArithmeticModel::new(v, false, &[]));
}
}
}
}
pub fn decompress<T: Read>(
&mut self,
dec: &mut decoders::ArithmeticDecoder<T>,
pred: i32,
context: u32,
) -> std::io::Result<i32> {
let m_bit = &mut self.m_bits[context as usize];
let corr = {
let mut c: i32;
self.k = dec.decode_symbol(m_bit)?;
if COMPRESS_ONLY_K {
if self.k != 0 {
if self.k < 32 {
c = dec.read_bits(self.k)? as i32;
if c >= (1u32 << (self.k - 1)) as i32 {
c += 1;
} else {
c -= ((1u32 << self.k) - 1) as i32;
}
} else {
c = self.corr_min;
}
} else {
c = dec.read_bit()? as i32;
}
}
else {
if self.k != 0 {
if self.k < 32 {
if self.k <= self.bits_high {
c = dec.decode_symbol(&mut self.m_corrector[(self.k - 1) as usize])?
as i32;
} else {
let k1 = self.k - self.bits_high;
c = dec.decode_symbol(&mut self.m_corrector[(self.k - 1) as usize])?
as i32;
let c1 = dec.read_bits(k1)?;
c = (c << k1 as i32) | c1 as i32;
}
if c >= (1u32 << (self.k - 1)) as i32 {
c += 1;
} else {
c -= ((1u32 << self.k) - 1) as i32;
}
} else {
c = self.corr_min;
}
} else {
c = dec.decode_bit(&mut self.m_corrector0)? as i32;
}
} c
};
let mut real = pred.wrapping_add(corr);
if real < 0 {
real += self.corr_range as i32;
} else if real >= self.corr_range as i32 {
real -= self.corr_range as i32
}
Ok(real)
}
}
pub struct IntegerDecompressorBuilder {
bits: u32,
contexts: u32,
bits_high: u32,
range: u32,
}
impl IntegerDecompressorBuilder {
pub fn new() -> Self {
Self {
bits: DEFAULT_BITS,
contexts: DEFAULT_CONTEXTS,
bits_high: DEFAULT_BITS_HIGH,
range: DEFAULT_RANGE,
}
}
pub fn bits(&mut self, bits: u32) -> &mut Self {
self.bits = bits;
self
}
pub fn contexts(&mut self, contexts: u32) -> &mut Self {
self.contexts = contexts;
self
}
pub fn build(&self) -> IntegerDecompressor {
IntegerDecompressor::new(self.bits, self.contexts, self.bits_high, self.range)
}
pub fn build_initialized(&self) -> IntegerDecompressor {
let mut idc = self.build();
idc.init();
idc
}
}