laz/decompressors.rs
1/*
2===============================================================================
3
4 CONTENTS:
5 Integer decompressor
6
7 PROGRAMMERS:
8
9 martin.isenburg@rapidlasso.com - http://rapidlasso.com
10 uday.karan@gmail.com - Hobu, Inc.
11
12 COPYRIGHT:
13
14 (c) 2007-2014, martin isenburg, rapidlasso - tools to catch reality
15 (c) 2014, Uday Verma, Hobu, Inc.
16 (c) 2019, Thomas Montaigu
17
18 This is free software; you can redistribute and/or modify it under the
19 terms of the Apache Public License 2.0 published by the Apache Software
20 Foundation. See the COPYING file for more information.
21
22 This software is distributed WITHOUT ANY WARRANTY and without even the
23 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24
25 CHANGE HISTORY:
26 6 June 2019: Translated to Rust
27
28===============================================================================
29*/
30
31use std::io::Read;
32
33use crate::decoders;
34use crate::models;
35
36const DEFAULT_BITS: u32 = 16;
37const DEFAULT_CONTEXTS: u32 = 1;
38const DEFAULT_BITS_HIGH: u32 = 8;
39const DEFAULT_RANGE: u32 = 0;
40
41pub const DEFAULT_DECOMPRESS_CONTEXTS: u32 = 0;
42
43const COMPRESS_ONLY_K: bool = false;
44
45#[derive(Clone)]
46pub struct IntegerDecompressor {
47 k: u32,
48
49 //bits: u32,
50 contexts: u32,
51 bits_high: u32,
52 //range: u32,
53 corr_bits: u32,
54 corr_range: u32,
55 corr_min: i32,
56 //corr_max: i32,
57 m_bits: Vec<models::ArithmeticModel>,
58 m_corrector0: models::ArithmeticBitModel,
59 m_corrector: Vec<models::ArithmeticModel>,
60}
61
62impl IntegerDecompressor {
63 pub fn new(bits: u32, contexts: u32, bits_high: u32, mut range: u32) -> Self {
64 let mut corr_bits: u32;
65 let corr_range: u32;
66 let corr_min: i32;
67 //let corr_max: i32;
68
69 if range != 0 {
70 // the corrector's significant bits and range
71 corr_bits = 0;
72 corr_range = range;
73
74 while range != 0 {
75 range >>= 1;
76 corr_bits += 1;
77 }
78 if corr_range == 1u32 << (corr_bits - 1) {
79 corr_bits -= 1;
80 }
81 // the corrector must fall into this interval
82 corr_min = -(corr_range as i32 / 2);
83 //corr_max = (corr_min + corr_range as i32 - 1) as i32;
84 } else if bits != 0 && (bits < 32) {
85 corr_bits = bits;
86 corr_range = 1u32 << bits;
87 // the corrector must fall into this interval
88 corr_min = -(corr_range as i32 / 2);
89 //corr_max = (corr_min + corr_range as i32 - 1) as i32;
90 } else {
91 corr_bits = 32;
92 corr_range = 0;
93 // the corrector must fall into this interval
94 corr_min = std::i32::MIN;
95 //corr_max = std::i32::MAX;
96 }
97 Self {
98 k: 0,
99 //bits,
100 contexts,
101 bits_high,
102 //range,
103 corr_bits,
104 corr_range,
105 corr_min,
106 m_bits: vec![],
107 m_corrector0: models::ArithmeticBitModel::new(),
108 m_corrector: vec![],
109 }
110 }
111
112 pub fn k(&self) -> u32 {
113 self.k
114 }
115
116 pub fn init(&mut self) {
117 if self.m_bits.is_empty() {
118 for _i in 0..self.contexts {
119 self.m_bits
120 .push(models::ArithmeticModel::new(self.corr_bits + 1, false, &[]));
121 }
122
123 // m_corrector0 is already initialized
124 if !COMPRESS_ONLY_K {
125 for i in 1..=self.corr_bits {
126 let v = if i <= self.bits_high {
127 1 << i
128 } else {
129 1 << self.bits_high
130 };
131 self.m_corrector
132 .push(models::ArithmeticModel::new(v, false, &[]));
133 }
134 }
135 }
136 }
137
138 pub fn decompress<T: Read>(
139 &mut self,
140 dec: &mut decoders::ArithmeticDecoder<T>,
141 pred: i32,
142 context: u32,
143 ) -> std::io::Result<i32> {
144 let m_bit = &mut self.m_bits[context as usize];
145 //--- read corrector ---//
146 let corr = {
147 let mut c: i32;
148 // decode within which interval the corrector is falling
149 self.k = dec.decode_symbol(m_bit)?;
150 // decode the exact location of the corrector within the interval
151 if COMPRESS_ONLY_K {
152 if self.k != 0 {
153 // then c is either smaller than 0 or bigger than 1
154 if self.k < 32 {
155 c = dec.read_bits(self.k)? as i32;
156 if c >= (1u32 << (self.k - 1)) as i32 {
157 // if c is in the interval [ 2^(k-1) ... + 2^k - 1 ]
158 // so we translate c back into the interval [ 2^(k-1) + 1 ... 2^k ] by adding 1
159 c += 1;
160 } else {
161 // otherwise c is in the interval [ 0 ... + 2^(k-1) - 1 ]
162 // so we translate c back into the interval [ - (2^k - 1) ... - (2^(k-1)) ] by subtracting (2^k - 1)
163 c -= ((1u32 << self.k) - 1) as i32;
164 }
165 } else {
166 c = self.corr_min;
167 }
168 } else {
169 c = dec.read_bit()? as i32;
170 }
171 }
172 // COMPRESS_ONLY_K
173 else {
174 if self.k != 0 {
175 // then c is either smaller than 0 or bigger than 1
176 if self.k < 32 {
177 if self.k <= self.bits_high {
178 // for small k we can do this in one step
179 // decompress c with the range coder
180 c = dec.decode_symbol(&mut self.m_corrector[(self.k - 1) as usize])?
181 as i32;
182 } else {
183 // for larger k we need to do this in two steps
184 let k1 = self.k - self.bits_high;
185 // decompress higher bits with table
186 c = dec.decode_symbol(&mut self.m_corrector[(self.k - 1) as usize])?
187 as i32;
188 let c1 = dec.read_bits(k1)?;
189 // put the corrector back together
190 c = (c << k1 as i32) | c1 as i32;
191 }
192
193 // translate c back into its correct interval
194 if c >= (1u32 << (self.k - 1)) as i32 {
195 // so we translate c back into the interval [ 2^(k-1) + 1 ... 2^k ] by adding 1
196 c += 1;
197 } else {
198 // otherwise c is in the interval [ 0 ... + 2^(k-1) - 1 ]
199 // so we translate c back into the interval [ - (2^k - 1) ... - (2^(k-1)) ] by subtracting (2^k - 1)
200 c -= ((1u32 << self.k) - 1) as i32;
201 }
202 } else {
203 c = self.corr_min;
204 }
205 } else {
206 c = dec.decode_bit(&mut self.m_corrector0)? as i32;
207 }
208 } // COMPRESS_ONLY_K
209 c
210 };
211 //--- read corrector ---//
212 let mut real = pred.wrapping_add(corr);
213 if real < 0 {
214 real += self.corr_range as i32;
215 } else if real >= self.corr_range as i32 {
216 real -= self.corr_range as i32
217 }
218 Ok(real)
219 }
220}
221
222pub struct IntegerDecompressorBuilder {
223 bits: u32,
224 contexts: u32,
225 bits_high: u32,
226 range: u32,
227}
228
229impl IntegerDecompressorBuilder {
230 pub fn new() -> Self {
231 Self {
232 bits: DEFAULT_BITS,
233 contexts: DEFAULT_CONTEXTS,
234 bits_high: DEFAULT_BITS_HIGH,
235 range: DEFAULT_RANGE,
236 }
237 }
238 pub fn bits(&mut self, bits: u32) -> &mut Self {
239 self.bits = bits;
240 self
241 }
242
243 pub fn contexts(&mut self, contexts: u32) -> &mut Self {
244 self.contexts = contexts;
245 self
246 }
247
248 pub fn build(&self) -> IntegerDecompressor {
249 IntegerDecompressor::new(self.bits, self.contexts, self.bits_high, self.range)
250 }
251
252 pub fn build_initialized(&self) -> IntegerDecompressor {
253 let mut idc = self.build();
254 idc.init();
255 idc
256 }
257}