use std::fs::File; use std::io::{BufReader, Cursor}; use laz::las::file::SimpleReader; use laz::{LasZipCompressor, LasZipDecompressor, LazItemRecordBuilder, LazVlrBuilder}; fn organize_as_variable_size_chunks( raw_points: &[u8], point_size: usize, chunks_sizes: &[usize], ) -> Vec> { let mut chunks = Vec::>::with_capacity(chunks_sizes.len()); for chunk_size in chunks_sizes { let mut chunk = vec![0u8; chunk_size * point_size]; chunk.copy_from_slice(&raw_points[..chunk_size * point_size]); chunks.push(chunk); } chunks } fn check_chunks(concatenated_chunks: &[u8], chunks: &Vec>) { let mut start = 0usize; let mut end = 0usize; for chunk in chunks { end += chunk.len(); assert_eq!(&concatenated_chunks[start..end], chunk.as_slice()); start = end; } } /// Test variable chunk size compression by first compressing data with /// variable size chunks enabled, then checking if the decompression gives back /// the expected points. /// /// This test both the compression and decompression. #[test] fn test_variable_size_chunks() { // 1. Data preparation: read a LAS file to pick points that we are going to use // in this test. let las_file = BufReader::new(File::open("tests/data/point-time-color.las").unwrap()); let mut las_reader = SimpleReader::new(las_file).unwrap(); let mut las_points_bytes = Vec::::new(); las_reader.read_to_end(&mut las_points_bytes).unwrap(); let point_size = las_reader.header.point_size as usize; let chunk_sizes = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]; let chunks = organize_as_variable_size_chunks(&las_points_bytes, point_size, &chunk_sizes); // 2. Compress into multiple chunks of variable size. let laz_vlr = LazVlrBuilder::new( LazItemRecordBuilder::default_for_point_format_id(las_reader.header.point_format_id, 0) .unwrap(), ) .with_variable_chunk_size() .build(); let mut compressed_output = Cursor::new(Vec::::new()); { let mut compressor = LasZipCompressor::new(&mut compressed_output, laz_vlr.clone()).unwrap(); compressor.compress_chunks(&chunks).unwrap(); compressor.done().unwrap(); } // 3. Decompress what we just compressed and see if we get the same points // that we gave to the compressor compressed_output.set_position(0); let mut decompressor = LasZipDecompressor::new(&mut compressed_output, laz_vlr).unwrap(); let num_points_compressed = chunk_sizes.iter().sum::(); let mut points_out = vec![0u8; point_size * num_points_compressed]; decompressor.decompress_many(&mut points_out).unwrap(); check_chunks(&points_out, &chunks); } /// Test variable chunk size compression by first compressing data with /// variable size chunks enabled, then checking if the decompression gives back /// the expected points. /// /// This **only** test the compression #[cfg(feature = "parallel")] #[test] fn test_variable_size_chunks_parallel_compression() { use laz::ParLasZipCompressor; // 1. Data preparation: read a LAS file to pick points that we are going to use // in this test. let las_file = BufReader::new(File::open("tests/data/point-time-color.las").unwrap()); let mut las_reader = SimpleReader::new(las_file).unwrap(); let mut las_points_bytes = Vec::::new(); las_reader.read_to_end(&mut las_points_bytes).unwrap(); let point_size = las_reader.header.point_size as usize; let chunk_sizes = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]; let chunks = organize_as_variable_size_chunks(&las_points_bytes, point_size, &chunk_sizes); // 2. Compress into multiple chunks of variable size. let laz_vlr = LazVlrBuilder::default() .with_point_format(las_reader.header.point_format_id, 0) .unwrap() .with_variable_chunk_size() .build(); let mut compressed_output = Cursor::new(Vec::::new()); { let mut compressor = ParLasZipCompressor::new(&mut compressed_output, laz_vlr.clone()).unwrap(); compressor.compress_chunks(&chunks).unwrap(); compressor.done().unwrap(); } // 3. Decompress what we just compressed and see if we get the same points // that we gave to the compressor compressed_output.set_position(0); let mut decompressor = LasZipDecompressor::new(&mut compressed_output, laz_vlr).unwrap(); let num_points_compressed = chunk_sizes.iter().sum::(); let mut points_out = vec![0u8; point_size * num_points_compressed]; decompressor.decompress_many(&mut points_out).unwrap(); check_chunks(&points_out, &chunks); } /// This **only** test the compression #[cfg(feature = "parallel")] #[test] fn test_variable_size_chunks_parallel_decompression() { use laz::ParLasZipDecompressor; // 1. Data preparation: read a LAS file to pick points that we are going to use // in this test. let las_file = BufReader::new(File::open("tests/data/point-time-color.las").unwrap()); let mut las_reader = SimpleReader::new(las_file).unwrap(); let mut las_points_bytes = Vec::::new(); las_reader.read_to_end(&mut las_points_bytes).unwrap(); let point_size = las_reader.header.point_size as usize; let chunk_sizes = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]; let chunks = organize_as_variable_size_chunks(&las_points_bytes, point_size, &chunk_sizes); // 2. Compress into multiple chunks of variable size. let laz_vlr = LazVlrBuilder::default() .with_point_format(las_reader.header.point_format_id, 0) .unwrap() .with_variable_chunk_size() .build(); let mut compressed_output = Cursor::new(Vec::::new()); { let mut compressor = LasZipCompressor::new(&mut compressed_output, laz_vlr.clone()).unwrap(); compressor.compress_chunks(&chunks).unwrap(); compressor.done().unwrap(); } // 3. Decompress what we just compressed and see if we get the same points // that we gave to the compressor compressed_output.set_position(0); let mut decompressor = ParLasZipDecompressor::new(&mut compressed_output, laz_vlr).unwrap(); let num_points_compressed = chunk_sizes.iter().sum::(); let mut points_out = vec![0u8; point_size * num_points_compressed]; decompressor.decompress_many(&mut points_out).unwrap(); check_chunks(&points_out, &chunks); }