Skip to content

Commit f4e27ea

Browse files
authored
feat: Add Zstd compression support and corresponding tests (#157)
- Introduced a new ZstdDecoder for handling Zstd compression in TIFF files. - Updated the DecoderRegistry to include the ZstdDecoder. - Added a test case for Zstd compression.
1 parent 6c962b6 commit f4e27ea

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ reqwest = { version = "0.12", default-features = false, optional = true }
2121
thiserror = "1"
2222
tokio = { version = "1.43.0", default-features = false, features = ["sync"] }
2323
weezl = "0.1.0"
24+
zstd = "0.13"
2425

2526
[dev-dependencies]
2627
object_store = { version = "0.12", features = ["http"] }

src/decoder.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@ impl AsMut<HashMap<CompressionMethod, Box<dyn Decoder>>> for DecoderRegistry {
3838

3939
impl Default for DecoderRegistry {
4040
fn default() -> Self {
41-
let mut registry = HashMap::with_capacity(5);
41+
let mut registry = HashMap::with_capacity(6);
4242
registry.insert(CompressionMethod::None, Box::new(UncompressedDecoder) as _);
4343
registry.insert(CompressionMethod::Deflate, Box::new(DeflateDecoder) as _);
4444
registry.insert(CompressionMethod::OldDeflate, Box::new(DeflateDecoder) as _);
4545
registry.insert(CompressionMethod::LZW, Box::new(LZWDecoder) as _);
4646
registry.insert(CompressionMethod::ModernJPEG, Box::new(JPEGDecoder) as _);
47+
registry.insert(CompressionMethod::ZSTD, Box::new(ZstdDecoder) as _);
4748
Self(registry)
4849
}
4950
}
@@ -125,6 +126,24 @@ impl Decoder for UncompressedDecoder {
125126
}
126127
}
127128

129+
/// A decoder for the Zstd compression method.
130+
#[derive(Debug, Clone)]
131+
pub struct ZstdDecoder;
132+
133+
impl Decoder for ZstdDecoder {
134+
fn decode_tile(
135+
&self,
136+
buffer: Bytes,
137+
_photometric_interpretation: PhotometricInterpretation,
138+
_jpeg_tables: Option<&[u8]>,
139+
) -> AsyncTiffResult<Bytes> {
140+
let mut decoder = zstd::Decoder::new(Cursor::new(buffer))?;
141+
let mut buf = Vec::new();
142+
decoder.read_to_end(&mut buf)?;
143+
Ok(buf.into())
144+
}
145+
}
146+
128147
// https://github.com/image-rs/image-tiff/blob/3bfb43e83e31b0da476832067ada68a82b378b7b/src/decoder/image.rs#L389-L450
129148
fn decode_modern_jpeg(
130149
buf: Bytes,

tests/image_tiff/decode_images.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,17 @@ async fn test_int16_rgb() {
224224
assert!(ifd.bits_per_sample().iter().all(|x| *x == 16));
225225
}
226226

227+
#[tokio::test]
228+
async fn test_zstd_compression() {
229+
let tiff = open_tiff("int16_zstd.tif").await;
230+
let ifd = &tiff.ifds()[0];
231+
assert!(matches!(
232+
ifd.photometric_interpretation(),
233+
PhotometricInterpretation::BlackIsZero
234+
));
235+
assert!(ifd.bits_per_sample().iter().all(|x| *x == 16));
236+
}
237+
227238
#[tokio::test]
228239
async fn test_string_tags() {
229240
// these files have null-terminated strings for their Software tag. One has extra bytes after

0 commit comments

Comments
 (0)