diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 711293c..ac8694c 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -3,7 +3,9 @@ use std::collections::HashMap; use std::convert::TryFrom; use std::io::{self, Read, Seek}; -use crate::{ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError}; +use crate::{ + bytecast, ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError, +}; use self::ifd::Directory; use crate::tags::{ @@ -211,6 +213,24 @@ impl<'a> DecodingBuffer<'a> { DecodingBuffer::I64(ref mut buf) => DecodingBuffer::I64(buf), } } + + fn prefix<'b>(&'b mut self, new_length: usize) -> DecodingBuffer<'b> + where + 'a: 'b, + { + match *self { + DecodingBuffer::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[..new_length]), + DecodingBuffer::U16(ref mut buf) => DecodingBuffer::U16(&mut buf[..new_length]), + DecodingBuffer::U32(ref mut buf) => DecodingBuffer::U32(&mut buf[..new_length]), + DecodingBuffer::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[..new_length]), + DecodingBuffer::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[..new_length]), + DecodingBuffer::F64(ref mut buf) => DecodingBuffer::F64(&mut buf[..new_length]), + DecodingBuffer::I8(ref mut buf) => DecodingBuffer::I8(&mut buf[..new_length]), + DecodingBuffer::I16(ref mut buf) => DecodingBuffer::I16(&mut buf[..new_length]), + DecodingBuffer::I32(ref mut buf) => DecodingBuffer::I32(&mut buf[..new_length]), + DecodingBuffer::I64(ref mut buf) => DecodingBuffer::I64(&mut buf[..new_length]), + } + } } #[derive(Debug)] @@ -506,51 +526,51 @@ fn rev_hpredict( Ok(()) } -fn process_photometry_u64(buffer: &mut [u64], bytes: usize) { - for datum in buffer[..bytes / 8].iter_mut() { +fn process_photometry_u64(buffer: &mut [u64]) { + for datum in buffer.iter_mut() { *datum = 0xffff_ffff_ffff_ffff - *datum } } -fn process_photometry_u32(buffer: &mut [u32], bytes: usize) { - for datum in buffer[..bytes / 4].iter_mut() { +fn process_photometry_u32(buffer: &mut [u32]) { + for datum in buffer.iter_mut() { *datum = 0xffff_ffff - *datum } } -fn process_photometry_u16(buffer: &mut [u16], bytes: usize) { - for datum in buffer[..bytes / 2].iter_mut() { +fn process_photometry_u16(buffer: &mut [u16]) { + for datum in buffer.iter_mut() { *datum = 0xffff - *datum } } -fn process_photometry_i16(buffer: &mut [i16], bytes: usize) { - for datum in buffer[..bytes / 2].iter_mut() { +fn process_photometry_i16(buffer: &mut [i16]) { + for datum in buffer.iter_mut() { *datum = !*datum; } } -fn process_photometry_i8(buffer: &mut [i8], bytes: usize) { - for datum in buffer[..bytes].iter_mut() { +fn process_photometry_i8(buffer: &mut [i8]) { + for datum in buffer.iter_mut() { *datum = !*datum; } } -fn process_photometry_u8(buffer: &mut [u8], bytes: usize) { - for byte in buffer[..bytes].iter_mut() { - *byte = !*byte; +fn process_photometry_u8(buffer: &mut [u8]) { + for byte in buffer.iter_mut() { + *byte = 0xff - *byte } } -fn process_photometry_f64(buffer: &mut [f64], bytes: usize) { - for datum in buffer[..bytes / 8].iter_mut() { +fn process_photometry_f64(buffer: &mut [f64]) { + for datum in buffer.iter_mut() { // FIXME: assumes [0, 1) range for floats *datum = 1.0 - *datum } } -fn process_photometry_f32(buffer: &mut [f32], bytes: usize) { - for datum in buffer[..bytes / 4].iter_mut() { +fn process_photometry_f32(buffer: &mut [f32]) { + for datum in buffer.iter_mut() { // FIXME: assumes [0, 1) range for floats *datum = 1.0 - *datum } @@ -1041,341 +1061,44 @@ impl Decoder { /// Returns the number of bytes read. fn expand_strip<'a>( &mut self, - buffer: DecodingBuffer<'a>, + mut buffer: DecodingBuffer<'a>, offset: u64, length: u64, - strip_sample_count: usize, - ) -> TiffResult { + ) -> TiffResult<()> { + // Validate that the provided buffer is of the expected type. let color_type = self.colortype()?; - self.goto_offset_u64(offset)?; - - let (bytes, mut reader) = Self::create_reader( - &mut self.reader, - self.compression_method, - length, - strip_sample_count, - buffer.byte_len(), - )?; - - Ok(match (color_type, buffer) { - (ColorType::RGB(8), DecodingBuffer::U8(ref mut buffer)) - | (ColorType::RGBA(8), DecodingBuffer::U8(ref mut buffer)) - | (ColorType::CMYK(8), DecodingBuffer::U8(ref mut buffer)) => { - reader.read_exact(&mut buffer[..bytes])?; - bytes - } - (ColorType::RGBA(16), DecodingBuffer::U16(ref mut buffer)) - | (ColorType::RGB(16), DecodingBuffer::U16(ref mut buffer)) - | (ColorType::CMYK(16), DecodingBuffer::U16(ref mut buffer)) => { - reader.read_u16_into(&mut buffer[..bytes / 2])?; - bytes / 2 - } - (ColorType::RGBA(32), DecodingBuffer::U32(ref mut buffer)) - | (ColorType::RGB(32), DecodingBuffer::U32(ref mut buffer)) - | (ColorType::CMYK(32), DecodingBuffer::U32(ref mut buffer)) => { - reader.read_u32_into(&mut buffer[..bytes / 4])?; - bytes / 4 - } - (ColorType::RGBA(32), DecodingBuffer::F32(ref mut buffer)) - | (ColorType::RGB(32), DecodingBuffer::F32(ref mut buffer)) - | (ColorType::CMYK(32), DecodingBuffer::F32(ref mut buffer)) => { - reader.read_f32_into(&mut buffer[..bytes / 4])?; - bytes / 4 - } - (ColorType::RGBA(64), DecodingBuffer::F64(ref mut buffer)) - | (ColorType::RGB(64), DecodingBuffer::F64(ref mut buffer)) - | (ColorType::CMYK(64), DecodingBuffer::F64(ref mut buffer)) => { - reader.read_f64_into(&mut buffer[..bytes / 8])?; - bytes / 8 - } - (ColorType::RGBA(64), DecodingBuffer::U64(ref mut buffer)) - | (ColorType::RGB(64), DecodingBuffer::U64(ref mut buffer)) - | (ColorType::CMYK(64), DecodingBuffer::U64(ref mut buffer)) => { - reader.read_u64_into(&mut buffer[..bytes / 8])?; - bytes / 8 - } - (ColorType::RGBA(8), DecodingBuffer::I8(ref mut buffer)) - | (ColorType::RGB(8), DecodingBuffer::I8(ref mut buffer)) - | (ColorType::CMYK(8), DecodingBuffer::I8(ref mut buffer)) => { - reader.read_i8_into(&mut buffer[..bytes])?; - bytes - } - (ColorType::RGBA(16), DecodingBuffer::I16(ref mut buffer)) - | (ColorType::RGB(16), DecodingBuffer::I16(ref mut buffer)) - | (ColorType::CMYK(16), DecodingBuffer::I16(ref mut buffer)) => { - reader.read_i16_into(&mut buffer[..bytes / 2])?; - bytes / 2 - } - - (ColorType::Gray(64), DecodingBuffer::U64(ref mut buffer)) => { - reader.read_u64_into(&mut buffer[..bytes / 8])?; - if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { - process_photometry_u64(buffer, bytes) - } - bytes / 8 - } - (ColorType::Gray(64), DecodingBuffer::I64(ref mut buffer)) => { - reader.read_i64_into(&mut buffer[..bytes / 8])?; - bytes / 8 - } - (ColorType::Gray(32), DecodingBuffer::U32(ref mut buffer)) => { - reader.read_u32_into(&mut buffer[..bytes / 4])?; - if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { - process_photometry_u32(buffer, bytes) - } - bytes / 4 - } - (ColorType::Gray(32), DecodingBuffer::I32(ref mut buffer)) => { - reader.read_i32_into(&mut buffer[..bytes / 4])?; - bytes / 4 - } - (ColorType::Gray(16), DecodingBuffer::U16(ref mut buffer)) => { - reader.read_u16_into(&mut buffer[..bytes / 2])?; - if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { - process_photometry_u16(buffer, bytes) - } - bytes / 2 - } - (ColorType::Gray(8), DecodingBuffer::I8(ref mut buffer)) => { - reader.read_i8_into(&mut buffer[..bytes])?; - if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { - process_photometry_i8(buffer, bytes) - } - bytes - } - // The following conversions interpret the image as in libtiff. - // In particular, MIN is white and MAX is black and not Zero as the name would imply. - (ColorType::Gray(16), DecodingBuffer::I16(ref mut buffer)) => { - reader.read_i16_into(&mut buffer[..bytes / 2])?; - if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { - process_photometry_i16(buffer, bytes) - } - bytes / 2 - } - (ColorType::Gray(n), DecodingBuffer::U8(ref mut buffer)) if n <= 8 => { - reader.read_exact(&mut buffer[..bytes])?; - if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { - process_photometry_u8(buffer, bytes) - } - bytes - } - (ColorType::Gray(32), DecodingBuffer::F32(ref mut buffer)) => { - reader.read_f32_into(&mut buffer[..bytes / 4])?; - if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { - process_photometry_f32(buffer, bytes) - } - bytes / 4 - } - (ColorType::Gray(64), DecodingBuffer::F64(ref mut buffer)) => { - reader.read_f64_into(&mut buffer[..bytes / 8])?; - if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { - process_photometry_f64(buffer, bytes) - } - bytes / 8 - } - (type_, _) => { - return Err(TiffError::UnsupportedError( - TiffUnsupportedError::UnsupportedColorType(type_), - )) - } - }) - } - - /// Decompresses the tile into the supplied buffer. - /// Returns the number of bytes read. - fn expand_tile<'a>( - &mut self, - buffer: DecodingBuffer<'a>, - offset: u64, - compressed_length: u64, - tile: usize, - ) -> TiffResult { - let color_type = self.colortype()?; - self.goto_offset_u64(offset)?; - - let tile_attrs = self.tile_attributes.as_mut().unwrap(); - let (padding_right, padding_down) = tile_attrs.get_padding(tile); - let tile_samples = tile_attrs.tile_samples; - let tile_length = tile_attrs.tile_length; - let row_samples = tile_attrs.row_samples; - let padding_right_samples = padding_right * self.bits_per_sample.len(); - - let (bytes, mut reader) = Self::create_reader( - &mut self.reader, - self.compression_method, - compressed_length, - tile_samples, - buffer.byte_len(), - )?; - - let tile_decoder = self.tile_decoder.as_mut().unwrap(); - let line_samples = tile_decoder.result_width * self.bits_per_sample.len(); - let padding_buffer = &mut tile_decoder.padding_buffer; - - macro_rules! fill_tile_buffer { - ($img_buf:ident, $byte_len:expr, $read_fn:ident) => {{ - for row in 0..(tile_length - padding_down) { - let row_start = row * line_samples; - let row_end = row_start + row_samples - padding_right_samples; - - let src = &mut $img_buf[(row_start / $byte_len)..(row_end / $byte_len)]; - reader.$read_fn(src)?; - // Skip horizontal padding - // TODO: is there a better way of skipping the padding ? - if padding_right > 0 { - reader.read_exact(padding_buffer)? - } - } - Ok((bytes / $byte_len)) - }}; - } - - macro_rules! tile_photometry { - ($img_buf:ident, $byte_len:expr, $photometry_fn:ident) => {{ - for row in 0..(tile_length - padding_down) { - let row_start = row * line_samples; - let row_end = row_start + row_samples - padding_right_samples; - - let buf = &mut $img_buf[row_start..row_end]; - if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { - $photometry_fn( - buf, - (row_samples - padding_right_samples) * self.bits_per_sample.len(), - ) - }; - } - }}; - } - - match (color_type, buffer) { - (ColorType::RGB(8), DecodingBuffer::U8(ref mut buffer)) - | (ColorType::RGBA(8), DecodingBuffer::U8(ref mut buffer)) - | (ColorType::CMYK(8), DecodingBuffer::U8(ref mut buffer)) => { - fill_tile_buffer! {buffer, 1, read_exact} - } - (ColorType::RGBA(16), DecodingBuffer::U16(ref mut buffer)) - | (ColorType::RGB(16), DecodingBuffer::U16(ref mut buffer)) - | (ColorType::CMYK(16), DecodingBuffer::U16(ref mut buffer)) => { - fill_tile_buffer! {buffer, 2, read_u16_into} - } - (ColorType::RGBA(32), DecodingBuffer::U32(ref mut buffer)) - | (ColorType::RGB(32), DecodingBuffer::U32(ref mut buffer)) - | (ColorType::CMYK(32), DecodingBuffer::U32(ref mut buffer)) => { - fill_tile_buffer! {buffer, 4, read_u32_into} - } - (ColorType::RGBA(32), DecodingBuffer::F32(ref mut buffer)) - | (ColorType::RGB(32), DecodingBuffer::F32(ref mut buffer)) - | (ColorType::CMYK(32), DecodingBuffer::F32(ref mut buffer)) => { - fill_tile_buffer! {buffer, 4, read_f32_into} - } - (ColorType::RGBA(64), DecodingBuffer::F64(ref mut buffer)) - | (ColorType::RGB(64), DecodingBuffer::F64(ref mut buffer)) - | (ColorType::CMYK(64), DecodingBuffer::F64(ref mut buffer)) => { - fill_tile_buffer! {buffer, 8, read_f64_into} - } - (ColorType::RGBA(64), DecodingBuffer::U64(ref mut buffer)) - | (ColorType::RGB(64), DecodingBuffer::U64(ref mut buffer)) - | (ColorType::CMYK(64), DecodingBuffer::U64(ref mut buffer)) => { - fill_tile_buffer! {buffer, 8, read_u64_into} - } - (ColorType::RGBA(8), DecodingBuffer::I8(ref mut buffer)) - | (ColorType::RGB(8), DecodingBuffer::I8(ref mut buffer)) - | (ColorType::CMYK(8), DecodingBuffer::I8(ref mut buffer)) => { - fill_tile_buffer! {buffer, 1, read_i8_into} - } - (ColorType::RGBA(16), DecodingBuffer::I16(ref mut buffer)) - | (ColorType::RGB(16), DecodingBuffer::I16(ref mut buffer)) - | (ColorType::CMYK(16), DecodingBuffer::I16(ref mut buffer)) => { - fill_tile_buffer! {buffer, 2, read_i16_into} - } - (ColorType::Gray(64), DecodingBuffer::U64(ref mut buffer)) => { - let units_read = fill_tile_buffer! {buffer, 8, read_u64_into}; - tile_photometry!(buffer, 8, process_photometry_u64); - units_read - } - (ColorType::Gray(64), DecodingBuffer::I64(ref mut buffer)) => { - fill_tile_buffer! {buffer, 8, read_i64_into} - } - (ColorType::Gray(32), DecodingBuffer::U32(ref mut buffer)) => { - let units_read = fill_tile_buffer!(buffer, 4, read_u32_into); - tile_photometry!(buffer, 4, process_photometry_u32); - units_read - } - (ColorType::Gray(32), DecodingBuffer::I32(ref mut buffer)) => { - fill_tile_buffer! {buffer, 4, read_i32_into} - } - (ColorType::Gray(16), DecodingBuffer::U16(ref mut buffer)) => { - let units_read = fill_tile_buffer!(buffer, 2, read_u16_into); - tile_photometry!(buffer, 2, process_photometry_u16); - units_read - } - (ColorType::Gray(8), DecodingBuffer::I8(ref mut buffer)) => { - let units_read = fill_tile_buffer!(buffer, 1, read_i8_into); - tile_photometry!(buffer, 1, process_photometry_i8); - units_read - } - // The following conversions interpret the image as in libtiff. - // In particular, MIN is white and MAX is black and not Zero as the name would imply. - (ColorType::Gray(16), DecodingBuffer::I16(ref mut buffer)) => { - let units_read = fill_tile_buffer!(buffer, 2, read_i16_into); - tile_photometry!(buffer, 2, process_photometry_i16); - units_read - } - (ColorType::Gray(n), DecodingBuffer::U8(ref mut buffer)) if n <= 8 => { - let units_read = fill_tile_buffer!(buffer, 1, read_exact); - tile_photometry!(buffer, 1, process_photometry_u8); - units_read - } - (ColorType::Gray(32), DecodingBuffer::F32(ref mut buffer)) => { - let units_read = fill_tile_buffer!(buffer, 4, read_f32_into); - tile_photometry!(buffer, 4, process_photometry_f32); - units_read - } - (ColorType::Gray(64), DecodingBuffer::F64(ref mut buffer)) => { - let units_read = fill_tile_buffer!(buffer, 8, read_f64_into); - tile_photometry!(buffer, 8, process_photometry_f64); - units_read - } + match (color_type, &buffer) { + (ColorType::RGB(n), _) + | (ColorType::RGBA(n), _) + | (ColorType::CMYK(n), _) + | (ColorType::Gray(n), _) + if usize::from(n) == buffer.byte_len() * 8 => {} + (ColorType::Gray(n), DecodingBuffer::U8(_)) if n <= 8 => {} (type_, _) => { return Err(TiffError::UnsupportedError( TiffUnsupportedError::UnsupportedColorType(type_), )) } } - } - fn create_reader<'r>( - reader: &'r mut SmartReader, - compression_method: CompressionMethod, - compressed_length: u64, - tile_samples: usize, - byte_len: usize, - ) -> TiffResult<(usize, Box)> { - let (bytes, reader): (usize, Box) = match compression_method { - CompressionMethod::None => { - let order = reader.byte_order; - ( - usize::try_from(compressed_length)?, - Box::new(SmartReader::wrap(reader, order)), - ) - } - CompressionMethod::LZW => { - let (bytes, reader) = LZWReader::new( - reader, - usize::try_from(compressed_length)?, - tile_samples * byte_len, - )?; - (bytes, Box::new(reader)) - } + // Construct necessary reader to perform decompression. + self.goto_offset_u64(offset)?; + let byte_order = self.reader.byte_order; + let mut reader: Box = match self.compression_method { + CompressionMethod::None => Box::new(&mut self.reader), + CompressionMethod::LZW => Box::new( + LZWReader::new( + &mut self.reader, + usize::try_from(length)?, + buffer.len() * buffer.byte_len(), + )? + .1, + ), CompressionMethod::PackBits => { - let order = reader.byte_order; - let (bytes, reader) = - PackBitsReader::new(reader, order, usize::try_from(compressed_length)?)?; - (bytes, Box::new(reader)) + Box::new(PackBitsReader::new(&mut self.reader, usize::try_from(length)?)?.1) } CompressionMethod::OldDeflate => { - let (bytes, reader) = DeflateReader::new(reader, tile_samples)?; - (bytes, Box::new(reader)) + Box::new(DeflateReader::new(&mut self.reader, buffer.len() * buffer.byte_len())?.1) } method => { return Err(TiffError::UnsupportedError( @@ -1384,18 +1107,291 @@ impl Decoder { } }; - // FIXME: this might be suboptimal. We might default remaining bits to ยด0`, which some - // other decoders might do. - if bytes / byte_len > tile_samples { - return Err(TiffError::FormatError( - TiffFormatError::UnexpectedCompressedData { - actual_bytes: bytes, - required_bytes: tile_samples * byte_len, - }, - )); + // Read into output buffer. + { + let buffer = match &mut buffer { + DecodingBuffer::U8(buf) => &mut *buf, + DecodingBuffer::I8(buf) => bytecast::i8_as_ne_mut_bytes(buf), + DecodingBuffer::U16(buf) => bytecast::u16_as_ne_mut_bytes(buf), + DecodingBuffer::I16(buf) => bytecast::i16_as_ne_mut_bytes(buf), + DecodingBuffer::U32(buf) => bytecast::u32_as_ne_mut_bytes(buf), + DecodingBuffer::I32(buf) => bytecast::i32_as_ne_mut_bytes(buf), + DecodingBuffer::U64(buf) => bytecast::u64_as_ne_mut_bytes(buf), + DecodingBuffer::I64(buf) => bytecast::i64_as_ne_mut_bytes(buf), + DecodingBuffer::F32(buf) => bytecast::f32_as_ne_mut_bytes(buf), + DecodingBuffer::F64(buf) => bytecast::f64_as_ne_mut_bytes(buf), + }; + + let mut bytes_written = 0; + while bytes_written < buffer.len() { + match reader.read(&mut buffer[bytes_written..]) { + Ok(0) => break, + Ok(n) => bytes_written += n, + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} + Err(e) => Err(e)?, + } + } + for b in &mut buffer[bytes_written..] { + *b = 0; + } } - Ok((bytes, reader)) + // Fix endianness. If `byte_order` matches the host, then conversion is a no-op. + match byte_order { + ByteOrder::LittleEndian => match &mut buffer { + DecodingBuffer::U8(_) | DecodingBuffer::I8(_) => {} + DecodingBuffer::U16(buf) => buf.iter_mut().for_each(|v| *v = u16::from_le(*v)), + DecodingBuffer::I16(buf) => buf.iter_mut().for_each(|v| *v = i16::from_le(*v)), + DecodingBuffer::U32(buf) => buf.iter_mut().for_each(|v| *v = u32::from_le(*v)), + DecodingBuffer::I32(buf) => buf.iter_mut().for_each(|v| *v = i32::from_le(*v)), + DecodingBuffer::U64(buf) => buf.iter_mut().for_each(|v| *v = u64::from_le(*v)), + DecodingBuffer::I64(buf) => buf.iter_mut().for_each(|v| *v = i64::from_le(*v)), + DecodingBuffer::F32(buf) => buf + .iter_mut() + .for_each(|v| *v = f32::from_bits(u32::from_le(v.to_bits()))), + DecodingBuffer::F64(buf) => buf + .iter_mut() + .for_each(|v| *v = f64::from_bits(u64::from_le(v.to_bits()))), + }, + ByteOrder::BigEndian => match &mut buffer { + DecodingBuffer::U8(_) | DecodingBuffer::I8(_) => {} + DecodingBuffer::U16(buf) => buf.iter_mut().for_each(|v| *v = u16::from_be(*v)), + DecodingBuffer::I16(buf) => buf.iter_mut().for_each(|v| *v = i16::from_be(*v)), + DecodingBuffer::U32(buf) => buf.iter_mut().for_each(|v| *v = u32::from_be(*v)), + DecodingBuffer::I32(buf) => buf.iter_mut().for_each(|v| *v = i32::from_be(*v)), + DecodingBuffer::U64(buf) => buf.iter_mut().for_each(|v| *v = u64::from_be(*v)), + DecodingBuffer::I64(buf) => buf.iter_mut().for_each(|v| *v = i64::from_be(*v)), + DecodingBuffer::F32(buf) => buf + .iter_mut() + .for_each(|v| *v = f32::from_bits(u32::from_be(v.to_bits()))), + DecodingBuffer::F64(buf) => buf + .iter_mut() + .for_each(|v| *v = f64::from_bits(u64::from_be(v.to_bits()))), + }, + } + + // Invert colors if necessary. + if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { + match (color_type, &mut buffer) { + (ColorType::Gray(64), DecodingBuffer::U64(ref mut buffer)) => { + for datum in buffer.iter_mut() { + *datum = 0xffff_ffff_ffff_ffff - *datum + } + } + (ColorType::Gray(32), DecodingBuffer::U32(ref mut buffer)) => { + for datum in buffer.iter_mut() { + *datum = 0xffff_ffff - *datum + } + } + (ColorType::Gray(16), DecodingBuffer::U16(ref mut buffer)) => { + for datum in buffer.iter_mut() { + *datum = 0xffff - *datum + } + } + (ColorType::Gray(n), DecodingBuffer::U8(ref mut buffer)) if n <= 8 => { + for byte in buffer.iter_mut() { + *byte = 0xff - *byte + } + } + (ColorType::Gray(32), DecodingBuffer::F32(ref mut buffer)) => { + for datum in buffer.iter_mut() { + // FIXME: assumes [0, 1) range for floats + *datum = 1.0 - *datum + } + } + (ColorType::Gray(64), DecodingBuffer::F64(ref mut buffer)) => { + for datum in buffer.iter_mut() { + // FIXME: assumes [0, 1) range for floats + *datum = 1.0 - *datum + } + } + _ => {} + } + } + + Ok(()) + } + + /// Decompresses the tile into the supplied buffer. + /// Returns the number of bytes read. + fn expand_tile<'a>( + &mut self, + mut buffer: DecodingBuffer<'a>, + offset: u64, + compressed_length: u64, + tile: usize, + ) -> TiffResult<()> { + let color_type = self.colortype()?; + let byte_len = buffer.byte_len(); + + let tile_attrs = self.tile_attributes.as_mut().unwrap(); + let (padding_right, padding_down) = tile_attrs.get_padding(tile); + let tile_samples = tile_attrs.tile_samples; + let tile_length = tile_attrs.tile_length; + let row_samples = tile_attrs.row_samples; + let padding_right_samples = padding_right * self.bits_per_sample.len(); + + self.goto_offset_u64(offset)?; + + let tile_decoder = self.tile_decoder.as_mut().unwrap(); + let line_samples = tile_decoder.result_width * self.bits_per_sample.len(); + let padding_buffer = &mut tile_decoder.padding_buffer; + + let mut reader = Self::create_reader( + &mut self.reader, + self.compression_method, + compressed_length, + tile_samples, + byte_len, + )?; + + for row in 0..(tile_length - padding_down) { + let buf = match &mut buffer { + DecodingBuffer::U8(buf) => &mut *buf, + DecodingBuffer::I8(buf) => bytecast::i8_as_ne_mut_bytes(buf), + DecodingBuffer::U16(buf) => bytecast::u16_as_ne_mut_bytes(buf), + DecodingBuffer::I16(buf) => bytecast::i16_as_ne_mut_bytes(buf), + DecodingBuffer::U32(buf) => bytecast::u32_as_ne_mut_bytes(buf), + DecodingBuffer::I32(buf) => bytecast::i32_as_ne_mut_bytes(buf), + DecodingBuffer::U64(buf) => bytecast::u64_as_ne_mut_bytes(buf), + DecodingBuffer::I64(buf) => bytecast::i64_as_ne_mut_bytes(buf), + DecodingBuffer::F32(buf) => bytecast::f32_as_ne_mut_bytes(buf), + DecodingBuffer::F64(buf) => bytecast::f64_as_ne_mut_bytes(buf), + }; + + let row_start = row * line_samples; + let row_end = row_start + row_samples - padding_right_samples; + + let row = &mut buf[(row_start * byte_len)..(row_end * byte_len)]; + reader.read_exact(row)?; + // Skip horizontal padding + // TODO: find a better way of skipping the padding + if padding_right > 0 { + reader.read_exact(padding_buffer)? + } + + // Fix byte order if necessary + match self.byte_order { + ByteOrder::LittleEndian => match &mut buffer { + DecodingBuffer::U8(_) | DecodingBuffer::I8(_) => {} + DecodingBuffer::U16(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = u16::from_le(*v)), + DecodingBuffer::I16(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = i16::from_le(*v)), + DecodingBuffer::U32(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = u32::from_le(*v)), + DecodingBuffer::I32(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = i32::from_le(*v)), + DecodingBuffer::U64(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = u64::from_le(*v)), + DecodingBuffer::I64(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = i64::from_le(*v)), + DecodingBuffer::F32(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = f32::from_bits(u32::from_le(v.to_bits()))), + DecodingBuffer::F64(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = f64::from_bits(u64::from_le(v.to_bits()))), + }, + ByteOrder::BigEndian => match &mut buffer { + DecodingBuffer::U8(_) | DecodingBuffer::I8(_) => {} + DecodingBuffer::U16(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = u16::from_be(*v)), + DecodingBuffer::I16(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = i16::from_be(*v)), + DecodingBuffer::U32(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = u32::from_be(*v)), + DecodingBuffer::I32(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = i32::from_be(*v)), + DecodingBuffer::U64(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = u64::from_be(*v)), + DecodingBuffer::I64(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = i64::from_be(*v)), + DecodingBuffer::F32(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = f32::from_bits(u32::from_be(v.to_bits()))), + DecodingBuffer::F64(b) => b[row_start..row_end] + .iter_mut() + .for_each(|v| *v = f64::from_bits(u64::from_be(v.to_bits()))), + }, + }; + + // Invert colors if necessary. + if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { + match (color_type, &mut buffer) { + (ColorType::Gray(64), DecodingBuffer::U64(ref mut buffer)) => { + process_photometry_u64(&mut buffer[row_start..row_end]); + } + (ColorType::Gray(32), DecodingBuffer::U32(ref mut buffer)) => { + process_photometry_u32(&mut buffer[row_start..row_end]); + } + (ColorType::Gray(16), DecodingBuffer::U16(ref mut buffer)) => { + process_photometry_u16(&mut buffer[row_start..row_end]); + } + (ColorType::Gray(n), DecodingBuffer::U8(ref mut buffer)) if n <= 8 => { + process_photometry_u8(&mut buffer[row_start..row_end]); + } + (ColorType::Gray(32), DecodingBuffer::F32(ref mut buffer)) => { + process_photometry_f32(&mut buffer[row_start..row_end]); + } + (ColorType::Gray(64), DecodingBuffer::F64(ref mut buffer)) => { + process_photometry_f64(&mut buffer[row_start..row_end]); + } + (ColorType::Gray(n), DecodingBuffer::I8(ref mut buffer)) if n <= 8 => { + process_photometry_i8(&mut buffer[row_start..row_end]); + } + (ColorType::Gray(16), DecodingBuffer::I16(ref mut buffer)) => { + process_photometry_i16(&mut buffer[row_start..row_end]); + } + _ => {} + } + } + } + + Ok(()) + } + + fn create_reader<'r>( + reader: &'r mut SmartReader, + compression_method: CompressionMethod, + compressed_length: u64, + samples: usize, // Expected chunk length in samples + byte_len: usize, // Byte length of the result buffer + ) -> TiffResult> { + Ok(match compression_method { + CompressionMethod::None => Box::new(reader), + CompressionMethod::LZW => Box::new( + LZWReader::new( + reader, + usize::try_from(compressed_length)?, + samples * byte_len, + )? + .1, + ), + CompressionMethod::PackBits => { + Box::new(PackBitsReader::new(reader, usize::try_from(compressed_length)?)?.1) + } + CompressionMethod::OldDeflate => { + Box::new(DeflateReader::new(reader, samples * byte_len)?.1) + } + method => { + return Err(TiffError::UnsupportedError( + TiffUnsupportedError::UnsupportedCompressionMethod(method), + )) + } + }) } fn check_chunk_type(&self, expected: ChunkType) -> TiffResult<()> { @@ -1599,20 +1595,12 @@ impl Decoder { )); } - let units_read = self.expand_strip(buffer.copy(), offset, byte_count, buffer_size)?; + self.expand_strip(buffer.prefix(buffer_size), offset, byte_count)?; self.strip_decoder.as_mut().unwrap().strip_index += 1; if u32::try_from(index)? == self.strip_count()? { self.strip_decoder = None; } - if units_read < buffer_size { - return Err(TiffError::FormatError( - TiffFormatError::InconsistentStripSamples { - actual_samples: units_read, - required_samples: buffer_size, - }, - )); - } if let Ok(predictor) = self.get_tag_unsigned(Tag::Predictor) { match Predictor::from_u16(predictor) { Some(Predictor::None) => (), @@ -1657,22 +1645,12 @@ impl Decoder { ))?; let tile_attrs = self.tile_attributes.as_ref().unwrap(); - let tile_samples = tile_attrs.tile_samples; let tile_width = tile_attrs.tile_width; let tile_length = tile_attrs.tile_length; let (padding_right, padding_down) = tile_attrs.get_padding(tile); - let units_read = self.expand_tile(result.copy(), file_offset, compressed_bytes, tile)?; - - if units_read < tile_samples { - return Err(TiffError::FormatError( - TiffFormatError::InconsistentStripSamples { - actual_samples: units_read, - required_samples: tile_samples, - }, - )); - } + self.expand_tile(result.copy(), file_offset, compressed_bytes, tile)?; if let Ok(predictor) = self.get_tag_unsigned(Tag::Predictor) { match Predictor::from_u16(predictor) { diff --git a/src/decoder/stream.rs b/src/decoder/stream.rs index ce8d4fc..61fa5df 100644 --- a/src/decoder/stream.rs +++ b/src/decoder/stream.rs @@ -1,6 +1,5 @@ //! All IO functionality needed for TIFF decoding -use crate::bytecast; use crate::error::{TiffError, TiffResult}; use miniz_oxide::inflate; use std::io::{self, Read, Seek}; @@ -30,24 +29,6 @@ pub trait EndianReader: Read { }) } - #[inline(always)] - fn read_u16_into(&mut self, buffer: &mut [u16]) -> Result<(), io::Error> { - self.read_exact(bytecast::u16_as_ne_mut_bytes(buffer))?; - match self.byte_order() { - ByteOrder::LittleEndian => { - for n in buffer { - *n = u16::from_le(*n); - } - } - ByteOrder::BigEndian => { - for n in buffer { - *n = u16::from_be(*n); - } - } - } - Ok(()) - } - /// Reads an i8 #[inline(always)] fn read_i8(&mut self) -> Result { @@ -59,24 +40,6 @@ pub trait EndianReader: Read { }) } - #[inline(always)] - fn read_i8_into(&mut self, buffer: &mut [i8]) -> Result<(), io::Error> { - self.read_exact(bytecast::i8_as_ne_mut_bytes(buffer))?; - match self.byte_order() { - ByteOrder::LittleEndian => { - for n in buffer { - *n = i8::from_le(*n); - } - } - ByteOrder::BigEndian => { - for n in buffer { - *n = i8::from_be(*n); - } - } - } - Ok(()) - } - /// Reads an i16 #[inline(always)] fn read_i16(&mut self) -> Result { @@ -88,24 +51,6 @@ pub trait EndianReader: Read { }) } - #[inline(always)] - fn read_i16_into(&mut self, buffer: &mut [i16]) -> Result<(), io::Error> { - self.read_exact(bytecast::i16_as_ne_mut_bytes(buffer))?; - match self.byte_order() { - ByteOrder::LittleEndian => { - for n in buffer { - *n = i16::from_le(*n); - } - } - ByteOrder::BigEndian => { - for n in buffer { - *n = i16::from_be(*n); - } - } - } - Ok(()) - } - /// Reads an u32 #[inline(always)] fn read_u32(&mut self) -> Result { @@ -117,42 +62,6 @@ pub trait EndianReader: Read { }) } - #[inline(always)] - fn read_u32_into(&mut self, buffer: &mut [u32]) -> Result<(), io::Error> { - self.read_exact(bytecast::u32_as_ne_mut_bytes(buffer))?; - match self.byte_order() { - ByteOrder::LittleEndian => { - for n in buffer { - *n = u32::from_le(*n); - } - } - ByteOrder::BigEndian => { - for n in buffer { - *n = u32::from_be(*n); - } - } - } - Ok(()) - } - - #[inline(always)] - fn read_i32_into(&mut self, buffer: &mut [i32]) -> Result<(), io::Error> { - self.read_exact(bytecast::i32_as_ne_mut_bytes(buffer))?; - match self.byte_order() { - ByteOrder::LittleEndian => { - for n in buffer { - *n = i32::from_le(*n); - } - } - ByteOrder::BigEndian => { - for n in buffer { - *n = i32::from_be(*n); - } - } - } - Ok(()) - } - /// Reads an i32 #[inline(always)] fn read_i32(&mut self) -> Result { @@ -175,42 +84,6 @@ pub trait EndianReader: Read { }) } - #[inline(always)] - fn read_u64_into(&mut self, buffer: &mut [u64]) -> Result<(), io::Error> { - self.read_exact(bytecast::u64_as_ne_mut_bytes(buffer))?; - match self.byte_order() { - ByteOrder::LittleEndian => { - for n in buffer { - *n = u64::from_le(*n); - } - } - ByteOrder::BigEndian => { - for n in buffer { - *n = u64::from_be(*n); - } - } - } - Ok(()) - } - - #[inline(always)] - fn read_i64_into(&mut self, buffer: &mut [i64]) -> Result<(), io::Error> { - self.read_exact(bytecast::i64_as_ne_mut_bytes(buffer))?; - match self.byte_order() { - ByteOrder::LittleEndian => { - for n in buffer { - *n = i64::from_le(*n); - } - } - ByteOrder::BigEndian => { - for n in buffer { - *n = i64::from_be(*n); - } - } - } - Ok(()) - } - /// Reads an i64 #[inline(always)] fn read_i64(&mut self) -> Result { @@ -233,24 +106,6 @@ pub trait EndianReader: Read { })) } - #[inline(always)] - fn read_f32_into(&mut self, buffer: &mut [f32]) -> Result<(), io::Error> { - self.read_exact(bytecast::f32_as_ne_mut_bytes(buffer))?; - match self.byte_order() { - ByteOrder::LittleEndian => { - for n in buffer { - *n = f32::from_bits(u32::from_le(n.to_bits())); - } - } - ByteOrder::BigEndian => { - for n in buffer { - *n = f32::from_bits(u32::from_be(n.to_bits())); - } - } - } - Ok(()) - } - /// Reads an f64 #[inline(always)] fn read_f64(&mut self) -> Result { @@ -261,24 +116,6 @@ pub trait EndianReader: Read { ByteOrder::BigEndian => u64::from_be_bytes(n), })) } - - #[inline(always)] - fn read_f64_into(&mut self, buffer: &mut [f64]) -> Result<(), io::Error> { - self.read_exact(bytecast::f64_as_ne_mut_bytes(buffer))?; - match self.byte_order() { - ByteOrder::LittleEndian => { - for n in buffer { - *n = f64::from_bits(u64::from_le(n.to_bits())); - } - } - ByteOrder::BigEndian => { - for n in buffer { - *n = f64::from_bits(u64::from_be(n.to_bits())); - } - } - } - Ok(()) - } } /// @@ -292,7 +129,6 @@ pub trait EndianReader: Read { /// Reader that decompresses DEFLATE streams pub struct DeflateReader { buffer: io::Cursor>, - byte_order: ByteOrder, } impl DeflateReader { @@ -300,7 +136,6 @@ impl DeflateReader { reader: &mut SmartReader, max_uncompressed_length: usize, ) -> TiffResult<(usize, Self)> { - let byte_order = reader.byte_order; let mut compressed = Vec::new(); reader.read_to_end(&mut compressed)?; @@ -316,7 +151,6 @@ impl DeflateReader { Ok(( uncompressed.len(), Self { - byte_order, buffer: io::Cursor::new(uncompressed), }, )) @@ -329,12 +163,6 @@ impl Read for DeflateReader { } } -impl EndianReader for DeflateReader { - fn byte_order(&self) -> ByteOrder { - self.byte_order - } -} - /// /// ## LZW Reader /// @@ -342,7 +170,6 @@ impl EndianReader for DeflateReader { /// Reader that decompresses LZW streams pub struct LZWReader { buffer: io::Cursor>, - byte_order: ByteOrder, } impl LZWReader { @@ -355,25 +182,21 @@ impl LZWReader { where R: Read + Seek, { - let order = reader.byte_order; let mut compressed = vec![0; compressed_length as usize]; reader.read_exact(&mut compressed[..])?; - let mut uncompressed = Vec::with_capacity(max_uncompressed_length); + let mut uncompressed = vec![0; max_uncompressed_length]; let mut decoder = weezl::decode::Decoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8); + let mut bytes_read = 0; + let mut bytes_written = 0; - while uncompressed.len() < max_uncompressed_length { - let bytes_written = uncompressed.len(); - uncompressed.reserve(1 << 12); - let buffer_space = uncompressed.capacity().min(max_uncompressed_length); - uncompressed.resize(buffer_space, 0u8); - + while bytes_written < max_uncompressed_length { let result = decoder.decode_bytes( &compressed[bytes_read..], &mut uncompressed[bytes_written..], ); bytes_read += result.consumed_in; - uncompressed.truncate(bytes_written + result.consumed_out); + bytes_written += result.consumed_out; match result.status { Ok(weezl::LzwStatus::Ok) => {} @@ -388,12 +211,11 @@ impl LZWReader { } } - let bytes = uncompressed.len(); + uncompressed.resize(bytes_written, 0); Ok(( - bytes, + uncompressed.len(), LZWReader { buffer: io::Cursor::new(uncompressed), - byte_order: order, }, )) } @@ -406,20 +228,12 @@ impl Read for LZWReader { } } -impl EndianReader for LZWReader { - #[inline(always)] - fn byte_order(&self) -> ByteOrder { - self.byte_order - } -} - /// /// ## JPEG Reader (for "new-style" JPEG format (TIFF compression tag 7)) /// pub(crate) struct JpegReader { buffer: io::Cursor>, - byte_order: ByteOrder, } impl JpegReader { /// Constructs new JpegReader wrapping a SmartReader. @@ -442,8 +256,6 @@ impl JpegReader { where R: Read + Seek, { - let order = reader.byte_order; - // Read jpeg image data let mut segment = vec![0; length as usize]; reader.read_exact(&mut segment[..])?; @@ -453,16 +265,14 @@ impl JpegReader { let mut jpeg_data = tables.clone(); let truncated_length = jpeg_data.len() - 2; jpeg_data.truncate(truncated_length); - jpeg_data.extend_from_slice(&mut segment[2..]); + jpeg_data.extend_from_slice(&segment[2..]); Ok(JpegReader { buffer: io::Cursor::new(jpeg_data), - byte_order: order, }) } None => Ok(JpegReader { buffer: io::Cursor::new(segment), - byte_order: order, }), } } @@ -475,13 +285,6 @@ impl Read for JpegReader { } } -impl EndianReader for JpegReader { - #[inline(always)] - fn byte_order(&self) -> ByteOrder { - self.byte_order - } -} - /// /// ## PackBits Reader /// @@ -489,58 +292,46 @@ impl EndianReader for JpegReader { /// Reader that unpacks Apple's `PackBits` format pub struct PackBitsReader { buffer: io::Cursor>, - byte_order: ByteOrder, } impl PackBitsReader { /// Wraps a reader pub fn new( mut reader: R, - byte_order: ByteOrder, length: usize, ) -> io::Result<(usize, PackBitsReader)> { let mut buffer = Vec::new(); - let mut read: usize = 0; - while read < length { - let lread = read_packbits_run(&mut reader, &mut buffer)?; - if lread == 0 { - return Err(io::ErrorKind::UnexpectedEof.into()); - } - read += lread; - } - Ok(( - buffer.len(), - PackBitsReader { - buffer: io::Cursor::new(buffer), - byte_order, - }, - )) - } -} + let mut header: [u8; 1] = [0]; + let mut data: [u8; 1] = [0]; -fn read_packbits_run(reader: &mut R, buffer: &mut Vec) -> io::Result { - let mut header: [u8; 1] = [0]; + let mut bytes_read = 0; + while bytes_read < length { + reader.read_exact(&mut header)?; + bytes_read += 1; - let bytes = reader.read(&mut header)?; - - match bytes { - 0 => Ok(0), - _ => match header[0] as i8 { - -128 => Ok(1), - h if h >= -127 && h <= -1 => { + let h = header[0] as i8; + if h >= -127 && h <= -1 { let new_len = buffer.len() + (1 - h as isize) as usize; - reader.read_exact(&mut header)?; - buffer.resize(new_len, header[0]); - Ok(2) - } - h => { + reader.read_exact(&mut data)?; + buffer.resize(new_len, data[0]); + bytes_read += 1; + } else if h >= 0 { let num_vals = h as usize + 1; let start = buffer.len(); buffer.resize(start + num_vals, 0); reader.read_exact(&mut buffer[start..])?; - Ok(num_vals + 1) + bytes_read += num_vals + } else { + // h = -128 is a no-op. } - }, + } + + Ok(( + buffer.len(), + PackBitsReader { + buffer: io::Cursor::new(buffer), + }, + )) } } @@ -551,13 +342,6 @@ impl Read for PackBitsReader { } } -impl EndianReader for PackBitsReader { - #[inline(always)] - fn byte_order(&self) -> ByteOrder { - self.byte_order - } -} - /// /// ## SmartReader Reader /// @@ -566,7 +350,7 @@ impl EndianReader for PackBitsReader { #[derive(Debug)] pub struct SmartReader where - R: Read + Seek, + R: Read, { reader: R, pub byte_order: ByteOrder, @@ -574,7 +358,7 @@ where impl SmartReader where - R: Read + Seek, + R: Read, { /// Wraps a reader pub fn wrap(reader: R, byte_order: ByteOrder) -> SmartReader { @@ -584,7 +368,7 @@ where impl EndianReader for SmartReader where - R: Read + Seek, + R: Read, { #[inline(always)] fn byte_order(&self) -> ByteOrder { @@ -592,7 +376,7 @@ where } } -impl Read for SmartReader { +impl Read for SmartReader { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { self.reader.read(buf) @@ -619,8 +403,7 @@ mod test { let encoded_len = encoded.len(); let buff = io::Cursor::new(encoded); - let (_, mut decoder) = - PackBitsReader::new(buff, ByteOrder::LittleEndian, encoded_len).unwrap(); + let (_, mut decoder) = PackBitsReader::new(buff, encoded_len).unwrap(); let mut decoded = Vec::new(); decoder.read_to_end(&mut decoded).unwrap();