feat: decode old-style (pre-TIFF-6.0) LZW streams

This commit is contained in:
aarshivv committed 2026-07-25 12:45:40 +05:30
1 parent f28f5fc830
commit c27fd94e1d
3 files changed
+35 -7

No files matched your search

+24 -6
View File
@@ -141,14 +141,32 @@ pub struct LZWReader<R: Read> {
impl<R: Read> LZWReader<R> {
/// Wraps a reader
pub fn new(reader: R, compressed_length: usize) -> LZWReader<R> {
let configuration =
let mut buffered = BufReader::with_capacity(
(32 * 1024).min(compressed_length),
reader.take(u64::try_from(compressed_length).unwrap()),
);
// `Compression = 5` covers both the current LZW variant and the pre-TIFF-6.0
// "old-style" one, with no tag to distinguish them. New-style is MSB-first with
// the "early change" code-size switch, and its stream begins with the Clear code
// (256) -> first byte 0x80. Old-style is LSB-first *without* the early change
// (GIF-style increment timing), and begins with 0x00 followed by a byte with bit
// 0 set. This is the heuristic libtiff uses to select its compatibility decoder;
// on a short/failed peek we default to the modern variant.
let old_style = matches!(
buffered.fill_buf(),
Ok(head) if head.len() >= 2 && head[0] == 0x00 && head[1] & 0x01 != 0
);
let configuration = if old_style {
weezl::decode::Configuration::new(weezl::BitOrder::Lsb, 8)
} else {
weezl::decode::Configuration::with_tiff_size_switch(weezl::BitOrder::Msb, 8)
.with_yield_on_full_buffer(true);
}
.with_yield_on_full_buffer(true);
Self {
reader: BufReader::with_capacity(
(32 * 1024).min(compressed_length),
reader.take(u64::try_from(compressed_length).unwrap()),
),
reader: buffered,
decoder: configuration.build(),
}
}