Merge pull request #407 from aarshivv/feat/old-style-lzw
feat: decode old-style (pre-TIFF-6.0) LZW streams
This commit is contained in:
3 files changed
+35
-7
No files matched your search
+24
-6
@@ -141,14 +141,32 @@ pub struct LZWReader<R: Read> {
|
|||||||
impl<R: Read> LZWReader<R> {
|
impl<R: Read> LZWReader<R> {
|
||||||
/// Wraps a reader
|
/// Wraps a reader
|
||||||
pub fn new(reader: R, compressed_length: usize) -> LZWReader<R> {
|
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)
|
weezl::decode::Configuration::with_tiff_size_switch(weezl::BitOrder::Msb, 8)
|
||||||
.with_yield_on_full_buffer(true);
|
}
|
||||||
|
.with_yield_on_full_buffer(true);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
reader: BufReader::with_capacity(
|
reader: buffered,
|
||||||
(32 * 1024).min(compressed_length),
|
|
||||||
reader.take(u64::try_from(compressed_length).unwrap()),
|
|
||||||
),
|
|
||||||
decoder: configuration.build(),
|
decoder: configuration.build(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1060,6 +1060,16 @@ fn test_gray_u12_hpredict() {
|
|||||||
test_image_sum_u16("hpredict-1c-12b.tiff", ColorType::Gray(12), 11000);
|
test_image_sum_u16("hpredict-1c-12b.tiff", ColorType::Gray(12), 11000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- Old-style LZW ----
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_old_style_lzw() {
|
||||||
|
// Pre-TIFF-6.0 "old-style" LZW: LSB-first bit order with no early-change size
|
||||||
|
// switch. Auto-detected from the stream (first byte 0x00, second byte odd).
|
||||||
|
// Same image as libtiffpic's quad-lzw.tif; the decoded pixels must match.
|
||||||
|
test_image_sum_u8("quad-lzw-compat.tiff", ColorType::RGB(8), 21048924);
|
||||||
|
}
|
||||||
|
|
||||||
// ---- TransparencyMask ----
|
// ---- TransparencyMask ----
|
||||||
|
|
||||||
/// Build a minimal uncompressed 2x2 TIFF in memory, in the requested byte order,
|
/// Build a minimal uncompressed 2x2 TIFF in memory, in the requested byte order,
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ const FILES: &[(&str, Option<u32>)] = &[
|
|||||||
("tests/libtiffpic/oxford.tif", Some(0x355d2e3e)),
|
("tests/libtiffpic/oxford.tif", Some(0x355d2e3e)),
|
||||||
("tests/libtiffpic/pc260001.tif", Some(0xdb56b753)),
|
("tests/libtiffpic/pc260001.tif", Some(0xdb56b753)),
|
||||||
("tests/libtiffpic/quad-jpeg.tif", Some(0xcba22475)),
|
("tests/libtiffpic/quad-jpeg.tif", Some(0xcba22475)),
|
||||||
("tests/libtiffpic/quad-lzw.tif", Some(0)), // invalid LZW stream
|
("tests/libtiffpic/quad-lzw.tif", Some(0x6055f9ee)), // old-style (LSB) LZW
|
||||||
("tests/libtiffpic/quad-tile.tif", Some(0x6055f9ee)),
|
("tests/libtiffpic/quad-tile.tif", Some(0x6055f9ee)),
|
||||||
("tests/libtiffpic/README", None),
|
("tests/libtiffpic/README", None),
|
||||||
("tests/libtiffpic/smallliz.tif", Some(0)), // unsupported YCbCr chroma subsampling
|
("tests/libtiffpic/smallliz.tif", Some(0)), // unsupported YCbCr chroma subsampling
|
||||||
|
|||||||
Reference in new issue
Block a user