Skip to main content

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}