gistools/readers/las/laz/
v3.rs

1use super::{
2    ItemReader,
3    arithmetic_decoder::{ArithmeticDecoder, ArithmeticModel},
4    constants::{
5        LASZIP_DECOMPRESS_SELECTIVE_ALL, LASZIP_DECOMPRESS_SELECTIVE_BYTE0,
6        LASZIP_DECOMPRESS_SELECTIVE_CLASSIFICATION, LASZIP_DECOMPRESS_SELECTIVE_FLAGS,
7        LASZIP_DECOMPRESS_SELECTIVE_GPS_TIME, LASZIP_DECOMPRESS_SELECTIVE_INTENSITY,
8        LASZIP_DECOMPRESS_SELECTIVE_NIR, LASZIP_DECOMPRESS_SELECTIVE_POINT_SOURCE,
9        LASZIP_DECOMPRESS_SELECTIVE_RGB, LASZIP_DECOMPRESS_SELECTIVE_SCAN_ANGLE,
10        LASZIP_DECOMPRESS_SELECTIVE_USER_DATA, LASZIP_DECOMPRESS_SELECTIVE_WAVEPACKET,
11        LASZIP_DECOMPRESS_SELECTIVE_Z,
12    },
13    integer_compressor::IntegerCompressor,
14    v2::StreamingMedian5,
15};
16use crate::{
17    parsers::{Buffer, BufferReader, RGBA, Reader},
18    readers::{
19        LASPoint, WavePacket,
20        laz::constants::{NUMBER_RETURN_LEVEL_8CTX, NUMBER_RETURN_MAP_6CTX},
21        util::{U64I64F64, ValueType64, i8_clamp, i16_quantize, u8_clamp, u8_fold, u32_zero_bit0},
22    },
23};
24use alloc::{rc::Rc, vec, vec::Vec};
25use core::cell::RefCell;
26
27const LASZIP_GPSTIME_MULTI: i32 = 500;
28const LASZIP_GPSTIME_MULTI_MINUS: i32 = -10;
29const LASZIP_GPSTIME_MULTI_CODE_FULL: i32 = LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 1;
30const LASZIP_GPSTIME_MULTI_TOTAL: i32 = LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 5;
31
32/// LAS Point 1.4 context
33#[derive(Debug, Clone)]
34pub struct LASContextPoint14 {
35    /// contexts last point
36    pub last_item: LASPoint,
37    /// If the context is unused
38    pub unused: bool,
39    /// last intensity
40    pub last_intensity: [u16; 8],
41    /// last x diff median5
42    pub last_x_diff_median5: [StreamingMedian5; 12],
43    /// last y diff median5
44    pub last_y_diff_median5: [StreamingMedian5; 12],
45    /// last height
46    pub last_z: [i32; 8],
47    /// last height diff median5
48    pub m_changed_values: [Option<ArithmeticModel>; 8],
49    /// last height diff median5
50    pub m_scanner_channel: Option<ArithmeticModel>,
51    /// last height diff median5
52    pub m_number_of_returns: [Option<ArithmeticModel>; 16],
53    /// last height diff median5
54    pub m_return_number_gps_same: Option<ArithmeticModel>,
55    /// last height diff median5
56    pub m_return_number: [Option<ArithmeticModel>; 16],
57    /// last height diff median5
58    pub ic_dx: Option<IntegerCompressor<BufferReader>>,
59    /// last height diff median5
60    pub ic_dy: Option<IntegerCompressor<BufferReader>>,
61    /// last height diff median5
62    pub ic_z: Option<IntegerCompressor<BufferReader>>,
63    /// arithmetic model classification
64    pub m_classification: [Option<ArithmeticModel>; 64],
65    /// arithmetic model flags
66    pub m_flags: [Option<ArithmeticModel>; 64],
67    /// arithmetic model user data
68    pub m_user_data: [Option<ArithmeticModel>; 64],
69    /// integer compression intensity
70    pub ic_intensity: Option<IntegerCompressor<BufferReader>>,
71    /// integer compression scan angle
72    pub ic_scan_angle: Option<IntegerCompressor<BufferReader>>,
73    /// integer compression source id
74    pub ic_point_source_id: Option<IntegerCompressor<BufferReader>>,
75    // GPS time stuff
76    /// last gps value
77    pub last: u32,
78    /// next gps value
79    pub next: u32,
80    /// last gps time
81    pub last_gpstime: [U64I64F64; 4],
82    /// last gps time difference
83    pub last_gpstime_diff: [i32; 4],
84    /// multi extreme counter
85    pub multi_extreme_counter: [i32; 4],
86    /// gps time arithmetic model
87    pub m_gpstime_multi: Option<ArithmeticModel>,
88    /// gps time arithmetic model
89    pub m_gpstime0diff: Option<ArithmeticModel>,
90    /// gps time arithmetic model
91    pub ic_gpstime: Option<IntegerCompressor<BufferReader>>,
92}
93impl Default for LASContextPoint14 {
94    /// Create a new LASContextPoint14
95    fn default() -> Self {
96        Self {
97            unused: false,
98            last_item: LASPoint::default(),
99            last_intensity: [0; 8],
100            last_x_diff_median5: [StreamingMedian5::new(); 12],
101            last_y_diff_median5: [StreamingMedian5::new(); 12],
102            last_z: [0; 8],
103            m_changed_values: [const { None }; 8],
104            m_scanner_channel: None,
105            m_number_of_returns: [const { None }; 16],
106            m_return_number_gps_same: None,
107            m_return_number: [const { None }; 16],
108            ic_dx: None,
109            ic_dy: None,
110            ic_z: None,
111            m_classification: [const { None }; 64],
112            m_flags: [const { None }; 64],
113            m_user_data: [const { None }; 64],
114            ic_intensity: None,
115            ic_scan_angle: None,
116            ic_point_source_id: None,
117            last: 0,
118            next: 0,
119            last_gpstime: [
120                U64I64F64::new(0_u64, ValueType64::U64),
121                U64I64F64::new(0_u64, ValueType64::U64),
122                U64I64F64::new(0_u64, ValueType64::U64),
123                U64I64F64::new(0_u64, ValueType64::U64),
124            ],
125            last_gpstime_diff: [0; 4],
126            multi_extreme_counter: [0; 4],
127            m_gpstime_multi: None,
128            m_gpstime0diff: None,
129            ic_gpstime: None,
130        }
131    }
132}
133
134/// LAS RGB 1.4 context
135#[derive(Debug, Default, Clone)]
136pub struct LAZContextRGB14 {
137    /// true if unused
138    pub unused: bool,
139    /// last item data
140    pub last_item: [u16; 3],
141    // models
142    /// bytes used
143    pub m_byte_used: Option<ArithmeticModel>,
144    /// RGB diff 0
145    pub m_rgb_diff0: Option<ArithmeticModel>,
146    /// RGB diff 1
147    pub m_rgb_diff1: Option<ArithmeticModel>,
148    /// RGB diff 2
149    pub m_rgb_diff2: Option<ArithmeticModel>,
150    /// RGB diff 3
151    pub m_rgb_diff3: Option<ArithmeticModel>,
152    /// RGB diff 4
153    pub m_rgb_diff4: Option<ArithmeticModel>,
154    /// RGB diff 5
155    pub m_rgb_diff5: Option<ArithmeticModel>,
156}
157
158/// LAS RGB & NIR 1.4 context
159#[derive(Debug, Default, Clone)]
160pub struct LASContextRGBNir14 {
161    /// true if unused
162    pub unused: bool,
163    /// last item data
164    pub last_item: [u16; 4],
165    // models
166    /// bytes used
167    pub m_rgb_bytes_used: Option<ArithmeticModel>,
168    /// RGB diff 0
169    pub m_rgb_diff0: Option<ArithmeticModel>,
170    /// RGB diff 1
171    pub m_rgb_diff1: Option<ArithmeticModel>,
172    /// RGB diff 2
173    pub m_rgb_diff2: Option<ArithmeticModel>,
174    /// RGB diff 3
175    pub m_rgb_diff3: Option<ArithmeticModel>,
176    /// RGB diff 4
177    pub m_rgb_diff4: Option<ArithmeticModel>,
178    /// RGB diff 5
179    pub m_rgb_diff5: Option<ArithmeticModel>,
180    /// NIR bytes used
181    pub m_nir_bytes_used: Option<ArithmeticModel>,
182    /// NIR diff 0
183    pub m_nir_diff0: Option<ArithmeticModel>,
184    /// NIR diff 1
185    pub m_nir_diff1: Option<ArithmeticModel>,
186}
187
188/// LAS WAVEPACKET 1.4 context
189#[derive(Debug, Default, Clone)]
190pub struct LASContextWavePacket14<T: Reader> {
191    /// true if unused
192    pub unused: bool,
193    /// last item data
194    pub last_item: [u8; 29],
195    /// last difference
196    pub last_diff32: i32,
197    /// last offset difference
198    pub sym_last_offset_diff: u32,
199    // models
200    /// packet index model
201    pub m_packet_index: Option<ArithmeticModel>,
202    /// offset diff models
203    pub m_offset_diff: [Option<ArithmeticModel>; 4],
204    /// packet size model
205    pub ic_offset_diff: Option<IntegerCompressor<T>>,
206    /// packet size integer compressor
207    pub ic_packet_size: Option<IntegerCompressor<T>>,
208    /// return point integer compressor
209    pub ic_return_point: Option<IntegerCompressor<T>>,
210    /// xyz integer compressor
211    pub ic_xyz: Option<IntegerCompressor<T>>,
212}
213
214/// LAS BYTE 1.4 context
215#[derive(Debug, Default, Clone)]
216pub struct LAZContextByte14 {
217    /// true if unused
218    pub unused: bool,
219    /// last item data
220    pub last_item: Buffer,
221    /// bytes model
222    pub m_bytes: Vec<ArithmeticModel>,
223}
224
225/// Parse LAZ Point 1.4v3
226#[derive(Debug, Clone)]
227pub struct LAZPoint14v3Reader<T: Reader> {
228    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
229    // streams
230    instream_channel_returns_xy: Option<Rc<RefCell<BufferReader>>>,
231    instream_z: Option<Rc<RefCell<BufferReader>>>,
232    instream_classification: Option<Rc<RefCell<BufferReader>>>,
233    instream_flags: Option<Rc<RefCell<BufferReader>>>,
234    instream_intensity: Option<Rc<RefCell<BufferReader>>>,
235    instream_scan_angle: Option<Rc<RefCell<BufferReader>>>,
236    instream_user_data: Option<Rc<RefCell<BufferReader>>>,
237    instream_point_source: Option<Rc<RefCell<BufferReader>>>,
238    instream_gps_time: Option<Rc<RefCell<BufferReader>>>,
239    // decoders
240    dec_channel_returns_xy: Rc<RefCell<ArithmeticDecoder<BufferReader>>>,
241    dec_z: Rc<RefCell<ArithmeticDecoder<BufferReader>>>,
242    dec_classification: Rc<RefCell<ArithmeticDecoder<BufferReader>>>,
243    dec_flags: Rc<RefCell<ArithmeticDecoder<BufferReader>>>,
244    dec_intensity: Rc<RefCell<ArithmeticDecoder<BufferReader>>>,
245    dec_scan_angle: Rc<RefCell<ArithmeticDecoder<BufferReader>>>,
246    dec_user_data: Rc<RefCell<ArithmeticDecoder<BufferReader>>>,
247    dec_point_source: Rc<RefCell<ArithmeticDecoder<BufferReader>>>,
248    dec_gps_time: Rc<RefCell<ArithmeticDecoder<BufferReader>>>,
249    // Point structure
250    requested_z: bool,
251    requested_classification: bool,
252    requested_flags: bool,
253    requested_intensity: bool,
254    requested_scan_angle: bool,
255    requested_user_data: bool,
256    requested_point_source: bool,
257    requested_gps_time: bool,
258    // zero num_bytes and init booleans
259    num_bytes_channel_returns_xy: u32,
260    num_bytes_z: u32,
261    num_bytes_classification: u32,
262    num_bytes_flags: u32,
263    num_bytes_intensity: u32,
264    num_bytes_scan_angle: u32,
265    num_bytes_user_data: u32,
266    num_bytes_point_source: u32,
267    num_bytes_gps_time: u32,
268    changed_z: bool,
269    changed_classification: bool,
270    changed_flags: bool,
271    changed_intensity: bool,
272    changed_scan_angle: bool,
273    changed_user_data: bool,
274    changed_point_source: bool,
275    changed_gps_time: bool,
276    bytes: Option<Buffer>,
277    num_bytes_allocated: u32,
278    current_context: u32,
279    contexts: [LASContextPoint14; 4],
280}
281impl<T: Reader> LAZPoint14v3Reader<T> {
282    /// Create a new LAZPoint14v3Reader
283    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>, decompress_selective: Option<u32>) -> Self {
284        let decompress_selective = decompress_selective.unwrap_or(LASZIP_DECOMPRESS_SELECTIVE_ALL);
285
286        let tmp_decoders = Rc::new(RefCell::new(ArithmeticDecoder::new(Rc::new(RefCell::new(
287            BufferReader::new(vec![0_u8; 0]),
288        )))));
289        let mut point_read = LAZPoint14v3Reader {
290            dec,
291            // streams
292            instream_channel_returns_xy: None,
293            instream_z: None,
294            instream_classification: None,
295            instream_flags: None,
296            instream_intensity: None,
297            instream_scan_angle: None,
298            instream_user_data: None,
299            instream_point_source: None,
300            instream_gps_time: None,
301            // decoders
302            dec_channel_returns_xy: tmp_decoders.clone(),
303            dec_z: tmp_decoders.clone(),
304            dec_classification: tmp_decoders.clone(),
305            dec_flags: tmp_decoders.clone(),
306            dec_intensity: tmp_decoders.clone(),
307            dec_scan_angle: tmp_decoders.clone(),
308            dec_user_data: tmp_decoders.clone(),
309            dec_point_source: tmp_decoders.clone(),
310            dec_gps_time: tmp_decoders.clone(),
311            // Point structure
312            requested_z: false,
313            requested_classification: false,
314            requested_flags: false,
315            requested_intensity: false,
316            requested_scan_angle: false,
317            requested_user_data: false,
318            requested_point_source: false,
319            requested_gps_time: false,
320            // zero num_bytes and init booleans
321            num_bytes_channel_returns_xy: 0,
322            num_bytes_z: 0,
323            num_bytes_classification: 0,
324            num_bytes_flags: 0,
325            num_bytes_intensity: 0,
326            num_bytes_scan_angle: 0,
327            num_bytes_user_data: 0,
328            num_bytes_point_source: 0,
329            num_bytes_gps_time: 0,
330            changed_z: false,
331            changed_classification: false,
332            changed_flags: false,
333            changed_intensity: false,
334            changed_scan_angle: false,
335            changed_user_data: false,
336            changed_point_source: false,
337            changed_gps_time: false,
338            bytes: None,
339            num_bytes_allocated: 0,
340            current_context: 0,
341            contexts: [
342                LASContextPoint14::default(),
343                LASContextPoint14::default(),
344                LASContextPoint14::default(),
345                LASContextPoint14::default(),
346            ],
347        };
348
349        // mark the four scanner channel contexts as uninitialized
350        for context in &mut point_read.contexts {
351            context.m_changed_values[0] = None;
352        }
353
354        point_read.requested_z = (decompress_selective & LASZIP_DECOMPRESS_SELECTIVE_Z) != 0;
355        point_read.requested_classification =
356            (decompress_selective & LASZIP_DECOMPRESS_SELECTIVE_CLASSIFICATION) != 0;
357        point_read.requested_flags =
358            (decompress_selective & LASZIP_DECOMPRESS_SELECTIVE_FLAGS) != 0;
359        point_read.requested_intensity =
360            (decompress_selective & LASZIP_DECOMPRESS_SELECTIVE_INTENSITY) != 0;
361        point_read.requested_scan_angle =
362            (decompress_selective & LASZIP_DECOMPRESS_SELECTIVE_SCAN_ANGLE) != 0;
363        point_read.requested_user_data =
364            (decompress_selective & LASZIP_DECOMPRESS_SELECTIVE_USER_DATA) != 0;
365        point_read.requested_point_source =
366            (decompress_selective & LASZIP_DECOMPRESS_SELECTIVE_POINT_SOURCE) != 0;
367        point_read.requested_gps_time =
368            (decompress_selective & LASZIP_DECOMPRESS_SELECTIVE_GPS_TIME) != 0;
369
370        point_read
371    }
372
373    /// Read the GPS Time
374    fn read_gps_time(&mut self) {
375        let Self { contexts, current_context, .. } = self;
376        let current_context = *current_context as usize;
377        let mut multi: i32;
378        if contexts[current_context].last_gpstime_diff[contexts[current_context].last as usize] == 0
379        {
380            // if the last integer difference was zero
381            multi = self
382                .dec_gps_time
383                .borrow_mut()
384                .decode_symbol(contexts[current_context].m_gpstime0diff.as_mut().unwrap())
385                as i32;
386            if multi == 0 {
387                // the difference can be represented with 32 bits
388                contexts[current_context].last_gpstime_diff
389                    [contexts[current_context].last as usize] =
390                    contexts[current_context].ic_gpstime.as_mut().unwrap().decompress(0, 0);
391                contexts[current_context].last_gpstime[contexts[current_context].last as usize]
392                    .set_i64(
393                        contexts[current_context].last_gpstime
394                            [contexts[current_context].last as usize]
395                            .i64()
396                            + contexts[current_context].last_gpstime_diff
397                                [contexts[current_context].last as usize]
398                                as i64,
399                    );
400                contexts[current_context].multi_extreme_counter
401                    [contexts[current_context].last as usize] = 0;
402            } else if multi == 1 {
403                // the difference is huge
404                contexts[current_context].next = (contexts[current_context].next + 1) & 3;
405                contexts[current_context].last_gpstime[contexts[current_context].next as usize]
406                    .set_u64(
407                        contexts[current_context].ic_gpstime.as_mut().unwrap().decompress(
408                            (contexts[current_context].last_gpstime
409                                [contexts[current_context].last as usize]
410                                .u64()
411                                >> 32) as i32,
412                            8,
413                        ) as u64,
414                    );
415                contexts[current_context].last_gpstime[contexts[current_context].next as usize]
416                    .set_u64(
417                        contexts[current_context].last_gpstime
418                            [contexts[current_context].next as usize]
419                            .u64()
420                            << 32,
421                    );
422                let input_int = self.dec_gps_time.borrow_mut().read_int();
423                contexts[current_context].last_gpstime[contexts[current_context].next as usize]
424                    .set_u64(
425                        contexts[current_context].last_gpstime
426                            [contexts[current_context].next as usize]
427                            .u64()
428                            | input_int as u64,
429                    );
430                contexts[current_context].last = contexts[current_context].next;
431                contexts[current_context].last_gpstime_diff
432                    [contexts[current_context].last as usize] = 0;
433                contexts[current_context].multi_extreme_counter
434                    [contexts[current_context].last as usize] = 0;
435            }
436            // we switch to another sequence
437            else {
438                contexts[current_context].last =
439                    ((contexts[current_context].last as i32 + multi - 1) & 3) as u32;
440                self.read_gps_time();
441            }
442        } else {
443            multi = self
444                .dec_gps_time
445                .borrow_mut()
446                .decode_symbol(contexts[current_context].m_gpstime_multi.as_mut().unwrap())
447                as i32;
448            if multi == 1 {
449                contexts[current_context].last_gpstime[contexts[current_context].last as usize]
450                    .set_i64(
451                        contexts[current_context].last_gpstime
452                            [contexts[current_context].last as usize]
453                            .i64()
454                            + contexts[current_context].ic_gpstime.as_mut().unwrap().decompress(
455                                contexts[current_context].last_gpstime_diff
456                                    [contexts[current_context].last as usize],
457                                1,
458                            ) as i64,
459                    );
460                contexts[current_context].multi_extreme_counter
461                    [contexts[current_context].last as usize] = 0;
462            } else if multi < LASZIP_GPSTIME_MULTI_CODE_FULL {
463                let gpstime_diff: i32; // I32
464                if multi == 0 {
465                    gpstime_diff =
466                        contexts[current_context].ic_gpstime.as_mut().unwrap().decompress(0, 7);
467                    contexts[current_context].multi_extreme_counter
468                        [contexts[current_context].last as usize] += 1;
469                    if contexts[current_context].multi_extreme_counter
470                        [contexts[current_context].last as usize]
471                        > 3
472                    {
473                        contexts[current_context].last_gpstime_diff
474                            [contexts[current_context].last as usize] = gpstime_diff;
475                        contexts[current_context].multi_extreme_counter
476                            [contexts[current_context].last as usize] = 0;
477                    }
478                } else if multi < LASZIP_GPSTIME_MULTI {
479                    if multi < 10 {
480                        gpstime_diff =
481                            contexts[current_context].ic_gpstime.as_mut().unwrap().decompress(
482                                multi
483                                    * contexts[current_context].last_gpstime_diff
484                                        [contexts[current_context].last as usize],
485                                2,
486                            );
487                    } else {
488                        gpstime_diff =
489                            contexts[current_context].ic_gpstime.as_mut().unwrap().decompress(
490                                multi
491                                    * contexts[current_context].last_gpstime_diff
492                                        [contexts[current_context].last as usize],
493                                3,
494                            );
495                    }
496                } else if multi == LASZIP_GPSTIME_MULTI {
497                    gpstime_diff =
498                        contexts[current_context].ic_gpstime.as_mut().unwrap().decompress(
499                            LASZIP_GPSTIME_MULTI
500                                * contexts[current_context].last_gpstime_diff
501                                    [contexts[current_context].last as usize],
502                            4,
503                        );
504                    contexts[current_context].multi_extreme_counter
505                        [contexts[current_context].last as usize] += 1;
506                    if contexts[current_context].multi_extreme_counter
507                        [contexts[current_context].last as usize]
508                        > 3
509                    {
510                        contexts[current_context].last_gpstime_diff
511                            [contexts[current_context].last as usize] = gpstime_diff;
512                        contexts[current_context].multi_extreme_counter
513                            [contexts[current_context].last as usize] = 0;
514                    }
515                } else {
516                    multi = LASZIP_GPSTIME_MULTI - multi;
517                    if multi > LASZIP_GPSTIME_MULTI_MINUS {
518                        gpstime_diff =
519                            contexts[current_context].ic_gpstime.as_mut().unwrap().decompress(
520                                multi
521                                    * contexts[current_context].last_gpstime_diff
522                                        [contexts[current_context].last as usize],
523                                5,
524                            );
525                    } else {
526                        gpstime_diff =
527                            contexts[current_context].ic_gpstime.as_mut().unwrap().decompress(
528                                LASZIP_GPSTIME_MULTI_MINUS
529                                    * contexts[current_context].last_gpstime_diff
530                                        [contexts[current_context].last as usize],
531                                6,
532                            );
533                        contexts[current_context].multi_extreme_counter
534                            [contexts[current_context].last as usize] += 1;
535                        if contexts[current_context].multi_extreme_counter
536                            [contexts[current_context].last as usize]
537                            > 3
538                        {
539                            contexts[current_context].last_gpstime_diff
540                                [contexts[current_context].last as usize] = gpstime_diff;
541                            contexts[current_context].multi_extreme_counter
542                                [contexts[current_context].last as usize] = 0;
543                        }
544                    }
545                }
546                contexts[current_context].last_gpstime[contexts[current_context].last as usize]
547                    .set_i64(
548                        contexts[current_context].last_gpstime
549                            [contexts[current_context].last as usize]
550                            .i64()
551                            + gpstime_diff as i64,
552                    );
553            } else if multi == LASZIP_GPSTIME_MULTI_CODE_FULL {
554                contexts[current_context].next = (contexts[current_context].next + 1) & 3;
555                contexts[current_context].last_gpstime[contexts[current_context].next as usize]
556                    .set_u64(
557                        contexts[current_context].ic_gpstime.as_mut().unwrap().decompress(
558                            (contexts[current_context].last_gpstime
559                                [contexts[current_context].last as usize]
560                                .u64()
561                                >> 32) as i32,
562                            8,
563                        ) as u64,
564                    );
565                contexts[current_context].last_gpstime[contexts[current_context].next as usize]
566                    .set_u64(
567                        contexts[current_context].last_gpstime
568                            [contexts[current_context].next as usize]
569                            .u64()
570                            << 32,
571                    );
572                contexts[current_context].last_gpstime[contexts[current_context].next as usize]
573                    .set_u64(
574                        contexts[current_context].last_gpstime
575                            [contexts[current_context].next as usize]
576                            .u64()
577                            | (self.dec_gps_time.borrow_mut().read_int()) as u64,
578                    );
579                contexts[current_context].last = contexts[current_context].next;
580                contexts[current_context].last_gpstime_diff
581                    [contexts[current_context].last as usize] = 0;
582                contexts[current_context].multi_extreme_counter
583                    [contexts[current_context].last as usize] = 0;
584            } else if multi >= LASZIP_GPSTIME_MULTI_CODE_FULL {
585                contexts[current_context].last = ((contexts[current_context].last as i32 + multi
586                    - LASZIP_GPSTIME_MULTI_CODE_FULL)
587                    & 3) as u32;
588                self.read_gps_time();
589            }
590        }
591    }
592
593    /// Create all entropy models and last items (if needed)
594    ///
595    /// ## Parameters
596    /// - `context`: the current context
597    /// - `item`: the current item to be read from
598    fn create_and_init_models_and_decompressors(&mut self, context: usize, item: &LASPoint) {
599        // should only be called when context is unused
600        assert!(self.contexts[context].unused);
601
602        // first create all entropy models and integer decompressors (if needed)
603        if self.contexts[context].m_changed_values[0].is_none() {
604            // for the channel_returns_XY layer
605            for i in 0..8 {
606                self.contexts[context].m_changed_values[i] = Some(ArithmeticModel::new(128, false));
607            }
608            self.contexts[context].m_scanner_channel = Some(ArithmeticModel::new(3, false));
609            for i in 0..16 {
610                self.contexts[context].m_number_of_returns[i] = None;
611                self.contexts[context].m_return_number[i] = None;
612            }
613            self.contexts[context].m_return_number_gps_same = Some(ArithmeticModel::new(13, false));
614
615            self.contexts[context].ic_dx = Some(IntegerCompressor::new(
616                self.dec_channel_returns_xy.clone(),
617                Some(32),
618                Some(2),
619                None,
620                None,
621            )); // 32 bits, 2 context
622            self.contexts[context].ic_dy = Some(IntegerCompressor::new(
623                self.dec_channel_returns_xy.clone(),
624                Some(32),
625                Some(22),
626                None,
627                None,
628            )); // 32 bits, 22 contexts
629
630            // for the Z layer
631            self.contexts[context].ic_z =
632                Some(IntegerCompressor::new(self.dec_z.clone(), Some(32), Some(20), None, None)); // 32 bits, 20 contexts
633
634            // for the classification layer, flags layer, and user_data layer
635            for i in 0..64 {
636                self.contexts[context].m_classification[i] = None;
637                self.contexts[context].m_flags[i] = None;
638                self.contexts[context].m_user_data[i] = None;
639            }
640            // for the intensity layer
641            self.contexts[context].ic_intensity = Some(IntegerCompressor::new(
642                self.dec_intensity.clone(),
643                Some(16),
644                Some(4),
645                None,
646                None,
647            ));
648            // for the scan_angle layer
649            self.contexts[context].ic_scan_angle = Some(IntegerCompressor::new(
650                self.dec_scan_angle.clone(),
651                Some(16),
652                Some(2),
653                None,
654                None,
655            ));
656            // for the point_source_id layer
657            self.contexts[context].ic_point_source_id = Some(IntegerCompressor::new(
658                self.dec_point_source.clone(),
659                Some(16),
660                None,
661                None,
662                None,
663            ));
664            // for the gps_time layer
665            self.contexts[context].m_gpstime_multi =
666                Some(ArithmeticModel::new(LASZIP_GPSTIME_MULTI_TOTAL as u32, false));
667            self.contexts[context].m_gpstime0diff = Some(ArithmeticModel::new(5, false));
668            self.contexts[context].ic_gpstime = Some(IntegerCompressor::new(
669                self.dec_gps_time.clone(),
670                Some(32),
671                Some(9),
672                None,
673                None,
674            )); // 32 bits, 9 contexts
675        }
676
677        // for the channel_returns_XY layer
678        for i in 0..8 {
679            self.contexts[context].m_changed_values[i].as_mut().unwrap().init(None);
680        }
681        self.contexts[context].m_scanner_channel.as_mut().unwrap().init(None);
682        for i in 0..16 {
683            self.contexts[context].m_number_of_returns[i] = None;
684            self.contexts[context].m_return_number[i] = None;
685        }
686        self.contexts[context].m_return_number_gps_same.as_mut().unwrap().init(None);
687        self.contexts[context].ic_dx.as_mut().unwrap().init_decompressor();
688        self.contexts[context].ic_dy.as_mut().unwrap().init_decompressor();
689        for i in 0..12 {
690            self.contexts[context].last_x_diff_median5[i].init();
691            self.contexts[context].last_y_diff_median5[i].init();
692        }
693        // for the Z layer
694        self.contexts[context].ic_z.as_mut().unwrap().init_decompressor();
695        for i in 0..8 {
696            self.contexts[context].last_z[i] = item.z;
697        }
698        // for the classification layer, flags layer, and user_data layer
699        for i in 0..64 {
700            self.contexts[context].m_classification[i] = None;
701            self.contexts[context].m_flags[i] = None;
702            self.contexts[context].m_user_data[i] = None;
703        }
704
705        // for the intensity layer
706        self.contexts[context].ic_intensity.as_mut().unwrap().init_decompressor();
707        for i in 0..8 {
708            self.contexts[context].last_intensity[i] = item.intensity;
709        }
710        // for the scan_angle layer
711        self.contexts[context].ic_scan_angle.as_mut().unwrap().init_decompressor();
712        // for the point_source_id layer
713        self.contexts[context].ic_point_source_id.as_mut().unwrap().init_decompressor();
714        // for the gps_time layer
715        self.contexts[context].m_gpstime_multi.as_mut().unwrap().init(None);
716        self.contexts[context].m_gpstime0diff.as_mut().unwrap().init(None);
717        self.contexts[context].ic_gpstime.as_mut().unwrap().init_decompressor();
718        self.contexts[context].last = 0;
719        self.contexts[context].next = 0;
720        self.contexts[context].last_gpstime_diff[0] = 0;
721        self.contexts[context].last_gpstime_diff[1] = 0;
722        self.contexts[context].last_gpstime_diff[2] = 0;
723        self.contexts[context].last_gpstime_diff[3] = 0;
724        self.contexts[context].multi_extreme_counter[0] = 0;
725        self.contexts[context].multi_extreme_counter[1] = 0;
726        self.contexts[context].multi_extreme_counter[2] = 0;
727        self.contexts[context].multi_extreme_counter[3] = 0;
728        self.contexts[context].last_gpstime[0].set_f64(item.gps_time.unwrap_or_default());
729        self.contexts[context].last_gpstime[1].set_f64(0.);
730        self.contexts[context].last_gpstime[2].set_f64(0.);
731        self.contexts[context].last_gpstime[3].set_f64(0.);
732        // init current context from last item
733        self.contexts[context].last_item = item.clone();
734        self.contexts[context].last_item.gps_time_change = Some(0);
735        self.contexts[context].unused = false;
736    }
737}
738impl<T: Reader> ItemReader for LAZPoint14v3Reader<T> {
739    fn init<R: Reader>(&mut self, item: &R, point: &mut LASPoint, context: &mut u32) {
740        point.inject_point14(item, 0, true);
741        {
742            // for layered compression 'dec' only hands over the stream
743            let dec = self.dec.borrow_mut();
744            let reader = dec.reader.borrow();
745
746            // how many bytes do we need to read
747            let mut num_bytes = self.num_bytes_channel_returns_xy;
748            if self.requested_z {
749                num_bytes += self.num_bytes_z;
750            }
751            if self.requested_classification {
752                num_bytes += self.num_bytes_classification;
753            }
754            if self.requested_flags {
755                num_bytes += self.num_bytes_flags;
756            }
757            if self.requested_intensity {
758                num_bytes += self.num_bytes_intensity;
759            }
760            if self.requested_scan_angle {
761                num_bytes += self.num_bytes_scan_angle;
762            }
763            if self.requested_user_data {
764                num_bytes += self.num_bytes_user_data;
765            }
766            if self.requested_point_source {
767                num_bytes += self.num_bytes_point_source;
768            }
769            if self.requested_gps_time {
770                num_bytes += self.num_bytes_gps_time;
771            }
772            // make sure the buffer is sufficiently large
773            if num_bytes > self.num_bytes_allocated {
774                //   self.bytes = new DataView(new ArrayBuffer(num_bytes));
775                self.bytes = Some(Buffer::new(vec![0; num_bytes as usize]));
776                self.num_bytes_allocated = num_bytes;
777            }
778            // load the requested bytes and init the corresponding instreams and decoders
779            // num_bytes = 0;
780            let bytes = reader.seek_slice(self.num_bytes_channel_returns_xy as usize);
781            let buffer = Buffer::new(bytes.clone());
782            let br = Rc::new(RefCell::new(BufferReader::new(bytes)));
783            self.bytes = Some(buffer);
784            self.instream_channel_returns_xy = Some(br.clone());
785            let mut decoder = ArithmeticDecoder::new(br.clone());
786            decoder.init(true);
787            self.dec_channel_returns_xy = Rc::new(RefCell::new(decoder));
788            // num_bytes += self.num_bytes_channel_returns_xy;
789
790            if self.requested_z {
791                if self.num_bytes_z != 0 {
792                    let bytes = reader.seek_slice(self.num_bytes_z as usize);
793                    let buffer = Buffer::new(bytes.clone());
794                    let br = Rc::new(RefCell::new(BufferReader::new(bytes)));
795                    self.bytes = Some(buffer);
796                    self.instream_z = Some(br.clone());
797                    let mut decoder = ArithmeticDecoder::new(br.clone());
798                    decoder.init(true);
799                    self.dec_z = Rc::new(RefCell::new(decoder));
800                    // num_bytes += self.num_bytes_z;
801                    self.changed_z = true;
802                } else {
803                    self.instream_z = None;
804                    self.changed_z = false;
805                }
806            } else {
807                if self.num_bytes_z != 0 {
808                    // skip num_bytes_z
809                    reader.seek(reader.tell() + self.num_bytes_z as u64);
810                }
811                self.changed_z = false;
812            }
813
814            if self.requested_classification {
815                if self.num_bytes_classification != 0 {
816                    let bytes = reader.seek_slice(self.num_bytes_classification as usize);
817                    let buffer = Buffer::new(bytes.clone());
818                    let br = Rc::new(RefCell::new(BufferReader::new(bytes)));
819                    self.bytes = Some(buffer);
820                    self.instream_classification = Some(br.clone());
821                    let mut decoder = ArithmeticDecoder::new(br.clone());
822                    decoder.init(true);
823                    self.dec_classification = Rc::new(RefCell::new(decoder));
824                    // num_bytes += self.num_bytes_classification;
825                    self.changed_classification = true;
826                } else {
827                    self.instream_classification = None;
828                    self.changed_classification = false;
829                }
830            } else {
831                if self.num_bytes_classification != 0 {
832                    reader.seek(reader.tell() + self.num_bytes_classification as u64);
833                }
834                self.changed_classification = false;
835            }
836
837            if self.requested_flags {
838                if self.num_bytes_flags != 0 {
839                    let bytes = reader.seek_slice(self.num_bytes_flags as usize);
840                    let buffer = Buffer::new(bytes.clone());
841                    let br = Rc::new(RefCell::new(BufferReader::new(bytes)));
842                    self.bytes = Some(buffer);
843                    self.instream_flags = Some(br.clone());
844                    let mut decoder = ArithmeticDecoder::new(br.clone());
845                    decoder.init(true);
846                    self.dec_flags = Rc::new(RefCell::new(decoder));
847                    // num_bytes += self.num_bytes_flags;
848                    self.changed_flags = true;
849                } else {
850                    self.instream_flags = None;
851                    self.changed_flags = false;
852                }
853            } else {
854                if self.num_bytes_flags != 0 {
855                    reader.seek(reader.tell() + self.num_bytes_flags as u64);
856                }
857                self.changed_flags = false;
858            }
859
860            if self.requested_intensity {
861                if self.num_bytes_intensity != 0 {
862                    let bytes = reader.seek_slice(self.num_bytes_intensity as usize);
863                    let buffer = Buffer::new(bytes.clone());
864                    let br = Rc::new(RefCell::new(BufferReader::new(bytes)));
865                    self.bytes = Some(buffer);
866                    self.instream_intensity = Some(br.clone());
867                    let mut decoder = ArithmeticDecoder::new(br.clone());
868                    decoder.init(true);
869                    self.dec_intensity = Rc::new(RefCell::new(decoder));
870                    // num_bytes += self.num_bytes_intensity;
871                    self.changed_intensity = true;
872                } else {
873                    self.instream_intensity = None;
874                    self.changed_intensity = false;
875                }
876            } else {
877                if self.num_bytes_intensity != 0 {
878                    reader.seek(reader.tell() + self.num_bytes_intensity as u64);
879                }
880                self.changed_intensity = false;
881            }
882
883            if self.requested_scan_angle {
884                if self.num_bytes_scan_angle != 0 {
885                    let bytes = reader.seek_slice(self.num_bytes_scan_angle as usize);
886                    let buffer = Buffer::new(bytes.clone());
887                    let br = Rc::new(RefCell::new(BufferReader::new(bytes)));
888                    self.bytes = Some(buffer);
889                    self.instream_scan_angle = Some(br.clone());
890                    let mut decoder = ArithmeticDecoder::new(br.clone());
891                    decoder.init(true);
892                    self.dec_scan_angle = Rc::new(RefCell::new(decoder));
893                    // num_bytes += self.num_bytes_scan_angle;
894                    self.changed_scan_angle = true;
895                } else {
896                    self.instream_scan_angle = None;
897                    self.changed_scan_angle = false;
898                }
899            } else {
900                if self.num_bytes_scan_angle != 0 {
901                    reader.seek(reader.tell() + self.num_bytes_scan_angle as u64);
902                }
903                self.changed_scan_angle = false;
904            }
905
906            if self.requested_user_data {
907                if self.num_bytes_user_data != 0 {
908                    let bytes = reader.seek_slice(self.num_bytes_user_data as usize);
909                    let buffer = Buffer::new(bytes.clone());
910                    let br = Rc::new(RefCell::new(BufferReader::new(bytes)));
911                    self.bytes = Some(buffer);
912                    self.instream_user_data = Some(br.clone());
913                    let mut decoder = ArithmeticDecoder::new(br.clone());
914                    decoder.init(true);
915                    self.dec_user_data = Rc::new(RefCell::new(decoder));
916                    // num_bytes += self.num_bytes_user_data;
917                    self.changed_user_data = true;
918                } else {
919                    self.instream_user_data = None;
920                    self.changed_user_data = false;
921                }
922            } else {
923                if self.num_bytes_user_data != 0 {
924                    reader.seek(reader.tell() + self.num_bytes_user_data as u64);
925                }
926                self.changed_user_data = false;
927            }
928
929            if self.requested_point_source {
930                if self.num_bytes_point_source != 0 {
931                    let bytes = reader.seek_slice(self.num_bytes_point_source as usize);
932                    let buffer = Buffer::new(bytes.clone());
933                    let br = Rc::new(RefCell::new(BufferReader::new(bytes)));
934                    self.bytes = Some(buffer);
935                    self.instream_point_source = Some(br.clone());
936                    let mut decoder = ArithmeticDecoder::new(br.clone());
937                    decoder.init(true);
938                    self.dec_point_source = Rc::new(RefCell::new(decoder));
939                    // num_bytes += self.num_bytes_point_source;
940                    self.changed_point_source = true;
941                } else {
942                    self.instream_point_source = None;
943                    self.changed_point_source = false;
944                }
945            } else {
946                if self.num_bytes_point_source != 0 {
947                    reader.seek(reader.tell() + self.num_bytes_point_source as u64);
948                }
949                self.changed_point_source = false;
950            }
951
952            if self.requested_gps_time {
953                if self.num_bytes_gps_time != 0 {
954                    let bytes = reader.seek_slice(self.num_bytes_gps_time as usize);
955                    let buffer = Buffer::new(bytes.clone());
956                    let br = Rc::new(RefCell::new(BufferReader::new(bytes)));
957                    self.bytes = Some(buffer);
958                    self.instream_gps_time = Some(br.clone());
959                    let mut decoder = ArithmeticDecoder::new(br.clone());
960                    decoder.init(true);
961                    self.dec_gps_time = Rc::new(RefCell::new(decoder));
962                    // num_bytes += self.num_bytes_gps_time;
963                    self.changed_gps_time = true;
964                } else {
965                    self.instream_gps_time = None;
966                    self.changed_gps_time = false;
967                }
968            } else {
969                if self.num_bytes_gps_time != 0 {
970                    reader.seek(reader.tell() + self.num_bytes_gps_time as u64);
971                }
972                self.changed_gps_time = false;
973            }
974        }
975
976        // mark the four scanner channel contexts as unused
977        for c in 0..4 {
978            self.contexts[c].unused = true;
979        }
980        // set scanner channel as current context
981        self.current_context = point.scanner_channel as u32;
982        *context = self.current_context; // the POINT14 reader sets context for all other items
983
984        // create and init models and decompressors
985        self.create_and_init_models_and_decompressors(self.current_context as usize, point);
986    }
987
988    fn read(&mut self, item: &mut LASPoint, context: &mut u32) {
989        // get last
990        let changed_values: i32;
991        {
992            let last_item = &mut self.contexts[self.current_context as usize].last_item;
993            ////////////////////////////////////////
994            // decompress returns_XY layer
995            ////////////////////////////////////////
996            // create single (3) / first (1) / last (2) / intermediate (0) context from last point return
997            let mut lpr: i32 = if last_item.return_number == 1 { 1 } else { 0 }; // (I32) first?
998            lpr += if last_item.return_number >= last_item.number_of_returns { 2 } else { 0 }; // last?
999            // add info whether the GPS time changed in the last return to the context
1000            lpr += if last_item.gps_time_change.unwrap_or_default() != 0 { 4 } else { 0 };
1001            // decompress which values have changed with last point return context
1002            changed_values = self.dec_channel_returns_xy.borrow_mut().decode_symbol(
1003                self.contexts[self.current_context as usize].m_changed_values[lpr as usize]
1004                    .as_mut()
1005                    .unwrap(),
1006            ) as i32; // I32
1007        }
1008
1009        // if scanner channel has changed
1010        if (changed_values & (1 << 6)) != 0 {
1011            // U32
1012            let diff = self.dec_channel_returns_xy.borrow_mut().decode_symbol(
1013                self.contexts[self.current_context as usize].m_scanner_channel.as_mut().unwrap(),
1014            ); // curr = last + (sym + 1)
1015            // U32
1016            let scanner_channel = (self.current_context + diff + 1) % 4;
1017            // maybe create and init entropy models and integer compressors
1018            if self.contexts[scanner_channel as usize].unused {
1019                // create and init entropy models and integer decompressors
1020                let last_item = self.contexts[self.current_context as usize].last_item.clone();
1021                self.create_and_init_models_and_decompressors(scanner_channel as usize, &last_item);
1022            }
1023            // switch context to current scanner channel
1024            self.current_context = scanner_channel;
1025            *context = self.current_context; // the POINT14 reader sets context for all other items
1026            // get last for new context
1027            let last_item = &mut self.contexts[self.current_context as usize].last_item;
1028            last_item.scanner_channel = scanner_channel as u8;
1029        }
1030        // determine changed attributes
1031        let point_source_change = (changed_values & (1 << 5)) != 0;
1032        let gps_time_change = (changed_values & (1 << 4)) != 0;
1033        let scan_angle_change = (changed_values & (1 << 3)) != 0;
1034        // get last return counts
1035        {
1036            let last_item = &mut self.contexts[self.current_context as usize].last_item;
1037            let last_n = last_item.number_of_returns; // U32
1038            let last_r = last_item.return_number; // U32
1039            // if number of returns is different we decompress it
1040            let n: u32; // U32
1041            if (changed_values & (1 << 2)) != 0 {
1042                if self.contexts[self.current_context as usize].m_number_of_returns[last_n as usize]
1043                    .is_none()
1044                {
1045                    let mut model = ArithmeticModel::new(16, false);
1046                    model.init(None);
1047                    self.contexts[self.current_context as usize].m_number_of_returns
1048                        [last_n as usize] = Some(model);
1049                }
1050                n = self.dec_channel_returns_xy.borrow_mut().decode_symbol(
1051                    self.contexts[self.current_context as usize].m_number_of_returns
1052                        [last_n as usize]
1053                        .as_mut()
1054                        .unwrap(),
1055                );
1056                last_item.number_of_returns = n as u8;
1057            } else {
1058                n = last_n as u32;
1059            }
1060            // how is the return number different
1061            let r: u32; // U32
1062            if (changed_values & 3) == 0 {
1063                // same return number
1064                r = last_r as u32;
1065            } else if (changed_values & 3) == 1 {
1066                // return number plus 1 mod 16
1067                r = (last_r as u32 + 1) % 16;
1068                last_item.return_number = r as u8;
1069            } else if (changed_values & 3) == 2 {
1070                // return number minus 1 mod 16
1071                r = (last_r as u32 + 15) % 16;
1072                last_item.return_number = r as u8;
1073            } else {
1074                // the return number difference is bigger than +1 / -1 so we decompress how it is different
1075                if gps_time_change {
1076                    // if the GPS time has changed
1077                    if self.contexts[self.current_context as usize].m_return_number[last_r as usize]
1078                        .is_none()
1079                    {
1080                        let mut model = ArithmeticModel::new(16, false);
1081                        model.init(None);
1082                        self.contexts[self.current_context as usize].m_return_number
1083                            [last_r as usize] = Some(model);
1084                    }
1085                    r = self.dec_channel_returns_xy.borrow_mut().decode_symbol(
1086                        self.contexts[self.current_context as usize].m_return_number
1087                            [last_r as usize]
1088                            .as_mut()
1089                            .unwrap(),
1090                    );
1091                }
1092                // if the GPS time has not changed
1093                else {
1094                    // I32
1095                    let sym = self.dec_channel_returns_xy.borrow_mut().decode_symbol(
1096                        self.contexts[self.current_context as usize]
1097                            .m_return_number_gps_same
1098                            .as_mut()
1099                            .unwrap(),
1100                    ) as i32;
1101                    r = ((last_r as i32 + (sym + 2)) % 16) as u32;
1102                }
1103                last_item.return_number = r as u8;
1104            }
1105            // set legacy return counts and number of returns
1106            if n > 7 {
1107                if r > 6 {
1108                    if r >= n {
1109                        last_item.legacy_return_number = 7;
1110                    } else {
1111                        last_item.legacy_return_number = 6;
1112                    }
1113                } else {
1114                    last_item.legacy_return_number = r as u8;
1115                }
1116                last_item.legacy_number_of_returns = 7;
1117            } else {
1118                last_item.legacy_return_number = r as u8;
1119                last_item.legacy_number_of_returns = n as u8;
1120            }
1121            // get return map m and return level l context for current point
1122            let m = NUMBER_RETURN_MAP_6CTX[n as usize][r as usize] as u32; // U32
1123            let l = NUMBER_RETURN_LEVEL_8CTX[n as usize][r as usize]; // U32
1124            // create single (3) / first (1) / last (2) / intermediate (0) return context for current point
1125            let mut cpr = if r == 1 { 2 } else { 0 }; // (I32) first ?
1126            cpr += if r >= n { 1 } else { 0 }; // last ?
1127            let mut k_bits: u32; // U32
1128            let mut median: i32;
1129            let mut diff: i32; // I32
1130            let dec_index = (m << 1) | (if gps_time_change { 1 } else { 0 });
1131            // decompress X coordinate
1132            median = self.contexts[self.current_context as usize].last_x_diff_median5
1133                [dec_index as usize]
1134                .get();
1135            diff = self.contexts[self.current_context as usize]
1136                .ic_dx
1137                .as_mut()
1138                .unwrap()
1139                .decompress(median, if n == 1 { 1 } else { 0 });
1140            last_item.x += diff;
1141            self.contexts[self.current_context as usize].last_x_diff_median5[dec_index as usize]
1142                .add(diff);
1143            // decompress Y coordinate
1144            median = self.contexts[self.current_context as usize].last_y_diff_median5
1145                [dec_index as usize]
1146                .get();
1147            k_bits = self.contexts[self.current_context as usize].ic_dx.as_mut().unwrap().get_k();
1148            diff = self.contexts[self.current_context as usize].ic_dy.as_mut().unwrap().decompress(
1149                median,
1150                (if n == 1 { 1 } else { 0 })
1151                    + (if k_bits < 20 { u32_zero_bit0(k_bits) } else { 20 }),
1152            );
1153            last_item.y += diff;
1154            self.contexts[self.current_context as usize].last_y_diff_median5[dec_index as usize]
1155                .add(diff);
1156            ////////////////////////////////////////
1157            // decompress Z layer (if changed and requested)
1158            ////////////////////////////////////////
1159            if self.changed_z {
1160                // if the Z coordinate should be decompressed and changes within this chunk
1161                k_bits = (self.contexts[self.current_context as usize]
1162                    .ic_dx
1163                    .as_mut()
1164                    .unwrap()
1165                    .get_k()
1166                    + self.contexts[self.current_context as usize].ic_dy.as_mut().unwrap().get_k())
1167                    / 2;
1168                last_item.z =
1169                    self.contexts[self.current_context as usize].ic_z.as_mut().unwrap().decompress(
1170                        self.contexts[self.current_context as usize].last_z[l as usize],
1171                        (if n == 1 { 1 } else { 0 })
1172                            + (if k_bits < 18 { u32_zero_bit0(k_bits) } else { 18 }),
1173                    );
1174                self.contexts[self.current_context as usize].last_z[l as usize] = last_item.z;
1175            }
1176            ////////////////////////////////////////
1177            // decompress classifications layer (if changed and requested)
1178            ////////////////////////////////////////
1179            if self.changed_classification {
1180                // if the classification should be decompressed and changes within this chunk
1181                let last_classification = last_item.classification as u32; // U32
1182                let ccc =
1183                    (((last_classification & 0x1f) << 1) + (if cpr == 3 { 1 } else { 0 })) as i32; // I32
1184                if self.contexts[self.current_context as usize].m_classification[ccc as usize]
1185                    .is_none()
1186                {
1187                    let mut model = ArithmeticModel::new(256, false);
1188                    model.init(None);
1189                    self.contexts[self.current_context as usize].m_classification[ccc as usize] =
1190                        Some(model);
1191                }
1192                last_item.classification = self.dec_classification.borrow_mut().decode_symbol(
1193                    self.contexts[self.current_context as usize].m_classification[ccc as usize]
1194                        .as_mut()
1195                        .unwrap(),
1196                ) as u8;
1197                // update the legacy copy
1198                if last_item.classification < 32 {
1199                    last_item.legacy_classification = last_item.classification;
1200                } else {
1201                    last_item.legacy_classification = 0;
1202                }
1203            }
1204            ////////////////////////////////////////
1205            // decompress flags layer (if changed and requested)
1206            ////////////////////////////////////////
1207            if self.changed_flags {
1208                // if the flags should be decompressed and change within this chunk
1209                // U32
1210                let last_flags = ((last_item.edge_of_flight_line as u32) << 5)
1211                    | ((last_item.scan_direction_flag as u32) << 4)
1212                    | last_item.class_flag as u32;
1213                if self.contexts[self.current_context as usize].m_flags[last_flags as usize]
1214                    .is_none()
1215                {
1216                    let mut model = ArithmeticModel::new(64, false);
1217                    model.init(None);
1218                    self.contexts[self.current_context as usize].m_flags[last_flags as usize] =
1219                        Some(model);
1220                }
1221                let flags = self.dec_flags.borrow_mut().decode_symbol(
1222                    self.contexts[self.current_context as usize].m_flags[last_flags as usize]
1223                        .as_mut()
1224                        .unwrap(),
1225                ); // U32
1226                last_item.edge_of_flight_line = (flags & (1 << 5)) != 0;
1227                last_item.scan_direction_flag = (flags & (1 << 4)) != 0;
1228                last_item.class_flag = (flags & 0x0f) as u8;
1229                // legacy copies
1230                //   last_item.legacy_flags = flags & 0x07;
1231            }
1232            ////////////////////////////////////////
1233            // decompress intensity layer (if changed and requested)
1234            ////////////////////////////////////////
1235            if self.changed_intensity {
1236                // if the intensity should be decompressed and changes within this chunk
1237                // U16
1238                let intensity = self.contexts[self.current_context as usize]
1239                    .ic_intensity
1240                    .as_mut()
1241                    .unwrap()
1242                    .decompress(
1243                        self.contexts[self.current_context as usize].last_intensity
1244                            [(cpr << 1) | (if gps_time_change { 1 } else { 0 })]
1245                            as i32,
1246                        cpr as u32,
1247                    );
1248                self.contexts[self.current_context as usize].last_intensity
1249                    [(cpr << 1) | (if gps_time_change { 1 } else { 0 })] = intensity as u16;
1250                last_item.intensity = intensity as u16;
1251            }
1252            ////////////////////////////////////////
1253            // decompress scan_angle layer (if changed and requested)
1254            ////////////////////////////////////////
1255            if self.changed_scan_angle {
1256                // if the scan angle should be decompressed and changes within this chunk
1257                if scan_angle_change {
1258                    // if the scan angle has actually changed
1259                    last_item.scan_angle = self.contexts[self.current_context as usize]
1260                        .ic_scan_angle
1261                        .as_mut()
1262                        .unwrap()
1263                        .decompress(
1264                            last_item.scan_angle as i32,
1265                            if gps_time_change { 1 } else { 0 },
1266                        ) as i16; // if the GPS time has changed
1267                    last_item.legacy_scan_angle_rank =
1268                        i8_clamp(i16_quantize(0.006 * last_item.scan_angle as f64) as i32);
1269                }
1270            }
1271            ////////////////////////////////////////
1272            // decompress user_data layer (if changed and requested)
1273            ////////////////////////////////////////
1274            if self.changed_user_data {
1275                let index = (last_item.user_data / 4) as usize;
1276                // if the user data should be decompressed and changes within this chunk
1277                if self.contexts[self.current_context as usize].m_user_data[index].is_none() {
1278                    let mut model = ArithmeticModel::new(256, false);
1279                    model.init(None);
1280                    self.contexts[self.current_context as usize].m_user_data[index] = Some(model);
1281                }
1282                last_item.user_data = self.dec_user_data.borrow_mut().decode_symbol(
1283                    self.contexts[self.current_context as usize].m_user_data[index]
1284                        .as_mut()
1285                        .unwrap(),
1286                ) as u8;
1287            }
1288            ////////////////////////////////////////
1289            // decompress point_source layer (if changed and requested)
1290            ////////////////////////////////////////
1291            if self.changed_point_source {
1292                // if the point source ID should be decompressed and changes within this chunk
1293                if point_source_change {
1294                    // if the point source ID has actually changed
1295                    last_item.point_source_id = self.contexts[self.current_context as usize]
1296                        .ic_point_source_id
1297                        .as_mut()
1298                        .unwrap()
1299                        .decompress(last_item.point_source_id as i32, 0)
1300                        as u16;
1301                }
1302            }
1303        }
1304        ////////////////////////////////////////
1305        // decompress gps_time layer (if changed and requested)
1306        ////////////////////////////////////////
1307        if self.changed_gps_time {
1308            // if the GPS time should be decompressed and changes within this chunk
1309            if gps_time_change {
1310                // if the GPS time has actually changed
1311                self.read_gps_time();
1312                let last_item = &mut self.contexts[self.current_context as usize].last_item;
1313                last_item.gps_time = Some(
1314                    self.contexts[self.current_context as usize].last_gpstime
1315                        [self.contexts[self.current_context as usize].last as usize]
1316                        .f64(),
1317                );
1318            }
1319        }
1320        let last_item = &mut self.contexts[self.current_context as usize].last_item;
1321        // copy the last item
1322        *item = last_item.clone();
1323        // remember if the last point had a gps_time_change
1324        last_item.gps_time_change = Some(if gps_time_change { 1 } else { 0 });
1325    }
1326
1327    fn chunk_sizes<R: Reader>(&mut self, reader: &R) {
1328        self.num_bytes_channel_returns_xy = reader.uint32_le(None);
1329        self.num_bytes_z = reader.uint32_le(None);
1330        self.num_bytes_classification = reader.uint32_le(None);
1331        self.num_bytes_flags = reader.uint32_le(None);
1332        self.num_bytes_intensity = reader.uint32_le(None);
1333        self.num_bytes_scan_angle = reader.uint32_le(None);
1334        self.num_bytes_user_data = reader.uint32_le(None);
1335        self.num_bytes_point_source = reader.uint32_le(None);
1336        self.num_bytes_gps_time = reader.uint32_le(None);
1337    }
1338}
1339
1340/// Parse LAZ RGB 1.4v3
1341#[derive(Debug, Clone)]
1342pub struct LAZrgb14v3Reader<T: Reader> {
1343    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
1344    instream_rgb: Option<Rc<RefCell<BufferReader>>>,
1345    dec_rgb: Option<ArithmeticDecoder<BufferReader>>,
1346    changed_rgb: bool,
1347    num_bytes_rgb: u32,
1348    requested_rgb: bool,
1349    bytes: Option<Vec<u8>>,
1350    num_bytes_allocated: u32,
1351    current_context: u32,
1352    contexts: [LAZContextRGB14; 4],
1353}
1354impl<T: Reader> LAZrgb14v3Reader<T> {
1355    /// Create a new LAZrgb14v3Reader
1356    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>, decompress_selective: Option<u32>) -> Self {
1357        let decompress_selective = decompress_selective.unwrap_or(LASZIP_DECOMPRESS_SELECTIVE_ALL);
1358        let mut rgb_reader = Self {
1359            dec,
1360            instream_rgb: None,
1361            dec_rgb: None,
1362            changed_rgb: false,
1363            num_bytes_rgb: 0,
1364            requested_rgb: false,
1365            bytes: None,
1366            num_bytes_allocated: 0,
1367            current_context: 0,
1368            contexts: [
1369                LAZContextRGB14::default(),
1370                LAZContextRGB14::default(),
1371                LAZContextRGB14::default(),
1372                LAZContextRGB14::default(),
1373            ],
1374        };
1375        rgb_reader.requested_rgb = decompress_selective & LASZIP_DECOMPRESS_SELECTIVE_RGB != 0;
1376        // mark the four scanner channel contexts as uninitialized
1377        for c in 0..4 {
1378            rgb_reader.contexts[c].m_byte_used = None;
1379        }
1380        rgb_reader
1381    }
1382
1383    fn create_and_init_models_and_decompressors(&mut self, context: usize, item: &[u16; 3]) {
1384        // first create all entropy models (if needed)
1385        if self.contexts[context].m_byte_used.is_none() {
1386            self.contexts[context].m_byte_used = Some(ArithmeticModel::new(128, false));
1387            self.contexts[context].m_rgb_diff0 = Some(ArithmeticModel::new(256, false));
1388            self.contexts[context].m_rgb_diff1 = Some(ArithmeticModel::new(256, false));
1389            self.contexts[context].m_rgb_diff2 = Some(ArithmeticModel::new(256, false));
1390            self.contexts[context].m_rgb_diff3 = Some(ArithmeticModel::new(256, false));
1391            self.contexts[context].m_rgb_diff4 = Some(ArithmeticModel::new(256, false));
1392            self.contexts[context].m_rgb_diff5 = Some(ArithmeticModel::new(256, false));
1393        }
1394        // then init entropy models
1395        self.contexts[context].m_byte_used.as_mut().unwrap().init(None);
1396        self.contexts[context].m_rgb_diff0.as_mut().unwrap().init(None);
1397        self.contexts[context].m_rgb_diff1.as_mut().unwrap().init(None);
1398        self.contexts[context].m_rgb_diff2.as_mut().unwrap().init(None);
1399        self.contexts[context].m_rgb_diff3.as_mut().unwrap().init(None);
1400        self.contexts[context].m_rgb_diff4.as_mut().unwrap().init(None);
1401        self.contexts[context].m_rgb_diff5.as_mut().unwrap().init(None);
1402        // init current context from item
1403        self.contexts[context].last_item = *item;
1404        self.contexts[context].unused = false;
1405    }
1406}
1407impl<T: Reader> ItemReader for LAZrgb14v3Reader<T> {
1408    fn init<R: Reader>(&mut self, item: &R, point: &mut LASPoint, context: &mut u32) {
1409        {
1410            let dec = &mut self.dec.borrow_mut();
1411            let reader = &dec.reader.borrow();
1412
1413            // make sure the buffer is sufficiently large
1414            if self.num_bytes_rgb > self.num_bytes_allocated {
1415                self.num_bytes_allocated = self.num_bytes_rgb;
1416            }
1417            // load the requested bytes and init the corresponding instreams an decoders
1418            if self.requested_rgb {
1419                if self.num_bytes_rgb != 0 {
1420                    let bytes = reader.seek_slice(self.num_bytes_rgb as usize);
1421                    self.bytes = Some(bytes.clone());
1422                    let rgb_reader = Rc::new(RefCell::new(BufferReader::new(bytes)));
1423                    self.instream_rgb = Some(rgb_reader.clone());
1424                    let mut decoder = ArithmeticDecoder::new(rgb_reader);
1425                    decoder.init(true);
1426                    self.dec_rgb = Some(decoder);
1427                    self.changed_rgb = true;
1428                } else {
1429                    self.instream_rgb = None;
1430                    self.changed_rgb = false;
1431                }
1432            } else {
1433                if self.num_bytes_rgb != 0 {
1434                    reader.seek(reader.tell() + self.num_bytes_rgb as u64);
1435                }
1436                self.changed_rgb = false;
1437            }
1438            // mark the four scanner channel contexts as unused
1439            for c in 0..4 {
1440                self.contexts[c].unused = true;
1441            }
1442            // set scanner channel as current context
1443            self.current_context = *context; // all other items use context set by POINT14 reader
1444        }
1445        // create and init models and decompressors
1446        let mut data: [u16; 3] = [0, 0, 0];
1447        data[0] = item.uint16_le(None);
1448        data[1] = item.uint16_le(None);
1449        data[2] = item.uint16_le(None);
1450        point.rgba = Some(RGBA::from_u16s(data[0], data[1], data[2], u16::MAX));
1451        self.create_and_init_models_and_decompressors(self.current_context as usize, &data);
1452    }
1453
1454    fn read(&mut self, item: &mut LASPoint, context: &mut u32) {
1455        let item_rgb = item.rgba.unwrap().to_u16s();
1456        let mut item_rgb: [u16; 3] = [item_rgb.0, item_rgb.1, item_rgb.2];
1457        // get last
1458        let mut last_item = self.contexts[self.current_context as usize].last_item;
1459        // check for context switch
1460        if self.current_context != *context {
1461            self.current_context = *context; // all other items use context set by POINT14 reader
1462            if self.contexts[self.current_context as usize].unused {
1463                self.create_and_init_models_and_decompressors(
1464                    self.current_context as usize,
1465                    &last_item,
1466                );
1467                last_item = self.contexts[self.current_context as usize].last_item;
1468            }
1469        }
1470        // decompress
1471        if self.changed_rgb {
1472            // let mut corr: u8 = 0; // U8
1473            // let mut diff: i32 = 0; // I32
1474            let sym = self.dec_rgb.as_mut().unwrap().decode_symbol(
1475                self.contexts[self.current_context as usize].m_byte_used.as_mut().unwrap(),
1476            ); // U32
1477            if (sym & (1 << 0)) != 0 {
1478                let corr = self.dec_rgb.as_mut().unwrap().decode_symbol(
1479                    self.contexts[self.current_context as usize].m_rgb_diff0.as_mut().unwrap(),
1480                ) as u8;
1481                item_rgb[0] = u8_fold(corr as u32 + (last_item[0] & 255) as u32) as u16;
1482            } else {
1483                item_rgb[0] = last_item[0] & 0xff;
1484            }
1485            if (sym & (1 << 1)) != 0 {
1486                let corr = self.dec_rgb.as_mut().unwrap().decode_symbol(
1487                    self.contexts[self.current_context as usize].m_rgb_diff1.as_mut().unwrap(),
1488                ) as u8;
1489                item_rgb[0] |= (u8_fold(corr as u32 + (last_item[0] >> 8) as u32) as u16) << 8;
1490            } else {
1491                item_rgb[0] |= last_item[0] & 0xff00;
1492            }
1493            if (sym & (1 << 6)) != 0 {
1494                let mut diff = (item_rgb[0] & 0x00ff) as i32 - (last_item[0] & 0x00ff) as i32;
1495                if (sym & (1 << 2)) != 0 {
1496                    let corr = self.dec_rgb.as_mut().unwrap().decode_symbol(
1497                        self.contexts[self.current_context as usize].m_rgb_diff2.as_mut().unwrap(),
1498                    ) as u8;
1499                    item_rgb[1] = u8_fold(
1500                        corr as u32 + u8_clamp((diff + (last_item[1] & 255) as i32) as u32) as u32,
1501                    ) as u16;
1502                } else {
1503                    item_rgb[1] = last_item[1] & 0xff;
1504                }
1505                if (sym & (1 << 4)) != 0 {
1506                    let corr = self.dec_rgb.as_mut().unwrap().decode_symbol(
1507                        self.contexts[self.current_context as usize].m_rgb_diff4.as_mut().unwrap(),
1508                    ) as u8;
1509                    diff = (diff
1510                        + ((item_rgb[1] & 0x00ff) as i32 - (last_item[1] & 0x00ff) as i32))
1511                        / 2;
1512                    item_rgb[2] = u8_fold(
1513                        corr as u32 + u8_clamp((diff + (last_item[2] & 255) as i32) as u32) as u32,
1514                    ) as u16;
1515                } else {
1516                    item_rgb[2] = last_item[2] & 0xff;
1517                }
1518                diff = (item_rgb[0] >> 8) as i32 - (last_item[0] >> 8) as i32;
1519                if (sym & (1 << 3)) != 0 {
1520                    let corr = self.dec_rgb.as_mut().unwrap().decode_symbol(
1521                        self.contexts[self.current_context as usize].m_rgb_diff3.as_mut().unwrap(),
1522                    ) as u8;
1523                    item_rgb[1] |= (u8_fold(
1524                        corr as u32 + u8_clamp((diff + (last_item[1] >> 8) as i32) as u32) as u32,
1525                    ) as u16)
1526                        << 8;
1527                } else {
1528                    item_rgb[1] |= last_item[1] & 0xff00;
1529                }
1530                if (sym & (1 << 5)) != 0 {
1531                    let corr = self.dec_rgb.as_mut().unwrap().decode_symbol(
1532                        self.contexts[self.current_context as usize].m_rgb_diff5.as_mut().unwrap(),
1533                    ) as u8;
1534                    diff = (diff + ((item_rgb[1] >> 8) as i32 - (last_item[1] >> 8) as i32)) / 2;
1535                    item_rgb[2] |= (u8_fold(
1536                        corr as u32 + u8_clamp((diff + (last_item[2] >> 8) as i32) as u32) as u32,
1537                    ) as u16)
1538                        << 8;
1539                } else {
1540                    item_rgb[2] |= last_item[2] & 0xff00;
1541                }
1542            } else {
1543                item_rgb[1] = item_rgb[0];
1544                item_rgb[2] = item_rgb[0];
1545            }
1546            self.contexts[self.current_context as usize].last_item = item_rgb;
1547        }
1548        item.rgba = Some(RGBA::from_u16s(item_rgb[0], item_rgb[1], item_rgb[2], u16::MAX));
1549    }
1550
1551    fn chunk_sizes<R: Reader>(&mut self, reader: &R) {
1552        self.num_bytes_rgb = reader.uint32_le(None);
1553    }
1554}
1555
1556/// Parse LAZ RGB NIR 1.4v3
1557#[derive(Debug, Clone)]
1558pub struct LAZrgbNir14v3Reader<T: Reader> {
1559    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
1560    instream_rgb: Option<Rc<RefCell<BufferReader>>>,
1561    instream_nir: Option<Rc<RefCell<BufferReader>>>,
1562    dec_rgb: Option<ArithmeticDecoder<BufferReader>>,
1563    dec_nir: Option<ArithmeticDecoder<BufferReader>>,
1564    changed_rgb: bool,
1565    changed_nir: bool,
1566    num_bytes_rgb: u32,
1567    num_bytes_nir: u32,
1568    requested_rgb: bool,
1569    requested_nir: bool,
1570    bytes: Option<Buffer>,
1571    num_bytes_allocated: u32,
1572    current_context: u32,
1573    contexts: [LASContextRGBNir14; 4],
1574}
1575impl<T: Reader> LAZrgbNir14v3Reader<T> {
1576    /// Create a new LAZrgbNir14v3Reader
1577    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>, decompress_selective: Option<u32>) -> Self {
1578        let decompress_selective = decompress_selective.unwrap_or(LASZIP_DECOMPRESS_SELECTIVE_ALL);
1579        let mut rgbn_reader = LAZrgbNir14v3Reader {
1580            dec,
1581            instream_rgb: None,
1582            instream_nir: None,
1583            dec_rgb: None,
1584            dec_nir: None,
1585            changed_rgb: false,
1586            changed_nir: false,
1587            num_bytes_rgb: 0,
1588            num_bytes_nir: 0,
1589            requested_rgb: false,
1590            requested_nir: false,
1591            bytes: None,
1592            num_bytes_allocated: 0,
1593            current_context: 0,
1594            contexts: [
1595                LASContextRGBNir14::default(),
1596                LASContextRGBNir14::default(),
1597                LASContextRGBNir14::default(),
1598                LASContextRGBNir14::default(),
1599            ],
1600        };
1601        rgbn_reader.requested_rgb = (decompress_selective & LASZIP_DECOMPRESS_SELECTIVE_RGB) != 0;
1602        rgbn_reader.requested_nir = (decompress_selective & LASZIP_DECOMPRESS_SELECTIVE_NIR) != 0;
1603        // mark the four scanner channel contexts as uninitialized
1604        for c in 0..4 {
1605            rgbn_reader.contexts[c].m_rgb_bytes_used = None;
1606            rgbn_reader.contexts[c].m_nir_bytes_used = None;
1607        }
1608
1609        rgbn_reader
1610    }
1611
1612    fn create_and_init_models_and_decompressors(&mut self, context: usize, item: &[u16; 4]) {
1613        // first create all entropy models (if needed)
1614        if self.requested_rgb {
1615            if self.contexts[context].m_rgb_bytes_used.is_none() {
1616                self.contexts[context].m_rgb_bytes_used = Some(ArithmeticModel::new(128, false));
1617                self.contexts[context].m_rgb_diff0 = Some(ArithmeticModel::new(256, false));
1618                self.contexts[context].m_rgb_diff1 = Some(ArithmeticModel::new(256, false));
1619                self.contexts[context].m_rgb_diff2 = Some(ArithmeticModel::new(256, false));
1620                self.contexts[context].m_rgb_diff3 = Some(ArithmeticModel::new(256, false));
1621                self.contexts[context].m_rgb_diff4 = Some(ArithmeticModel::new(256, false));
1622                self.contexts[context].m_rgb_diff5 = Some(ArithmeticModel::new(256, false));
1623            }
1624            // then init entropy models
1625            self.contexts[context].m_rgb_bytes_used.as_mut().unwrap().init(None);
1626            self.contexts[context].m_rgb_diff0.as_mut().unwrap().init(None);
1627            self.contexts[context].m_rgb_diff1.as_mut().unwrap().init(None);
1628            self.contexts[context].m_rgb_diff2.as_mut().unwrap().init(None);
1629            self.contexts[context].m_rgb_diff3.as_mut().unwrap().init(None);
1630            self.contexts[context].m_rgb_diff4.as_mut().unwrap().init(None);
1631            self.contexts[context].m_rgb_diff5.as_mut().unwrap().init(None);
1632        }
1633        if self.requested_nir {
1634            if self.contexts[context].m_nir_bytes_used.is_none() {
1635                self.contexts[context].m_nir_bytes_used = Some(ArithmeticModel::new(4, false));
1636                self.contexts[context].m_nir_diff0 = Some(ArithmeticModel::new(256, false));
1637                self.contexts[context].m_nir_diff1 = Some(ArithmeticModel::new(256, false));
1638            }
1639            // then init entropy models
1640            self.contexts[context].m_nir_bytes_used.as_mut().unwrap().init(None);
1641            self.contexts[context].m_nir_diff0.as_mut().unwrap().init(None);
1642            self.contexts[context].m_nir_diff1.as_mut().unwrap().init(None);
1643        }
1644        // init current context from item
1645        self.contexts[context].last_item = *item;
1646        self.contexts[context].unused = false;
1647    }
1648}
1649impl<T: Reader> ItemReader for LAZrgbNir14v3Reader<T> {
1650    fn init<R: Reader>(&mut self, item: &R, point: &mut LASPoint, context: &mut u32) {
1651        {
1652            // for layered compression 'dec' only hands over the stream
1653            let dec = self.dec.borrow_mut();
1654            let reader = dec.reader.clone();
1655            // on the first init create instreams and decoders
1656            // TODO: Do we need this?
1657            // if self.instream_rgb.is_none() {
1658            //   // create decoders
1659            //   self.dec_rgb = Some(ArithmeticDecoder::new(reader));
1660            //   self.dec_nir = Some(ArithmeticDecoder::new(reader));
1661            // }
1662            let reader = reader.borrow_mut();
1663            // how many bytes do we need to read
1664            let mut num_bytes = 0;
1665            if self.requested_rgb {
1666                num_bytes += self.num_bytes_rgb;
1667            }
1668            if self.requested_nir {
1669                num_bytes += self.num_bytes_nir;
1670            }
1671            // make sure the buffer is sufficiently large
1672            if num_bytes > self.num_bytes_allocated {
1673                self.num_bytes_allocated = num_bytes;
1674            }
1675            // load the requested bytes and init the corresponding instreams an decoders
1676            // num_bytes = 0;
1677            if self.requested_rgb {
1678                if self.num_bytes_rgb != 0 {
1679                    let bytes = reader.seek_slice(self.num_bytes_rgb as usize);
1680                    let buffer = bytes.clone().into();
1681                    self.bytes = Some(buffer);
1682                    // num_bytes += self.num_bytes_rgb;
1683                    let br = Rc::new(RefCell::new(BufferReader::new(bytes)));
1684                    self.instream_rgb = Some(br.clone());
1685                    let mut decoder = ArithmeticDecoder::new(br);
1686                    decoder.init(true);
1687                    self.dec_rgb = Some(decoder);
1688                    self.changed_rgb = true;
1689                } else {
1690                    self.instream_rgb = None;
1691                    self.changed_rgb = false;
1692                }
1693            } else {
1694                if self.num_bytes_rgb != 0 {
1695                    reader.seek(reader.tell() + self.num_bytes_rgb as u64);
1696                }
1697                self.changed_rgb = false;
1698            }
1699            if self.requested_nir {
1700                if self.num_bytes_nir != 0 {
1701                    let bytes = reader.seek_slice(self.num_bytes_nir as usize);
1702                    let buffer = bytes.clone().into();
1703                    self.bytes = Some(buffer);
1704                    // let br = BufferReader::new(bytes);
1705                    let br = Rc::new(RefCell::new(BufferReader::new(bytes)));
1706                    self.instream_nir = Some(br.clone());
1707                    let mut decoder = ArithmeticDecoder::new(br);
1708                    decoder.init(true);
1709                    self.dec_nir = Some(decoder);
1710                    self.changed_nir = true;
1711                } else {
1712                    self.instream_nir = None;
1713                    self.changed_nir = false;
1714                }
1715            } else {
1716                if self.num_bytes_nir != 0 {
1717                    reader.seek(reader.tell() + self.num_bytes_nir as u64);
1718                }
1719                self.changed_nir = false;
1720            }
1721        }
1722        // mark the four scanner channel contexts as unused
1723        for c in 0..4 {
1724            self.contexts[c].unused = true;
1725        }
1726        // set scanner channel as current context
1727        self.current_context = *context; // all other items use context set by POINT14 reader
1728        // create and init models and decompressors
1729        let mut data: [u16; 4] = [0; 4];
1730        data[0] = item.uint16_le(None);
1731        data[1] = item.uint16_le(None);
1732        data[2] = item.uint16_le(None);
1733        data[3] = item.uint16_le(None);
1734        point.rgba = Some(RGBA::from_u16s(data[0], data[1], data[2], u16::MAX));
1735        point.nir = Some(data[3]);
1736        self.create_and_init_models_and_decompressors(self.current_context as usize, &data);
1737    }
1738
1739    fn read(&mut self, item: &mut LASPoint, context: &mut u32) {
1740        let item_rgb = item.rgba.unwrap().to_u16s();
1741        let mut item_rgb: [u16; 3] = [item_rgb.0, item_rgb.1, item_rgb.2];
1742        // let mut item_nir = item.nir.unwrap();
1743        // get last
1744        let mut last_item = self.contexts[self.current_context as usize].last_item;
1745        // check for context switch
1746        if self.current_context != *context {
1747            self.current_context = *context; // all other items use context set by POINT14 reader
1748            if self.contexts[self.current_context as usize].unused {
1749                self.create_and_init_models_and_decompressors(
1750                    self.current_context as usize,
1751                    &last_item,
1752                );
1753                last_item = self.contexts[self.current_context as usize].last_item;
1754            }
1755        }
1756        // decompress
1757        ////////////////////////////////////////
1758        // decompress RGB layer
1759        ////////////////////////////////////////
1760        if self.changed_rgb {
1761            let mut corr: u8; // U8
1762            // let mut diff: i32 = 0; // I32
1763            let sym = self.dec_rgb.as_mut().unwrap().decode_symbol(
1764                self.contexts[self.current_context as usize].m_rgb_bytes_used.as_mut().unwrap(),
1765            ); // U32
1766            if (sym & (1 << 0)) != 0 {
1767                corr = self.dec_rgb.as_mut().unwrap().decode_symbol(
1768                    self.contexts[self.current_context as usize].m_rgb_diff0.as_mut().unwrap(),
1769                ) as u8;
1770                item_rgb[0] = u8_fold(corr as u32 + (last_item[0] & 255) as u32) as u16;
1771            } else {
1772                item_rgb[0] = last_item[0] & 0xff;
1773            }
1774            if (sym & (1 << 1)) != 0 {
1775                corr = self.dec_rgb.as_mut().unwrap().decode_symbol(
1776                    self.contexts[self.current_context as usize].m_rgb_diff1.as_mut().unwrap(),
1777                ) as u8;
1778                item_rgb[0] |= (u8_fold(corr as u32 + (last_item[0] >> 8) as u32) as u16) << 8;
1779            } else {
1780                item_rgb[0] |= last_item[0] & 0xff00;
1781            }
1782            if (sym & (1 << 6)) != 0 {
1783                let diff: i32 = (item_rgb[0] & 0x00ff) as i32 - (last_item[0] & 0x00ff) as i32;
1784                if (sym & (1 << 2)) != 0 {
1785                    corr = self.dec_rgb.as_mut().unwrap().decode_symbol(
1786                        self.contexts[self.current_context as usize].m_rgb_diff2.as_mut().unwrap(),
1787                    ) as u8;
1788                    item_rgb[1] = u8_fold(
1789                        corr as u32 + u8_clamp((diff + (last_item[1] & 255) as i32) as u32) as u32,
1790                    ) as u16;
1791                } else {
1792                    item_rgb[1] = last_item[1] & 0xff;
1793                }
1794                if (sym & (1 << 4)) != 0 {
1795                    corr = self.dec_rgb.as_mut().unwrap().decode_symbol(
1796                        self.contexts[self.current_context as usize].m_rgb_diff4.as_mut().unwrap(),
1797                    ) as u8;
1798                    let diff = (diff
1799                        + ((item_rgb[1] & 0x00ff) as i32 - (last_item[1] & 0x00ff) as i32))
1800                        / 2;
1801                    item_rgb[2] = u8_fold(
1802                        corr as u32 + u8_clamp((diff + (last_item[2] & 255) as i32) as u32) as u32,
1803                    ) as u16;
1804                } else {
1805                    item_rgb[2] = last_item[2] & 0xff;
1806                }
1807                let diff = (item_rgb[0] >> 8) as i32 - (last_item[0] >> 8) as i32;
1808                if (sym & (1 << 3)) != 0 {
1809                    corr = self.dec_rgb.as_mut().unwrap().decode_symbol(
1810                        self.contexts[self.current_context as usize].m_rgb_diff3.as_mut().unwrap(),
1811                    ) as u8;
1812                    item_rgb[1] |= (u8_fold(
1813                        corr as u32 + u8_clamp((diff + (last_item[1] >> 8) as i32) as u32) as u32,
1814                    ) as u16)
1815                        << 8;
1816                } else {
1817                    item_rgb[1] |= last_item[1] & 0xff00;
1818                }
1819                if (sym & (1 << 5)) != 0 {
1820                    corr = self.dec_rgb.as_mut().unwrap().decode_symbol(
1821                        self.contexts[self.current_context as usize].m_rgb_diff5.as_mut().unwrap(),
1822                    ) as u8;
1823                    let diff =
1824                        (diff + ((item_rgb[1] >> 8) as i32 - (last_item[1] >> 8) as i32)) / 2;
1825                    item_rgb[2] |= (u8_fold(
1826                        corr as u32 + u8_clamp((diff + (last_item[2] >> 8) as i32) as u32) as u32,
1827                    ) as u16)
1828                        << 8;
1829                } else {
1830                    item_rgb[2] |= last_item[2] & 0xff00;
1831                }
1832            } else {
1833                item_rgb[1] = item_rgb[0];
1834                item_rgb[2] = item_rgb[0];
1835            }
1836            last_item[0..3].copy_from_slice(&item_rgb[0..3]);
1837        } else {
1838            item_rgb.copy_from_slice(&last_item[0..3]);
1839        }
1840        item.rgba = Some(RGBA::from_u16s(item_rgb[0], item_rgb[1], item_rgb[2], u16::MAX));
1841        ////////////////////////////////////////
1842        // decompress NIR layer
1843        ////////////////////////////////////////
1844        let mut item_nir: u16;
1845        if self.changed_nir {
1846            let mut corr: u8; // U8
1847            let sym = self.dec_nir.as_mut().unwrap().decode_symbol(
1848                self.contexts[self.current_context as usize].m_nir_bytes_used.as_mut().unwrap(),
1849            ); // U32
1850            if (sym & (1 << 0)) != 0 {
1851                corr = self.dec_nir.as_mut().unwrap().decode_symbol(
1852                    self.contexts[self.current_context as usize].m_nir_diff0.as_mut().unwrap(),
1853                ) as u8;
1854                item_nir = u8_fold(corr as u32 + (last_item[3] & 255) as u32) as u16;
1855            } else {
1856                item_nir = last_item[3] & 0xff;
1857            }
1858            if (sym & (1 << 1)) != 0 {
1859                corr = self.dec_nir.as_mut().unwrap().decode_symbol(
1860                    self.contexts[self.current_context as usize].m_nir_diff1.as_mut().unwrap(),
1861                ) as u8;
1862                item_nir |= (u8_fold(corr as u32 + (last_item[3] >> 8) as u32) as u16) << 8;
1863            } else {
1864                item_nir |= last_item[3] & 0xff00;
1865            }
1866            // last_item[3] = item_nir;
1867        } else {
1868            item_nir = last_item[3];
1869        }
1870        item.nir = Some(item_nir);
1871    }
1872
1873    fn chunk_sizes<R: Reader>(&mut self, reader: &R) {
1874        // read bytes per layer
1875        self.num_bytes_rgb = reader.uint32_le(None);
1876        self.num_bytes_nir = reader.uint32_le(None);
1877    }
1878}
1879
1880/// Parse LAZ wavepacket 1.4v3
1881#[derive(Debug, Clone)]
1882pub struct LAZwavepacket14v3Reader<T: Reader> {
1883    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
1884    instream_wavepacket: Option<BufferReader>,
1885    dec_wavepacket: Rc<RefCell<ArithmeticDecoder<BufferReader>>>,
1886    changed_wavepacket: bool,
1887    num_bytes_wavepacket: u32,
1888    requested_wavepacket: bool,
1889    bytes: Option<Buffer>,
1890    num_bytes_allocated: u32,
1891    current_context: u32,
1892    contexts: [LASContextWavePacket14<BufferReader>; 4],
1893}
1894impl<T: Reader> LAZwavepacket14v3Reader<T> {
1895    /// Create a new LAZwavepacket14v3Reader
1896    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>, decompress_selective: Option<u32>) -> Self {
1897        let decompress_selective = decompress_selective.unwrap_or(LASZIP_DECOMPRESS_SELECTIVE_ALL);
1898        let mut wavepacket_reader = LAZwavepacket14v3Reader {
1899            dec,
1900            instream_wavepacket: None,
1901            dec_wavepacket: Rc::new(RefCell::new(ArithmeticDecoder::new(
1902                RefCell::new(BufferReader::new(vec![0_u8; 0])).into(),
1903            ))),
1904            changed_wavepacket: false,
1905            num_bytes_wavepacket: 0,
1906            requested_wavepacket: false,
1907            bytes: None,
1908            num_bytes_allocated: 0,
1909            current_context: 0,
1910            contexts: [
1911                LASContextWavePacket14::<BufferReader>::default(),
1912                LASContextWavePacket14::<BufferReader>::default(),
1913                LASContextWavePacket14::<BufferReader>::default(),
1914                LASContextWavePacket14::<BufferReader>::default(),
1915            ],
1916        };
1917        wavepacket_reader.requested_wavepacket =
1918            (decompress_selective & LASZIP_DECOMPRESS_SELECTIVE_WAVEPACKET) != 0;
1919        // mark the four scanner channel contexts as uninitialized
1920        for c in 0..4 {
1921            wavepacket_reader.contexts[c].m_packet_index = None;
1922        }
1923        wavepacket_reader
1924    }
1925
1926    fn create_and_init_models_and_decompressors(&mut self, context: usize, item: &[u8; 29]) {
1927        // first create all entropy models (if needed)
1928        if self.requested_wavepacket {
1929            if self.contexts[context].m_packet_index.is_none() {
1930                self.contexts[context].m_packet_index = Some(ArithmeticModel::new(256, false));
1931                self.contexts[context].m_offset_diff[0] = Some(ArithmeticModel::new(4, false));
1932                self.contexts[context].m_offset_diff[1] = Some(ArithmeticModel::new(4, false));
1933                self.contexts[context].m_offset_diff[2] = Some(ArithmeticModel::new(4, false));
1934                self.contexts[context].m_offset_diff[3] = Some(ArithmeticModel::new(4, false));
1935                self.contexts[context].ic_offset_diff = Some(IntegerCompressor::new(
1936                    self.dec_wavepacket.clone(),
1937                    Some(32),
1938                    None,
1939                    None,
1940                    None,
1941                ));
1942                self.contexts[context].ic_packet_size = Some(IntegerCompressor::new(
1943                    self.dec_wavepacket.clone(),
1944                    Some(32),
1945                    None,
1946                    None,
1947                    None,
1948                ));
1949                self.contexts[context].ic_return_point = Some(IntegerCompressor::new(
1950                    self.dec_wavepacket.clone(),
1951                    Some(32),
1952                    None,
1953                    None,
1954                    None,
1955                ));
1956                self.contexts[context].ic_xyz = Some(IntegerCompressor::new(
1957                    self.dec_wavepacket.clone(),
1958                    Some(32),
1959                    Some(3),
1960                    None,
1961                    None,
1962                ));
1963            }
1964            // then init entropy models
1965            self.contexts[context].m_packet_index.as_mut().unwrap().init(None);
1966            self.contexts[context].m_offset_diff[0].as_mut().unwrap().init(None);
1967            self.contexts[context].m_offset_diff[1].as_mut().unwrap().init(None);
1968            self.contexts[context].m_offset_diff[2].as_mut().unwrap().init(None);
1969            self.contexts[context].m_offset_diff[3].as_mut().unwrap().init(None);
1970            self.contexts[context].ic_offset_diff.as_mut().unwrap().init_decompressor();
1971            self.contexts[context].ic_packet_size.as_mut().unwrap().init_decompressor();
1972            self.contexts[context].ic_return_point.as_mut().unwrap().init_decompressor();
1973            self.contexts[context].ic_xyz.as_mut().unwrap().init_decompressor();
1974        }
1975        // init current context from item
1976        self.contexts[context].last_diff32 = 0;
1977        self.contexts[context].sym_last_offset_diff = 0;
1978        self.contexts[context].last_item = *item;
1979        self.contexts[context].unused = false;
1980    }
1981}
1982impl<T: Reader> ItemReader for LAZwavepacket14v3Reader<T> {
1983    fn init<R: Reader>(&mut self, item: &R, point: &mut LASPoint, context: &mut u32) {
1984        {
1985            let dec = &mut self.dec.borrow_mut();
1986            let reader = dec.reader.borrow();
1987            // on the first init create instreams and decoders
1988            if self.instream_wavepacket.is_none() {
1989                // create decoders
1990                // TODO: Do we need this?
1991                //   self.dec_wavepacket = Some(ArithmeticDecoder::new(reader));
1992            }
1993            // make sure the buffer is sufficiently large
1994            if self.num_bytes_wavepacket > self.num_bytes_allocated {
1995                self.num_bytes_allocated = self.num_bytes_wavepacket;
1996            }
1997            // load the requested bytes and init the corresponding instreams an decoders
1998            if self.requested_wavepacket {
1999                if self.num_bytes_wavepacket != 0 {
2000                    let buf = reader.seek_slice(self.num_bytes_wavepacket as usize);
2001                    let br = BufferReader::new(buf.clone());
2002                    let buf_reader = Rc::new(RefCell::new(br.clone()));
2003                    self.bytes = Some(buf.into());
2004                    self.instream_wavepacket = Some(br);
2005                    let mut ad = ArithmeticDecoder::new(buf_reader.clone());
2006                    ad.init(true);
2007                    self.dec_wavepacket = Rc::new(RefCell::new(ad));
2008                    self.changed_wavepacket = true;
2009                } else {
2010                    self.instream_wavepacket = None;
2011                    self.changed_wavepacket = false;
2012                }
2013            } else {
2014                if self.num_bytes_wavepacket != 0 {
2015                    reader.seek(reader.tell() + self.num_bytes_wavepacket as u64);
2016                }
2017                self.changed_wavepacket = false;
2018            }
2019            // mark the four scanner channel contexts as unused
2020            for c in 0..4 {
2021                self.contexts[c].unused = true;
2022            }
2023            // set scanner channel as current context
2024            self.current_context = *context; // all other items use context set by POINT14 reader
2025        }
2026        // create and init models and decompressors
2027        let item: [u8; 29] = item.seek_slice(29).try_into().unwrap();
2028        point.inject_wave_packet(&BufferReader::new(item.to_vec()), 0);
2029        self.create_and_init_models_and_decompressors(self.current_context as usize, &item);
2030    }
2031
2032    fn read(&mut self, item: &mut LASPoint, context: &mut u32) {
2033        // get last
2034        if item.wave_packet.is_none() {
2035            item.wave_packet = Some(WavePacket::default());
2036        }
2037        let curr_item = item.wave_packet.as_mut().unwrap();
2038        let last_item_val = self.contexts[self.current_context as usize].last_item;
2039        let mut last_item = WavePacket::from_reader(&BufferReader::new(last_item_val.to_vec()), 0);
2040        // check for context switch
2041        if self.current_context != *context {
2042            self.current_context = *context; // all other items use context set by POINT14 reader
2043            if self.contexts[self.current_context as usize].unused {
2044                self.create_and_init_models_and_decompressors(
2045                    self.current_context as usize,
2046                    &last_item_val,
2047                );
2048                last_item = WavePacket::from_reader(
2049                    &BufferReader::new(
2050                        self.contexts[self.current_context as usize].last_item.to_vec(),
2051                    ),
2052                    0,
2053                );
2054            }
2055        }
2056
2057        // decompress
2058        if self.changed_wavepacket {
2059            // INDEX does not matter
2060            // curr_item.index = self.dec_wavepacket.decode_symbol(
2061            //     self.contexts[self.current_context as usize].m_packet_index.unwrap(),
2062            // );
2063
2064            self.contexts[self.current_context as usize].sym_last_offset_diff =
2065                self.dec_wavepacket.borrow_mut().decode_symbol(
2066                    self.contexts[self.current_context as usize].m_offset_diff[self.contexts
2067                        [self.current_context as usize]
2068                        .sym_last_offset_diff
2069                        as usize]
2070                        .as_mut()
2071                        .unwrap(),
2072                );
2073
2074            if self.contexts[self.current_context as usize].sym_last_offset_diff == 0 {
2075                curr_item.offset = last_item.offset;
2076            } else if self.contexts[self.current_context as usize].sym_last_offset_diff == 1 {
2077                curr_item.offset = last_item.offset + last_item.length as u64;
2078            } else if self.contexts[self.current_context as usize].sym_last_offset_diff == 2 {
2079                self.contexts[self.current_context as usize].last_diff32 = self.contexts
2080                    [self.current_context as usize]
2081                    .ic_offset_diff
2082                    .as_mut()
2083                    .unwrap()
2084                    .decompress(self.contexts[self.current_context as usize].last_diff32, 0);
2085                curr_item.offset = last_item.offset
2086                    + self.contexts[self.current_context as usize].last_diff32 as u64;
2087            } else {
2088                curr_item.offset = self.dec_wavepacket.borrow_mut().read_int64();
2089            }
2090
2091            curr_item.length = self.contexts[self.current_context as usize]
2092                .ic_packet_size
2093                .as_mut()
2094                .unwrap()
2095                .decompress(last_item.length as i32, 0) as u32;
2096            curr_item.return_point = self.contexts[self.current_context as usize]
2097                .ic_return_point
2098                .as_mut()
2099                .unwrap()
2100                .decompress(last_item.return_point as i32, 0)
2101                as f32;
2102            curr_item.x_t = self.contexts[self.current_context as usize]
2103                .ic_xyz
2104                .as_mut()
2105                .unwrap()
2106                .decompress(last_item.x_t as i32, 0) as f32;
2107            curr_item.y_t = self.contexts[self.current_context as usize]
2108                .ic_xyz
2109                .as_mut()
2110                .unwrap()
2111                .decompress(last_item.y_t as i32, 1) as f32;
2112            curr_item.z_t = self.contexts[self.current_context as usize]
2113                .ic_xyz
2114                .as_mut()
2115                .unwrap()
2116                .decompress(last_item.z_t as i32, 2) as f32;
2117
2118            self.contexts[self.current_context as usize].last_item =
2119                curr_item.to_bytes().try_into().unwrap();
2120            // curr_item.copyTo(last_item.data, 29);
2121        }
2122    }
2123
2124    fn chunk_sizes<R: Reader>(&mut self, reader: &R) {
2125        self.num_bytes_wavepacket = reader.uint32_le(None);
2126    }
2127}
2128
2129/// Parse LAZ RGB 1.4v3
2130#[derive(Debug, Clone)]
2131pub struct LAZbyte14v3Reader<T: Reader> {
2132    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
2133    size: u32,
2134    instream_bytes: Vec<Option<Rc<RefCell<BufferReader>>>>,
2135    dec_bytes: Vec<Option<ArithmeticDecoder<BufferReader>>>,
2136    num_bytes_bytes: Vec<u32>,
2137    changed_bytes: Vec<bool>,
2138    requested_bytes: Vec<bool>,
2139    bytes: Option<Vec<u8>>,
2140    num_bytes_allocated: u32,
2141    current_context: u32,
2142    contexts: [LAZContextByte14; 4],
2143}
2144impl<T: Reader> LAZbyte14v3Reader<T> {
2145    /// Create a new LAZbyte14v3Reader
2146    pub fn new(
2147        dec: Rc<RefCell<ArithmeticDecoder<T>>>,
2148        size: u32,
2149        decompress_selective: Option<u32>,
2150    ) -> Self {
2151        let decompress_selective = decompress_selective.unwrap_or(LASZIP_DECOMPRESS_SELECTIVE_ALL);
2152        let mut byte_reader = Self {
2153            dec,
2154            size,
2155            instream_bytes: vec![],
2156            dec_bytes: vec![],
2157            num_bytes_bytes: vec![],
2158            changed_bytes: vec![],
2159            requested_bytes: vec![],
2160            bytes: None,
2161            num_bytes_allocated: 0,
2162            current_context: 0,
2163            contexts: [
2164                LAZContextByte14::default(),
2165                LAZContextByte14::default(),
2166                LAZContextByte14::default(),
2167                LAZContextByte14::default(),
2168            ],
2169        };
2170
2171        byte_reader.num_bytes_bytes = vec![0; size as usize];
2172        byte_reader.changed_bytes = vec![false; size as usize];
2173        byte_reader.requested_bytes = vec![false; size as usize];
2174
2175        for i in 0..size as usize {
2176            byte_reader.num_bytes_bytes[i] = 0;
2177            byte_reader.changed_bytes[i] = false;
2178
2179            if i > 15 {
2180                // currently only the first 16 extra bytes can be selectively decompressed
2181                byte_reader.requested_bytes[i] = true;
2182            } else {
2183                byte_reader.requested_bytes[i] =
2184                    (decompress_selective & (LASZIP_DECOMPRESS_SELECTIVE_BYTE0 << i)) != 0;
2185            }
2186        }
2187
2188        // mark the four scanner channel contexts as uninitialized
2189        for c in 0..4 {
2190            byte_reader.contexts[c].m_bytes = vec![];
2191        }
2192        byte_reader.current_context = 0;
2193
2194        byte_reader
2195    }
2196
2197    fn create_and_init_models_and_decompressors(&mut self, context: usize, item: &[u8]) {
2198        // first create all entropy models and last items (if needed)
2199        if self.contexts[context].m_bytes.is_empty() {
2200            for i in 0..self.size as usize {
2201                let mut model = ArithmeticModel::new(256, false);
2202                model.init(None);
2203                self.contexts[context].m_bytes[i] = model;
2204            }
2205            // create last item
2206            self.contexts[context].last_item = Buffer::new(vec![0; self.size as usize]);
2207        }
2208        // then init entropy models
2209        for i in 0..self.size as usize {
2210            self.contexts[context].m_bytes[i].init(None);
2211        }
2212        // init current context from item
2213        self.contexts[context].last_item.copy_from_slice(0, item);
2214
2215        self.contexts[context].unused = false;
2216    }
2217}
2218impl<T: Reader> ItemReader for LAZbyte14v3Reader<T> {
2219    fn init<R: Reader>(&mut self, item: &R, _point: &mut LASPoint, context: &mut u32) {
2220        {
2221            let dec = &mut self.dec.borrow_mut();
2222            let reader = dec.reader.borrow();
2223            // on the first init create instreams and decoders
2224            if self.instream_bytes.is_empty() {
2225                // create instream pointer array
2226                self.instream_bytes = vec![None; self.size as usize];
2227                // create decoder pointer array
2228                self.dec_bytes = vec![None; self.size as usize];
2229                // create layer decoders
2230                // TODO: Is this needed? It brakes the simplicity
2231                // for i in 0..self.size as usize {
2232                //     self.dec_bytes[i] = Some(ArithmeticDecoder::new(reader.clone()));
2233                // }
2234            }
2235            // how many bytes do we need to read
2236            let mut num_bytes = 0;
2237            for i in 0..self.size as usize {
2238                if self.requested_bytes[i] {
2239                    num_bytes += self.num_bytes_bytes[i];
2240                }
2241            }
2242            // make sure the buffer is sufficiently large
2243            if num_bytes > self.num_bytes_allocated {
2244                self.num_bytes_allocated = num_bytes;
2245            }
2246            // load the requested bytes and init the corresponding instreams an decoders
2247            // num_bytes = 0;
2248            for i in 0..self.size as usize {
2249                if self.requested_bytes[i] {
2250                    if self.num_bytes_bytes[i] != 0 {
2251                        let buf = reader.seek_slice(self.num_bytes_bytes[i] as usize);
2252                        self.bytes = Some(buf.clone());
2253                        let buf_reader = Rc::new(RefCell::new(BufferReader::new(buf)));
2254                        self.instream_bytes[i] = Some(buf_reader.clone());
2255                        let mut decoder = ArithmeticDecoder::new(buf_reader);
2256                        decoder.init(true);
2257                        self.dec_bytes[i] = Some(decoder);
2258                        // num_bytes += self.num_bytes_bytes[i];
2259                        self.changed_bytes[i] = true;
2260                    } else {
2261                        self.dec_bytes[i] = None;
2262                        self.changed_bytes[i] = false;
2263                    }
2264                } else {
2265                    if self.num_bytes_bytes[i] != 0 {
2266                        reader.seek(reader.tell() + self.num_bytes_bytes[i] as u64);
2267                    }
2268                    self.changed_bytes[i] = false;
2269                }
2270            }
2271            // mark the four scanner channel contexts as unused
2272            for c in 0..4 {
2273                self.contexts[c].unused = true;
2274            }
2275            // set scanner channel as current context
2276            self.current_context = *context; // all other items use context set by POINT14 reader
2277        }
2278        // create and init models and decompressors
2279        self.create_and_init_models_and_decompressors(
2280            self.current_context as usize,
2281            &item.seek_slice(self.size as usize),
2282        );
2283    }
2284
2285    fn read(&mut self, _item: &mut LASPoint, context: &mut u32) {
2286        // get last
2287        let mut last_item: &mut Buffer =
2288            &mut self.contexts[self.current_context as usize].last_item;
2289        // check for context switch
2290        if self.current_context != *context {
2291            self.current_context = *context; // all other items use context set by POINT14 reader
2292            if self.contexts[self.current_context as usize].unused {
2293                let slice = last_item.buf().to_vec();
2294                self.create_and_init_models_and_decompressors(
2295                    self.current_context as usize,
2296                    &slice,
2297                );
2298                last_item = &mut self.contexts[self.current_context as usize].last_item;
2299            }
2300        }
2301        // decompress
2302        for i in 0..self.size as usize {
2303            if self.changed_bytes[i] {
2304                let value = last_item.get_u8_at(i) as u32
2305                    + self.dec_bytes[i].as_mut().unwrap().decode_symbol(
2306                        &mut self.contexts[self.current_context as usize].m_bytes[i],
2307                    );
2308                // item.setUint8(i, u8_fold(value));
2309                last_item.set_u8_at(i, u8_fold(value));
2310            } else {
2311                // item.setUint8(i, last_item.get_u8_at(i));
2312            }
2313        }
2314    }
2315
2316    fn chunk_sizes<R: Reader>(&mut self, reader: &R) {
2317        for i in 0..self.size as usize {
2318            self.num_bytes_bytes[i] = reader.uint32_le(None);
2319        }
2320    }
2321}