diff --git a/Cargo.toml b/Cargo.toml index d61ef4f..ab2b849 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ exclude = ["tests/images/*", "tests/fuzz_images/*"] half = { version = "2.4.1" } quick-error = "2.0.1" +fax = { version = "0.2.2", optional = true } flate2 = { version = "1.0.20", optional = true } weezl = { version = "0.1.10", optional = true } zstd = { version = "0.13", optional = true } diff --git a/src/decoder/image.rs b/src/decoder/image.rs index bff237a..5da841a 100644 --- a/src/decoder/image.rs +++ b/src/decoder/image.rs @@ -381,6 +381,7 @@ impl Image { } fn create_reader<'r, R: 'r + Read>( + &self, reader: R, compression_method: CompressionMethod, compressed_length: u64, @@ -452,6 +453,25 @@ impl Image { Box::new(Cursor::new(data)) } + CompressionMethod::Fax4 => { + let width = u16::try_from(self.width)?; + let height = u16::try_from(self.height)?; + let mut out: Vec = Vec::with_capacity(usize::from(width) * usize::from(height)); + + let mut buffer = Vec::with_capacity(usize::try_from(compressed_length)?); + reader.take(compressed_length).read_to_end(&mut buffer)?; + + // all extant tiff/fax4 decoders I've found always assume that the photometric interpretation + // is `WhiteIsZero`, ignoring the tag. ImageMagick appears to generate fax4-encoded tiffs + // with the tag incorrectly set to `BlackIsZero`. + fax::decoder::decode_g4(buffer.into_iter(), width, Some(height), |transitions| { + out.extend(fax::decoder::pels(transitions, width).map(|c| match c { + fax::Color::Black => 255, + fax::Color::White => 0, + })) + }); + Box::new(Cursor::new(out)) + } method => { return Err(TiffError::UnsupportedError( TiffUnsupportedError::UnsupportedCompressionMethod(method), @@ -653,7 +673,7 @@ impl Image { assert!(output_row_stride >= data_row_bytes); assert!(buf.len() >= output_row_stride * (data_dims.1 as usize - 1) + data_row_bytes); - let mut reader = Self::create_reader( + let mut reader = self.create_reader( reader, compression_method, *compressed_bytes, diff --git a/tests/decode_images.rs b/tests/decode_images.rs index d7e4c31..1cb7b7c 100644 --- a/tests/decode_images.rs +++ b/tests/decode_images.rs @@ -672,3 +672,9 @@ fn bytes_gray_f32() { byte_order_u32, ); } + +#[test] +#[cfg(feature = "fax")] +fn test_fax4() { + test_image_sum_u8("fax4.tiff", ColorType::Gray(1), 62384985); +} diff --git a/tests/images/fax4.tiff b/tests/images/fax4.tiff new file mode 100644 index 0000000..e74dc8a Binary files /dev/null and b/tests/images/fax4.tiff differ