diff --git a/Cargo.toml b/Cargo.toml index cd87c01..3db3078 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ byteorder = "1.2" lzw = "0.10" num-derive = "0.3" num-traits = "0.2" +libflate = "0.1" # TODO: Put behind a feature? [dev-dependencies] tempfile = "3.0" diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index dcda365..0aab11f 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -7,7 +7,7 @@ use {ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError}; use self::ifd::Directory; -use self::stream::{ByteOrder, EndianReader, LZWReader, PackBitsReader, SmartReader}; +use self::stream::{ByteOrder, EndianReader, LZWReader, DeflateReader, PackBitsReader, SmartReader}; pub mod ifd; mod stream; @@ -579,6 +579,12 @@ impl Decoder { )?; (bytes, Box::new(reader)) } + CompressionMethod::OldDeflate => { + let (bytes, reader) = DeflateReader::new( + &mut self.reader, + max_uncompressed_length)?; + (bytes, Box::new(reader)) + } method => { return Err(TiffError::UnsupportedError( TiffUnsupportedError::UnsupportedCompressionMethod(method), diff --git a/src/decoder/stream.rs b/src/decoder/stream.rs index 46d7d10..f1d3c31 100644 --- a/src/decoder/stream.rs +++ b/src/decoder/stream.rs @@ -3,6 +3,7 @@ use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; use lzw; use std::io::{self, Read, Seek}; +use libflate::zlib; /// Byte order of the TIFF file. #[derive(Clone, Copy, Debug)] @@ -67,6 +68,40 @@ pub trait EndianReader: Read { } } +/// Reader that decompresses DEFLATE streams +pub struct DeflateReader { + buffer: io::Cursor>, + byte_order: ByteOrder, +} + +impl DeflateReader { + pub fn new( + reader: &mut SmartReader, + max_uncompressed_length: usize, + ) -> io::Result<(usize, Self)> { + let byte_order = reader.byte_order; + let mut decoder = zlib::Decoder::new(reader)?; + let mut uncompressed = Vec::with_capacity(max_uncompressed_length); + let bytes_read = decoder.read_to_end(&mut uncompressed)?; + Ok((bytes_read, Self { + byte_order, + buffer: io::Cursor::new(uncompressed), + })) + } +} + +impl Read for DeflateReader { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.buffer.read(buf) + } +} + +impl EndianReader for DeflateReader { + fn byte_order(&self) -> ByteOrder { + self.byte_order + } +} + /// Reader that decompresses LZW streams pub struct LZWReader { buffer: io::Cursor>, diff --git a/src/lib.rs b/src/lib.rs index 8ed1d25..64a31cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ extern crate byteorder; extern crate lzw; +extern crate libflate; #[macro_use] extern crate num_derive; extern crate num_traits;