gistools/readers/las/laz/
integer_compressor.rs

1use super::arithmetic_decoder::{
2    ArithmeticBitModel, ArithmeticDecoder, ArithmeticModel, Corrector,
3};
4use crate::parsers::Reader;
5use alloc::{rc::Rc, vec, vec::Vec};
6use core::cell::RefCell;
7
8const I32_MIN: i32 = 0x80000000u32 as i32;
9const I32_MAX: i32 = 0x7fffffffu32 as i32;
10
11/// <https://github.com/LASzip/LASzip/blob/master/src/integercompressor.cpp>
12#[derive(Debug, Clone)]
13pub struct IntegerCompressor<T: Reader> {
14    /// Arithmetic decoder
15    pub dec: Rc<RefCell<ArithmeticDecoder<T>>>,
16    k: u32,
17    corr_bits: u32,
18    corr_range: u32,
19    /// Corrector minimum
20    pub corr_min: i32,
21    /// Corrector maximum
22    pub corr_max: i32,
23    m_bits: Vec<ArithmeticModel>,
24    m_corrector: Vec<Corrector>,
25    // user defined options
26    bits: u32,
27    contexts: u32,
28    bits_high: u32,
29    range: u32,
30}
31impl<T: Reader> IntegerCompressor<T> {
32    /// Create a new integer compressor
33    pub fn new(
34        dec: Rc<RefCell<ArithmeticDecoder<T>>>,
35        bits: Option<u32>,
36        contexts: Option<u32>,
37        bits_high: Option<u32>,
38        range: Option<u32>,
39    ) -> IntegerCompressor<T> {
40        let mut ic = IntegerCompressor {
41            dec,
42            k: 0,
43            corr_bits: 0,
44            corr_range: 0,
45            corr_min: 0,
46            corr_max: 0,
47            m_bits: vec![],
48            m_corrector: vec![],
49            bits: bits.unwrap_or(16),
50            contexts: contexts.unwrap_or(1),
51            bits_high: bits_high.unwrap_or(8),
52            range: range.unwrap_or(0),
53        };
54
55        if ic.range != 0 {
56            // the corrector's significant bits and range
57            ic.corr_bits = 0;
58            ic.corr_range = ic.range;
59            while ic.range != 0 {
60                ic.range >>= 1;
61                ic.corr_bits += 1;
62            }
63            if ic.corr_range == 1 << (ic.corr_bits - 1) {
64                ic.corr_bits -= 1;
65            }
66            // the corrector must fall into ic interval
67            ic.corr_min = -((ic.corr_range / 2) as i32);
68            ic.corr_max = ic.corr_min + ic.corr_range as i32 - 1;
69        } else if ic.bits != 0 && ic.bits < 32 {
70            ic.corr_bits = ic.bits;
71            ic.corr_range = 1 << ic.bits;
72            // the corrector must fall into ic interval
73            ic.corr_min = -((ic.corr_range / 2) as i32);
74            ic.corr_max = ic.corr_min + ic.corr_range as i32 - 1;
75        } else {
76            ic.corr_bits = 32;
77            ic.corr_range = 0;
78            // the corrector must fall into ic interval
79            ic.corr_min = I32_MIN;
80            ic.corr_max = I32_MAX;
81        }
82
83        ic
84    }
85
86    /// Get the K value in the Compressor
87    pub fn get_k(&self) -> u32 {
88        self.k
89    }
90
91    /// Initialize the decompressor
92    pub fn init_decompressor(&mut self) {
93        // maybe create the models
94        if self.m_bits.is_empty() {
95            self.m_bits = Vec::with_capacity(self.contexts as usize);
96            for _ in 0..self.contexts {
97                self.m_bits.push(ArithmeticModel::new(self.corr_bits + 1, false));
98            }
99            self.m_corrector.push(ArithmeticBitModel::new().into());
100            for i in 1..=self.corr_bits {
101                if i <= self.bits_high {
102                    self.m_corrector.push(ArithmeticModel::new(1 << i, false).into());
103                } else {
104                    self.m_corrector.push(ArithmeticModel::new(1 << self.bits_high, false).into());
105                }
106            }
107        }
108        // certainly init the models
109        for i in 0..self.contexts as usize {
110            self.m_bits[i].init(None);
111        }
112        for i in 0..=self.corr_bits as usize {
113            self.m_corrector[i].init(None);
114        }
115    }
116
117    /// Decompress
118    ///
119    /// ## Parameters
120    /// - `pred`: the predicted value
121    /// - `context`: the context DEFAULTS TO 0 IF NOT GIVEN
122    ///
123    /// ## Returns
124    /// The decompressed value
125    pub fn decompress(&mut self, pred: i32, context: u32) -> i32 {
126        let mut real = pred + self.read_corrector(context);
127        if real < 0 {
128            real += self.corr_range as i32;
129        } else if real as u32 >= self.corr_range {
130            real -= self.corr_range as i32;
131        }
132        real
133    }
134
135    /// Read in the corrector
136    ///
137    /// ## Parameters
138    /// - `m_bits`: the arithmetic model
139    ///
140    /// ## Returns
141    /// The corrector value
142    fn read_corrector(&mut self, context: u32) -> i32 {
143        let mut c: i32 = 0; // I32
144        let mut dec = self.dec.borrow_mut();
145
146        // decode within which interval the corrector is falling
147        self.k = dec.decode_symbol(&mut self.m_bits[context as usize]);
148
149        // decode the exact location of the corrector within the interval
150        if self.k != 0 {
151            // then c is either smaller than 0 or bigger than 1
152            if self.k < 32 {
153                if self.k <= self.bits_high {
154                    // for small k we can do self in one step
155                    // decompress c with the range coder
156                    if let Some(model) = self.m_corrector[self.k as usize].get_model() {
157                        c = dec.decode_symbol(model) as i32;
158                    }
159                } else {
160                    // for larger k we need to do self in two steps
161                    let k1 = self.k as i32 - self.bits_high as i32;
162                    // decompress higher bits with table
163                    if let Some(model) = self.m_corrector[self.k as usize].get_model() {
164                        c = dec.decode_symbol(model) as i32;
165                    }
166                    // read lower bits raw
167                    let c1 = dec.read_bits(k1 as u32) as i32;
168                    // put the corrector back together
169                    c = (c << k1) | c1;
170                }
171                // translate c back into its correct interval
172                if c >= (1 << (self.k - 1)) {
173                    // if c is in the interval [ 2^(k-1)  ...  + 2^k - 1 ]
174                    // so we translate c back into the interval [ 2^(k-1) + 1  ...  2^k ] by adding 1
175                    c += 1;
176                } else {
177                    // otherwise c is in the interval [ 0 ...  + 2^(k-1) - 1 ]
178                    // so we translate c back into the interval [ - (2^k - 1)  ...  - (2^(k-1)) ] by subtracting (2^k - 1)
179                    // c -= (1 << self.k) - 1;
180                    let offset = (1u32 << self.k) - 1;
181                    c = c.wrapping_sub(offset as i32);
182                }
183            } else {
184                c = self.corr_min;
185            }
186        } else {
187            // then c is either 0 or 1
188            if let Some(model) = self.m_corrector[0].get_bit_model() {
189                c = dec.decode_bit(model) as i32;
190            }
191        }
192
193        c
194    }
195}