gistools/readers/las/laz/
v2.rs

1use super::{
2    ItemReader,
3    arithmetic_decoder::{ArithmeticDecoder, ArithmeticModel},
4    constants::{NUMBER_RETURN_LEVEL, NUMBER_RETURN_MAP},
5    integer_compressor::IntegerCompressor,
6};
7use crate::{
8    parsers::{RGBA, Reader},
9    readers::{
10        LASPoint,
11        util::{U64I64F64, ValueType64, u8_clamp, u8_fold, u32_zero_bit0},
12    },
13};
14use alloc::{rc::Rc, vec, vec::Vec};
15use core::cell::RefCell;
16
17const LASZIP_GPSTIME_MULTI: i32 = 500;
18const LASZIP_GPSTIME_MULTI_MINUS: i32 = -10;
19const LASZIP_GPSTIME_MULTI_UNCHANGED: i32 = LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 1;
20const LASZIP_GPSTIME_MULTI_CODE_FULL: i32 = LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 2;
21const LASZIP_GPSTIME_MULTI_TOTAL: i32 = LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 6;
22
23/// Streaming Median 5
24#[derive(Debug, Default, Clone, Copy, PartialEq)]
25pub struct StreamingMedian5 {
26    /// contains the last 5 values
27    pub values: [i32; 5],
28    /// true if the last value was the highest
29    pub high: bool,
30}
31impl StreamingMedian5 {
32    /// Creates a new StreamingMedian5
33    pub fn new() -> Self {
34        let mut sm5 = StreamingMedian5::default();
35        sm5.init();
36        sm5
37    }
38    /// Initializes the StreamingMedian5
39    pub fn init(&mut self) {
40        self.values = [0; 5];
41        self.high = true;
42    }
43
44    /// add a new value
45    ///
46    /// ## Parameters
47    /// - `v`: the new value to add
48    pub fn add(&mut self, v: i32) {
49        let Self { high, values } = self;
50        if *high {
51            if v < values[2] {
52                values[4] = values[3];
53                values[3] = values[2];
54                if v < values[0] {
55                    values[2] = values[1];
56                    values[1] = values[0];
57                    values[0] = v;
58                } else if v < values[1] {
59                    values[2] = values[1];
60                    values[1] = v;
61                } else {
62                    values[2] = v;
63                }
64            } else {
65                if v < values[3] {
66                    values[4] = values[3];
67                    values[3] = v;
68                } else {
69                    values[4] = v;
70                }
71                self.high = false;
72            }
73        } else if values[2] < v {
74            values[0] = values[1];
75            values[1] = values[2];
76            if values[4] < v {
77                values[2] = values[3];
78                values[3] = values[4];
79                values[4] = v;
80            } else if values[3] < v {
81                values[2] = values[3];
82                values[3] = v;
83            } else {
84                values[2] = v;
85            }
86        } else {
87            if values[1] < v {
88                values[0] = values[1];
89                values[1] = v;
90            } else {
91                values[0] = v;
92            }
93            self.high = true;
94        }
95    }
96
97    /// ## Returns
98    /// The median value
99    pub fn get(&self) -> i32 {
100        self.values[2]
101    }
102}
103
104/// LAZ Point10 2.0 Reader
105#[derive(Debug, Clone)]
106pub struct LAZPoint10v2Reader<T: Reader> {
107    /// The arithmetic decoder
108    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
109    /// The last point
110    last_item: LASPoint,
111    /// The last increment
112    /// TODO: Can we drop this
113    pub last_incr: i32,
114    ic_dx: IntegerCompressor<T>,
115    ic_dy: IntegerCompressor<T>,
116    ic_z: IntegerCompressor<T>,
117    ic_intensity: IntegerCompressor<T>,
118    last_intensity: [u16; 16],
119    last_x_diff_median5: [StreamingMedian5; 16],
120    last_y_diff_median5: [StreamingMedian5; 16],
121    last_height: [i32; 8],
122    ic_point_source_id: IntegerCompressor<T>,
123    m_changed_values: ArithmeticModel,
124    m_bit_byte: [Option<ArithmeticModel>; 256],
125    m_classification: [Option<ArithmeticModel>; 256],
126    m_user_data: [Option<ArithmeticModel>; 256],
127    m_scan_angle_rank: [ArithmeticModel; 2],
128}
129impl<T: Reader> LAZPoint10v2Reader<T> {
130    /// Create a new LAZPoint10v2Reader
131    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>) -> Self {
132        Self {
133            dec: dec.clone(),
134            last_item: LASPoint::default(),
135            last_incr: 0,
136            ic_dx: IntegerCompressor::new(dec.clone(), Some(32), Some(2), None, None),
137            ic_dy: IntegerCompressor::new(dec.clone(), Some(32), Some(22), None, None),
138            ic_z: IntegerCompressor::new(dec.clone(), Some(32), Some(20), None, None),
139            ic_intensity: IntegerCompressor::new(dec.clone(), Some(16), Some(4), None, None),
140            last_intensity: [0; 16],
141            last_x_diff_median5: [StreamingMedian5::new(); 16],
142            last_y_diff_median5: [StreamingMedian5::new(); 16],
143            last_height: [0; 8],
144            ic_point_source_id: IntegerCompressor::new(dec.clone(), Some(16), None, None, None),
145            m_changed_values: ArithmeticModel::new(64, false),
146            m_bit_byte: [const { None }; 256],
147            m_classification: [const { None }; 256],
148            m_user_data: [const { None }; 256],
149            m_scan_angle_rank: [ArithmeticModel::new(256, false), ArithmeticModel::new(256, false)],
150        }
151    }
152}
153impl<T: Reader> ItemReader for LAZPoint10v2Reader<T> {
154    fn init<R: Reader>(&mut self, item: &R, point: &mut LASPoint, _context: &mut u32) {
155        // init state
156        for i in 0..16 {
157            self.last_x_diff_median5[i].init();
158            self.last_y_diff_median5[i].init();
159            self.last_intensity[i] = 0;
160            self.last_height[i / 2] = 0;
161        }
162        // init models and integer compressors
163        self.m_changed_values.init(None);
164        self.ic_intensity.init_decompressor();
165        self.m_scan_angle_rank[0].init(None);
166        self.m_scan_angle_rank[1].init(None);
167        self.ic_point_source_id.init_decompressor();
168        for i in 0..256 {
169            if let Some(m) = &mut self.m_bit_byte[i] {
170                m.init(None);
171            }
172            if let Some(m) = &mut self.m_classification[i] {
173                m.init(None);
174            }
175            if let Some(m) = &mut self.m_user_data[i] {
176                m.init(None);
177            }
178        }
179        self.ic_dx.init_decompressor();
180        self.ic_dy.init_decompressor();
181        self.ic_z.init_decompressor();
182
183        // init last item
184        self.last_item.inject_point10(item, 0);
185        point.inject_point10(item, 0);
186        // but set intensity to zero
187        self.last_item.intensity = 0;
188    }
189
190    fn read(&mut self, item: &mut LASPoint, _context: &mut u32) {
191        let r: usize;
192        let n: usize;
193        let m: usize;
194        let l: usize;
195        let mut k_bits;
196        let mut median;
197        let mut diff;
198        // decompress which other values have changed
199        let changed_values = self.dec.borrow_mut().decode_symbol(&mut self.m_changed_values) as i32;
200        if changed_values != 0 {
201            // decompress the edge_of_flight_line, scan_direction_flag, ... if it has changed
202            if (changed_values & 32) != 0 {
203                if self.m_bit_byte[self.last_item.flags as usize].is_none() {
204                    let mut m = ArithmeticModel::new(256, false);
205                    m.init(None);
206                    self.m_bit_byte[self.last_item.flags as usize] = Some(m);
207                }
208                self.last_item.set_flags(
209                    self.dec.borrow_mut().decode_symbol(
210                        self.m_bit_byte[self.last_item.flags as usize].as_mut().unwrap(),
211                    ) as u8,
212                    false,
213                );
214            }
215            r = self.last_item.return_number as usize;
216            n = self.last_item.number_of_returns as usize;
217            m = NUMBER_RETURN_MAP[n][r] as usize;
218            l = NUMBER_RETURN_LEVEL[n][r] as usize;
219            // decompress the intensity if it has changed
220            if (changed_values & 16) != 0 {
221                self.last_item.intensity = self
222                    .ic_intensity
223                    .decompress(self.last_intensity[m] as i32, if m < 3 { m as u32 } else { 3 })
224                    as u16;
225                self.last_intensity[m] = self.last_item.intensity;
226            } else {
227                self.last_item.intensity = self.last_intensity[m];
228            }
229            // decompress the classification ... if it has changed
230            if (changed_values & 8) != 0 {
231                if self.m_classification[self.last_item.classification as usize].is_none() {
232                    let mut m = ArithmeticModel::new(256, false);
233                    m.init(None);
234                    self.m_classification[self.last_item.classification as usize] = Some(m);
235                }
236                self.last_item.set_flags2(self.dec.borrow_mut().decode_symbol(
237                    self.m_classification[self.last_item.classification as usize].as_mut().unwrap(),
238                ) as u8);
239            }
240            // decompress the scan_angle_rank ... if it has changed
241            if (changed_values & 4) != 0 {
242                let mut val = self.dec.borrow_mut().decode_symbol(
243                    &mut self.m_scan_angle_rank[self.last_item.scan_direction_flag as usize],
244                );
245                let sar = self.last_item.scan_angle_rank;
246                if sar < 0 {
247                    val = (val as i32 + sar as i32) as u32;
248                } else {
249                    val += sar as u32;
250                }
251                self.last_item.scan_angle_rank = u8_fold(val) as i8;
252            }
253            // decompress the user_data ... if it has changed
254            if (changed_values & 2) != 0 {
255                if self.m_user_data[self.last_item.user_data as usize].is_none() {
256                    let mut m = ArithmeticModel::new(256, false);
257                    m.init(None);
258                    self.m_user_data[self.last_item.user_data as usize] = Some(m);
259                }
260                self.last_item.user_data = self.dec.borrow_mut().decode_symbol(
261                    self.m_user_data[self.last_item.user_data as usize].as_mut().unwrap(),
262                ) as u8;
263            }
264            // decompress the point_source_id ... if it has changed
265            if (changed_values & 1) != 0 {
266                self.last_item.point_source_id =
267                    self.ic_point_source_id.decompress(self.last_item.point_source_id as i32, 0)
268                        as u16;
269            }
270        } else {
271            r = self.last_item.return_number as usize;
272            n = self.last_item.number_of_returns as usize;
273            m = NUMBER_RETURN_MAP[n][r] as usize;
274            l = NUMBER_RETURN_LEVEL[n][r] as usize;
275        }
276        // decompress x coordinate
277        median = self.last_x_diff_median5[m].get();
278        diff = self.ic_dx.decompress(median, if n == 1 { 1 } else { 0 });
279        self.last_item.x += diff;
280        self.last_x_diff_median5[m].add(diff);
281        // decompress y coordinate
282        median = self.last_y_diff_median5[m].get();
283        k_bits = self.ic_dx.get_k();
284        diff = self.ic_dy.decompress(
285            median,
286            (n == 1) as u32 + if k_bits < 20 { u32_zero_bit0(k_bits) } else { 20 },
287        );
288        self.last_item.y += diff;
289        self.last_y_diff_median5[m].add(diff);
290        // decompress z coordinate
291        k_bits = (self.ic_dx.get_k() + self.ic_dy.get_k()) / 2;
292        self.last_item.z = self.ic_z.decompress(
293            self.last_height[l],
294            (n == 1) as u32 + if k_bits < 18 { u32_zero_bit0(k_bits) } else { 18 },
295        );
296        self.last_height[l] = self.last_item.z;
297
298        // copy in the last point
299        *item = self.last_item.clone();
300    }
301
302    fn chunk_sizes<R: Reader>(&mut self, _reader: &R) {}
303}
304
305/// Parse LAZ GPS Time 1.1v2
306#[derive(Debug, Clone)]
307pub struct LAZGpsTime11v2Reader<T: Reader> {
308    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
309    m_gpstime_multi: ArithmeticModel,
310    m_gpstime0diff: ArithmeticModel,
311    ic_gpstime: IntegerCompressor<T>,
312    last: u32,
313    next: u32,
314    last_gpstime: [U64I64F64; 4],
315    last_gpstime_diff: [i32; 4],
316    multi_extreme_counter: [i32; 4],
317}
318impl<T: Reader> LAZGpsTime11v2Reader<T> {
319    /// Create a new LAZGpsTime11v2Reader
320    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>) -> Self {
321        LAZGpsTime11v2Reader {
322            dec: dec.clone(),
323            m_gpstime_multi: ArithmeticModel::new(LASZIP_GPSTIME_MULTI_TOTAL as u32, false),
324            m_gpstime0diff: ArithmeticModel::new(6, false),
325            ic_gpstime: IntegerCompressor::new(dec, Some(32), Some(9), None, None),
326            last: 0,
327            next: 0,
328            last_gpstime: [
329                U64I64F64::new(0_u64, ValueType64::U64),
330                U64I64F64::new(0_u64, ValueType64::U64),
331                U64I64F64::new(0_u64, ValueType64::U64),
332                U64I64F64::new(0_u64, ValueType64::U64),
333            ],
334            last_gpstime_diff: [0, 0, 0, 0],
335            multi_extreme_counter: [0, 0, 0, 0],
336        }
337    }
338}
339impl<T: Reader> ItemReader for LAZGpsTime11v2Reader<T> {
340    fn init<R: Reader>(&mut self, item: &R, point: &mut LASPoint, _context: &mut u32) {
341        // init state
342        self.last = 0;
343        self.next = 0;
344        self.last_gpstime_diff = [0, 0, 0, 0];
345        self.multi_extreme_counter = [0, 0, 0, 0];
346        // init models and integer compressors
347        self.m_gpstime_multi.init(None);
348        self.m_gpstime0diff.init(None);
349        self.ic_gpstime.init_decompressor();
350        // init last item
351        self.last_gpstime[0].set_u64(item.uint64_le(Some(0)));
352        self.last_gpstime[1].set_u64(0);
353        self.last_gpstime[2].set_u64(0);
354        self.last_gpstime[3].set_u64(0);
355
356        point.gps_time = Some(self.last_gpstime[0].f64());
357    }
358
359    fn read(&mut self, item: &mut LASPoint, _context: &mut u32) {
360        let mut multi: i32; // I32
361        if self.last_gpstime_diff[self.last as usize] == 0 {
362            // if the last integer difference was zero
363            multi = self.dec.borrow_mut().decode_symbol(&mut self.m_gpstime0diff) as i32;
364            if multi == 1 {
365                // the difference can be represented with 32 bits
366                self.last_gpstime_diff[self.last as usize] = self.ic_gpstime.decompress(0, 0);
367                self.last_gpstime[self.last as usize].set_i64(
368                    self.last_gpstime[self.last as usize].i64()
369                        + self.last_gpstime_diff[self.last as usize] as i64,
370                );
371                self.multi_extreme_counter[self.last as usize] = 0;
372            } else if multi == 2 {
373                // the difference is huge
374                self.next = (self.next + 1) & 3;
375                self.last_gpstime[self.next as usize].set_u64(
376                    self.ic_gpstime
377                        .decompress((self.last_gpstime[self.last as usize].u64() >> 32) as i32, 8)
378                        as u64,
379                );
380                self.last_gpstime[self.next as usize]
381                    .set_u64(self.last_gpstime[self.next as usize].u64() << 32);
382                self.last_gpstime[self.next as usize].set_u64(
383                    self.last_gpstime[self.next as usize].u64()
384                        | self.dec.borrow_mut().read_int() as u64,
385                );
386                self.last = self.next;
387                self.last_gpstime_diff[self.last as usize] = 0;
388                self.multi_extreme_counter[self.last as usize] = 0;
389            } else if multi > 2 {
390                // we switch to another sequence
391                self.last = ((self.last as i32 + multi - 2) & 3) as u32;
392                self.read(item, _context);
393            }
394        } else {
395            multi = self.dec.borrow_mut().decode_symbol(&mut self.m_gpstime_multi) as i32;
396            if multi == 1 {
397                self.last_gpstime[self.last as usize].set_i64(
398                    self.last_gpstime[self.last as usize].i64()
399                        + self.ic_gpstime.decompress(self.last_gpstime_diff[self.last as usize], 1)
400                            as i64,
401                );
402                self.multi_extreme_counter[self.last as usize] = 0;
403            } else if multi < LASZIP_GPSTIME_MULTI_UNCHANGED {
404                let gpstime_diff;
405                if multi == 0 {
406                    gpstime_diff = self.ic_gpstime.decompress(0, 7);
407                    self.multi_extreme_counter[self.last as usize] += 1;
408                    if self.multi_extreme_counter[self.last as usize] > 3 {
409                        self.last_gpstime_diff[self.last as usize] = gpstime_diff;
410                        self.multi_extreme_counter[self.last as usize] = 0;
411                    }
412                } else if multi < LASZIP_GPSTIME_MULTI {
413                    if multi < 10 {
414                        gpstime_diff = self
415                            .ic_gpstime
416                            .decompress(multi * self.last_gpstime_diff[self.last as usize], 2);
417                    } else {
418                        gpstime_diff = self
419                            .ic_gpstime
420                            .decompress(multi * self.last_gpstime_diff[self.last as usize], 3);
421                    }
422                } else if multi == LASZIP_GPSTIME_MULTI {
423                    gpstime_diff = self.ic_gpstime.decompress(
424                        LASZIP_GPSTIME_MULTI * self.last_gpstime_diff[self.last as usize],
425                        4,
426                    );
427                    self.multi_extreme_counter[self.last as usize] += 1;
428                    if self.multi_extreme_counter[self.last as usize] > 3 {
429                        self.last_gpstime_diff[self.last as usize] = gpstime_diff;
430                        self.multi_extreme_counter[self.last as usize] = 0;
431                    }
432                } else {
433                    multi = LASZIP_GPSTIME_MULTI - multi;
434                    if multi > LASZIP_GPSTIME_MULTI_MINUS {
435                        gpstime_diff = self
436                            .ic_gpstime
437                            .decompress(multi * self.last_gpstime_diff[self.last as usize], 5);
438                    } else {
439                        gpstime_diff = self.ic_gpstime.decompress(
440                            LASZIP_GPSTIME_MULTI_MINUS * self.last_gpstime_diff[self.last as usize],
441                            6,
442                        );
443                        self.multi_extreme_counter[self.last as usize] += 1;
444                        if self.multi_extreme_counter[self.last as usize] > 3 {
445                            self.last_gpstime_diff[self.last as usize] = gpstime_diff;
446                            self.multi_extreme_counter[self.last as usize] = 0;
447                        }
448                    }
449                }
450                self.last_gpstime[self.last as usize]
451                    .set_i64(self.last_gpstime[self.last as usize].i64() + gpstime_diff as i64);
452            } else if multi == LASZIP_GPSTIME_MULTI_CODE_FULL {
453                self.next = (self.next + 1) & 3;
454                self.last_gpstime[self.next as usize].set_u64(
455                    self.ic_gpstime
456                        .decompress((self.last_gpstime[self.last as usize].u64() >> 32) as i32, 8)
457                        as u64,
458                );
459                self.last_gpstime[self.next as usize]
460                    .set_u64(self.last_gpstime[self.next as usize].u64() << 32);
461                self.last_gpstime[self.next as usize].set_u64(
462                    self.last_gpstime[self.next as usize].u64()
463                        | self.dec.borrow_mut().read_int() as u64,
464                );
465                self.last = self.next;
466                self.last_gpstime_diff[self.last as usize] = 0;
467                self.multi_extreme_counter[self.last as usize] = 0;
468            } else if multi >= LASZIP_GPSTIME_MULTI_CODE_FULL {
469                self.last =
470                    ((self.last as i32 + multi - LASZIP_GPSTIME_MULTI_CODE_FULL) & 3) as u32;
471                self.read(item, _context);
472            }
473        }
474
475        item.gps_time = Some(self.last_gpstime[self.last as usize].f64());
476    }
477
478    fn chunk_sizes<R: Reader>(&mut self, _reader: &R) {}
479}
480
481/// Parse LAZ RGB 1.2v2
482#[derive(Debug, Clone)]
483pub struct LAZrgb12v2Reader<T: Reader> {
484    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
485    last_item: [u16; 3],
486    m_byte_used: ArithmeticModel,
487    m_rgb_diff0: ArithmeticModel,
488    m_rgb_diff1: ArithmeticModel,
489    m_rgb_diff2: ArithmeticModel,
490    m_rgb_diff3: ArithmeticModel,
491    m_rgb_diff4: ArithmeticModel,
492    m_rgb_diff5: ArithmeticModel,
493}
494impl<T: Reader> LAZrgb12v2Reader<T> {
495    /// Create a new LAZrgb12v2Reader
496    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>) -> Self {
497        Self {
498            dec,
499            last_item: [0; 3],
500            m_byte_used: ArithmeticModel::new(128, false),
501            m_rgb_diff0: ArithmeticModel::new(256, false),
502            m_rgb_diff1: ArithmeticModel::new(256, false),
503            m_rgb_diff2: ArithmeticModel::new(256, false),
504            m_rgb_diff3: ArithmeticModel::new(256, false),
505            m_rgb_diff4: ArithmeticModel::new(256, false),
506            m_rgb_diff5: ArithmeticModel::new(256, false),
507        }
508    }
509}
510impl<T: Reader> ItemReader for LAZrgb12v2Reader<T> {
511    fn init<R: Reader>(&mut self, item: &R, point: &mut LASPoint, _context: &mut u32) {
512        // init models and integer compressors
513        self.m_byte_used.init(None);
514        self.m_rgb_diff0.init(None);
515        self.m_rgb_diff1.init(None);
516        self.m_rgb_diff2.init(None);
517        self.m_rgb_diff3.init(None);
518        self.m_rgb_diff4.init(None);
519        self.m_rgb_diff5.init(None);
520        // init last item
521        let r = item.uint16_le(None);
522        let g = item.uint16_le(None);
523        let b = item.uint16_le(None);
524        self.last_item = [r, g, b];
525        point.rgba = Some(RGBA::from_u16s(r, g, b, u16::MAX));
526    }
527
528    fn read(&mut self, item: &mut LASPoint, _context: &mut u32) {
529        let dec = &mut self.dec.borrow_mut();
530        let mut curr_item = self.last_item;
531
532        let mut corr: u8;
533        let mut diff: i32;
534        let sym = dec.decode_symbol(&mut self.m_byte_used);
535        if (sym & 1) != 0 {
536            corr = dec.decode_symbol(&mut self.m_rgb_diff0) as u8;
537            curr_item[0] = u8_fold(corr as u32 + (self.last_item[0] & 255) as u32) as u16;
538        } else {
539            curr_item[0] = self.last_item[0] & 0xff;
540        }
541        if (sym & (1 << 1)) != 0 {
542            corr = dec.decode_symbol(&mut self.m_rgb_diff1) as u8;
543            curr_item[0] |= (u8_fold(corr as u32 + (self.last_item[0] >> 8) as u32) as u16) << 8;
544        } else {
545            curr_item[0] |= self.last_item[0] & 0xff00;
546        }
547        if (sym & (1 << 6)) != 0 {
548            diff = (curr_item[0] & 0x00ff) as i32 - (self.last_item[0] & 0x00ff) as i32;
549            if (sym & (1 << 2)) != 0 {
550                corr = dec.decode_symbol(&mut self.m_rgb_diff2) as u8;
551                curr_item[1] = u8_fold(
552                    corr as u32 + u8_clamp((diff + (self.last_item[1] & 255) as i32) as u32) as u32,
553                ) as u16;
554            } else {
555                curr_item[1] = self.last_item[1] & 0xff;
556            }
557            if (sym & (1 << 4)) != 0 {
558                corr = dec.decode_symbol(&mut self.m_rgb_diff4) as u8;
559                diff = (diff
560                    + ((curr_item[1] & 0x00ff) as i32 - (self.last_item[1] & 0x00ff) as i32))
561                    / 2;
562                curr_item[2] = u8_fold(
563                    corr as u32 + u8_clamp((diff + (self.last_item[2] & 255) as i32) as u32) as u32,
564                ) as u16;
565            } else {
566                curr_item[2] = self.last_item[2] & 0xff;
567            }
568            diff = (curr_item[0] >> 8) as i32 - (self.last_item[0] >> 8) as i32;
569            if (sym & (1 << 3)) != 0 {
570                corr = dec.decode_symbol(&mut self.m_rgb_diff3) as u8;
571                curr_item[1] |= (u8_fold(
572                    corr as u32 + u8_clamp((diff + (self.last_item[1] >> 8) as i32) as u32) as u32,
573                ) as u16)
574                    << 8;
575            } else {
576                curr_item[1] |= self.last_item[1] & 0xff00;
577            }
578            if (sym & (1 << 5)) != 0 {
579                corr = dec.decode_symbol(&mut self.m_rgb_diff5) as u8;
580                diff = (diff + ((curr_item[1] >> 8) as i32 - (self.last_item[1] >> 8) as i32)) / 2;
581                curr_item[2] |= (u8_fold(
582                    corr as u32 + u8_clamp((diff + (self.last_item[2] >> 8) as i32) as u32) as u32,
583                ) as u16)
584                    << 8;
585            } else {
586                curr_item[2] |= self.last_item[2] & 0xff00;
587            }
588        } else {
589            curr_item[1] = curr_item[0];
590            curr_item[2] = curr_item[0];
591        }
592
593        self.last_item = curr_item;
594        item.rgba = Some(RGBA::from_u16s(curr_item[0], curr_item[1], curr_item[2], u16::MAX));
595    }
596
597    fn chunk_sizes<R: Reader>(&mut self, _reader: &R) {}
598}
599
600/// LAZ byte reader V2
601#[derive(Debug, Clone)]
602pub struct LAZbyte10v2Reader<T: Reader> {
603    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
604    size: u32,
605    m_byte: Vec<ArithmeticModel>,
606    last_item: Vec<u8>,
607}
608impl<T: Reader> LAZbyte10v2Reader<T> {
609    /// Create a new LAZbyte10v2Reader
610    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>, size: u32) -> Self {
611        Self {
612            size,
613            last_item: vec![0; size as usize],
614            m_byte: vec![ArithmeticModel::new(256, false); size as usize],
615            dec,
616        }
617    }
618}
619impl<T: Reader> ItemReader for LAZbyte10v2Reader<T> {
620    fn init<R: Reader>(&mut self, item: &R, _point: &mut LASPoint, _context: &mut u32) {
621        // init models and integer compressors
622        for m in self.m_byte.iter_mut() {
623            m.init(None);
624        }
625        // init last item
626        self.last_item = item.seek_slice(self.size as usize);
627    }
628
629    fn read(&mut self, _item: &mut LASPoint, _context: &mut u32) {
630        let mut res = vec![];
631        for i in 0..self.size as usize {
632            let value =
633                self.last_item[i] as u32 + self.dec.borrow_mut().decode_symbol(&mut self.m_byte[i]);
634            res.push(u8_fold(value));
635        }
636        self.last_item = res;
637    }
638
639    fn chunk_sizes<R: Reader>(&mut self, _reader: &R) {}
640}