geotiff_rs/parser/
compression.rs1use weezl::{decode::Decoder, BitOrder, LzwStatus};
2
3use super::TiffParserError;
4
5pub trait Decompressor {
6 fn decompress(&mut self, bytes: &[u8], size: usize) -> Result<Vec<u8>, TiffParserError>;
7}
8
9const COMPRESSION_NONE: u16 = 1;
10const COMPRESSION_LZW: u16 = 5;
11
12pub fn create_decompressor(compression: u16) -> Result<Box<dyn Decompressor>, TiffParserError> {
13 match compression {
14 COMPRESSION_NONE => Ok(Box::new(DummyDecompressor)),
15 COMPRESSION_LZW => Ok(Box::new(Decoder::with_tiff_size_switch(BitOrder::Msb, 8))),
16 compression => Err(TiffParserError::UnknownCompression(compression)),
17 }
18}
19
20struct DummyDecompressor;
21
22impl Decompressor for DummyDecompressor {
23 fn decompress(&mut self, bytes: &[u8], size: usize) -> Result<Vec<u8>, TiffParserError> {
24 Ok(bytes[..size].to_vec())
25 }
26}
27
28impl Decompressor for Decoder {
29 fn decompress(&mut self, bytes: &[u8], size: usize) -> Result<Vec<u8>, TiffParserError> {
30 let mut result = vec![0; size];
31 let mut consumed_in = 0;
32 let mut consumed_out = 0;
33 loop {
34 let decode_result =
35 self.decode_bytes(&bytes[consumed_in..], &mut result[consumed_out..]);
36 consumed_in += decode_result.consumed_in;
37 consumed_out += decode_result.consumed_out;
38 match decode_result.status {
39 Ok(LzwStatus::Ok) => {}
40 Ok(LzwStatus::NoProgress) => {
41 return Ok(result);
42 }
43 Ok(LzwStatus::Done) => {
44 return Ok(result);
45 }
46 Err(err) => {
47 eprintln!(
48 "error {}; size = {}, consumed_out = {}",
49 err, size, consumed_out
50 );
51 if consumed_out >= size {
52 return Ok(result);
53 } else {
54 return Err(err.into());
55 }
56 }
57 }
58 if consumed_out >= size {
59 return Ok(result);
60 }
61 }
62 }
63}