Merge remote-tracking branch 'upstream/master' into tiles

This commit is contained in:
Tomáš Král committed 2021-04-14 13:32:56 +02:00
commit d4ce174236
2 files changed
+384 -623

No files matched your search

+348 -370
View File
@@ -3,7 +3,9 @@ use std::collections::HashMap;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::io::{self, Read, Seek}; 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 self::ifd::Directory;
use crate::tags::{ use crate::tags::{
@@ -211,6 +213,24 @@ impl<'a> DecodingBuffer<'a> {
DecodingBuffer::I64(ref mut buf) => DecodingBuffer::I64(buf), 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)] #[derive(Debug)]
@@ -506,51 +526,51 @@ fn rev_hpredict(
Ok(()) Ok(())
} }
fn process_photometry_u64(buffer: &mut [u64], bytes: usize) { fn process_photometry_u64(buffer: &mut [u64]) {
for datum in buffer[..bytes / 8].iter_mut() { for datum in buffer.iter_mut() {
*datum = 0xffff_ffff_ffff_ffff - *datum *datum = 0xffff_ffff_ffff_ffff - *datum
} }
} }
fn process_photometry_u32(buffer: &mut [u32], bytes: usize) { fn process_photometry_u32(buffer: &mut [u32]) {
for datum in buffer[..bytes / 4].iter_mut() { for datum in buffer.iter_mut() {
*datum = 0xffff_ffff - *datum *datum = 0xffff_ffff - *datum
} }
} }
fn process_photometry_u16(buffer: &mut [u16], bytes: usize) { fn process_photometry_u16(buffer: &mut [u16]) {
for datum in buffer[..bytes / 2].iter_mut() { for datum in buffer.iter_mut() {
*datum = 0xffff - *datum *datum = 0xffff - *datum
} }
} }
fn process_photometry_i16(buffer: &mut [i16], bytes: usize) { fn process_photometry_i16(buffer: &mut [i16]) {
for datum in buffer[..bytes / 2].iter_mut() { for datum in buffer.iter_mut() {
*datum = !*datum; *datum = !*datum;
} }
} }
fn process_photometry_i8(buffer: &mut [i8], bytes: usize) { fn process_photometry_i8(buffer: &mut [i8]) {
for datum in buffer[..bytes].iter_mut() { for datum in buffer.iter_mut() {
*datum = !*datum; *datum = !*datum;
} }
} }
fn process_photometry_u8(buffer: &mut [u8], bytes: usize) { fn process_photometry_u8(buffer: &mut [u8]) {
for byte in buffer[..bytes].iter_mut() { for byte in buffer.iter_mut() {
*byte = !*byte; *byte = 0xff - *byte
} }
} }
fn process_photometry_f64(buffer: &mut [f64], bytes: usize) { fn process_photometry_f64(buffer: &mut [f64]) {
for datum in buffer[..bytes / 8].iter_mut() { for datum in buffer.iter_mut() {
// FIXME: assumes [0, 1) range for floats // FIXME: assumes [0, 1) range for floats
*datum = 1.0 - *datum *datum = 1.0 - *datum
} }
} }
fn process_photometry_f32(buffer: &mut [f32], bytes: usize) { fn process_photometry_f32(buffer: &mut [f32]) {
for datum in buffer[..bytes / 4].iter_mut() { for datum in buffer.iter_mut() {
// FIXME: assumes [0, 1) range for floats // FIXME: assumes [0, 1) range for floats
*datum = 1.0 - *datum *datum = 1.0 - *datum
} }
@@ -1041,341 +1061,44 @@ impl<R: Read + Seek> Decoder<R> {
/// Returns the number of bytes read. /// Returns the number of bytes read.
fn expand_strip<'a>( fn expand_strip<'a>(
&mut self, &mut self,
buffer: DecodingBuffer<'a>, mut buffer: DecodingBuffer<'a>,
offset: u64, offset: u64,
length: u64, length: u64,
strip_sample_count: usize, ) -> TiffResult<()> {
) -> TiffResult<usize> { // Validate that the provided buffer is of the expected type.
let color_type = self.colortype()?; let color_type = self.colortype()?;
self.goto_offset_u64(offset)?; match (color_type, &buffer) {
(ColorType::RGB(n), _)
let (bytes, mut reader) = Self::create_reader( | (ColorType::RGBA(n), _)
&mut self.reader, | (ColorType::CMYK(n), _)
self.compression_method, | (ColorType::Gray(n), _)
length, if usize::from(n) == buffer.byte_len() * 8 => {}
strip_sample_count, (ColorType::Gray(n), DecodingBuffer::U8(_)) if n <= 8 => {}
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<usize> {
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
}
(type_, _) => { (type_, _) => {
return Err(TiffError::UnsupportedError( return Err(TiffError::UnsupportedError(
TiffUnsupportedError::UnsupportedColorType(type_), TiffUnsupportedError::UnsupportedColorType(type_),
)) ))
} }
} }
}
fn create_reader<'r>( // Construct necessary reader to perform decompression.
reader: &'r mut SmartReader<R>, self.goto_offset_u64(offset)?;
compression_method: CompressionMethod, let byte_order = self.reader.byte_order;
compressed_length: u64, let mut reader: Box<dyn Read> = match self.compression_method {
tile_samples: usize, CompressionMethod::None => Box::new(&mut self.reader),
byte_len: usize, CompressionMethod::LZW => Box::new(
) -> TiffResult<(usize, Box<dyn EndianReader + 'r>)> { LZWReader::new(
let (bytes, reader): (usize, Box<dyn EndianReader>) = match compression_method { &mut self.reader,
CompressionMethod::None => { usize::try_from(length)?,
let order = reader.byte_order; buffer.len() * buffer.byte_len(),
( )?
usize::try_from(compressed_length)?, .1,
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))
}
CompressionMethod::PackBits => { CompressionMethod::PackBits => {
let order = reader.byte_order; Box::new(PackBitsReader::new(&mut self.reader, usize::try_from(length)?)?.1)
let (bytes, reader) =
PackBitsReader::new(reader, order, usize::try_from(compressed_length)?)?;
(bytes, Box::new(reader))
} }
CompressionMethod::OldDeflate => { CompressionMethod::OldDeflate => {
let (bytes, reader) = DeflateReader::new(reader, tile_samples)?; Box::new(DeflateReader::new(&mut self.reader, buffer.len() * buffer.byte_len())?.1)
(bytes, Box::new(reader))
} }
method => { method => {
return Err(TiffError::UnsupportedError( return Err(TiffError::UnsupportedError(
@@ -1384,18 +1107,291 @@ impl<R: Read + Seek> Decoder<R> {
} }
}; };
// FIXME: this might be suboptimal. We might default remaining bits to ´0`, which some // Read into output buffer.
// other decoders might do. {
if bytes / byte_len > tile_samples { let buffer = match &mut buffer {
return Err(TiffError::FormatError( DecodingBuffer::U8(buf) => &mut *buf,
TiffFormatError::UnexpectedCompressedData { DecodingBuffer::I8(buf) => bytecast::i8_as_ne_mut_bytes(buf),
actual_bytes: bytes, DecodingBuffer::U16(buf) => bytecast::u16_as_ne_mut_bytes(buf),
required_bytes: tile_samples * byte_len, 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<R>,
compression_method: CompressionMethod,
compressed_length: u64,
samples: usize, // Expected chunk length in samples
byte_len: usize, // Byte length of the result buffer
) -> TiffResult<Box<dyn Read + 'r>> {
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<()> { fn check_chunk_type(&self, expected: ChunkType) -> TiffResult<()> {
@@ -1599,20 +1595,12 @@ impl<R: Read + Seek> Decoder<R> {
)); ));
} }
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; self.strip_decoder.as_mut().unwrap().strip_index += 1;
if u32::try_from(index)? == self.strip_count()? { if u32::try_from(index)? == self.strip_count()? {
self.strip_decoder = None; 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) { if let Ok(predictor) = self.get_tag_unsigned(Tag::Predictor) {
match Predictor::from_u16(predictor) { match Predictor::from_u16(predictor) {
Some(Predictor::None) => (), Some(Predictor::None) => (),
@@ -1657,22 +1645,12 @@ impl<R: Read + Seek> Decoder<R> {
))?; ))?;
let tile_attrs = self.tile_attributes.as_ref().unwrap(); 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_width = tile_attrs.tile_width;
let tile_length = tile_attrs.tile_length; let tile_length = tile_attrs.tile_length;
let (padding_right, padding_down) = tile_attrs.get_padding(tile); let (padding_right, padding_down) = tile_attrs.get_padding(tile);
let units_read = self.expand_tile(result.copy(), file_offset, compressed_bytes, tile)?; 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,
},
));
}
if let Ok(predictor) = self.get_tag_unsigned(Tag::Predictor) { if let Ok(predictor) = self.get_tag_unsigned(Tag::Predictor) {
match Predictor::from_u16(predictor) { match Predictor::from_u16(predictor) {
+36 -253
View File
@@ -1,6 +1,5 @@
//! All IO functionality needed for TIFF decoding //! All IO functionality needed for TIFF decoding
use crate::bytecast;
use crate::error::{TiffError, TiffResult}; use crate::error::{TiffError, TiffResult};
use miniz_oxide::inflate; use miniz_oxide::inflate;
use std::io::{self, Read, Seek}; 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 /// Reads an i8
#[inline(always)] #[inline(always)]
fn read_i8(&mut self) -> Result<i8, io::Error> { fn read_i8(&mut self) -> Result<i8, io::Error> {
@@ -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 /// Reads an i16
#[inline(always)] #[inline(always)]
fn read_i16(&mut self) -> Result<i16, io::Error> { fn read_i16(&mut self) -> Result<i16, io::Error> {
@@ -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 /// Reads an u32
#[inline(always)] #[inline(always)]
fn read_u32(&mut self) -> Result<u32, io::Error> { fn read_u32(&mut self) -> Result<u32, io::Error> {
@@ -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 /// Reads an i32
#[inline(always)] #[inline(always)]
fn read_i32(&mut self) -> Result<i32, io::Error> { fn read_i32(&mut self) -> Result<i32, io::Error> {
@@ -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 /// Reads an i64
#[inline(always)] #[inline(always)]
fn read_i64(&mut self) -> Result<i64, io::Error> { fn read_i64(&mut self) -> Result<i64, io::Error> {
@@ -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 /// Reads an f64
#[inline(always)] #[inline(always)]
fn read_f64(&mut self) -> Result<f64, io::Error> { fn read_f64(&mut self) -> Result<f64, io::Error> {
@@ -261,24 +116,6 @@ pub trait EndianReader: Read {
ByteOrder::BigEndian => u64::from_be_bytes(n), 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 /// Reader that decompresses DEFLATE streams
pub struct DeflateReader { pub struct DeflateReader {
buffer: io::Cursor<Vec<u8>>, buffer: io::Cursor<Vec<u8>>,
byte_order: ByteOrder,
} }
impl DeflateReader { impl DeflateReader {
@@ -300,7 +136,6 @@ impl DeflateReader {
reader: &mut SmartReader<R>, reader: &mut SmartReader<R>,
max_uncompressed_length: usize, max_uncompressed_length: usize,
) -> TiffResult<(usize, Self)> { ) -> TiffResult<(usize, Self)> {
let byte_order = reader.byte_order;
let mut compressed = Vec::new(); let mut compressed = Vec::new();
reader.read_to_end(&mut compressed)?; reader.read_to_end(&mut compressed)?;
@@ -316,7 +151,6 @@ impl DeflateReader {
Ok(( Ok((
uncompressed.len(), uncompressed.len(),
Self { Self {
byte_order,
buffer: io::Cursor::new(uncompressed), 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 /// ## LZW Reader
/// ///
@@ -342,7 +170,6 @@ impl EndianReader for DeflateReader {
/// Reader that decompresses LZW streams /// Reader that decompresses LZW streams
pub struct LZWReader { pub struct LZWReader {
buffer: io::Cursor<Vec<u8>>, buffer: io::Cursor<Vec<u8>>,
byte_order: ByteOrder,
} }
impl LZWReader { impl LZWReader {
@@ -355,25 +182,21 @@ impl LZWReader {
where where
R: Read + Seek, R: Read + Seek,
{ {
let order = reader.byte_order;
let mut compressed = vec![0; compressed_length as usize]; let mut compressed = vec![0; compressed_length as usize];
reader.read_exact(&mut compressed[..])?; 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 decoder = weezl::decode::Decoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8);
let mut bytes_read = 0; let mut bytes_read = 0;
let mut bytes_written = 0;
while uncompressed.len() < max_uncompressed_length { while bytes_written < 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);
let result = decoder.decode_bytes( let result = decoder.decode_bytes(
&compressed[bytes_read..], &compressed[bytes_read..],
&mut uncompressed[bytes_written..], &mut uncompressed[bytes_written..],
); );
bytes_read += result.consumed_in; bytes_read += result.consumed_in;
uncompressed.truncate(bytes_written + result.consumed_out); bytes_written += result.consumed_out;
match result.status { match result.status {
Ok(weezl::LzwStatus::Ok) => {} Ok(weezl::LzwStatus::Ok) => {}
@@ -388,12 +211,11 @@ impl LZWReader {
} }
} }
let bytes = uncompressed.len(); uncompressed.resize(bytes_written, 0);
Ok(( Ok((
bytes, uncompressed.len(),
LZWReader { LZWReader {
buffer: io::Cursor::new(uncompressed), 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)) /// ## JPEG Reader (for "new-style" JPEG format (TIFF compression tag 7))
/// ///
pub(crate) struct JpegReader { pub(crate) struct JpegReader {
buffer: io::Cursor<Vec<u8>>, buffer: io::Cursor<Vec<u8>>,
byte_order: ByteOrder,
} }
impl JpegReader { impl JpegReader {
/// Constructs new JpegReader wrapping a SmartReader. /// Constructs new JpegReader wrapping a SmartReader.
@@ -442,8 +256,6 @@ impl JpegReader {
where where
R: Read + Seek, R: Read + Seek,
{ {
let order = reader.byte_order;
// Read jpeg image data // Read jpeg image data
let mut segment = vec![0; length as usize]; let mut segment = vec![0; length as usize];
reader.read_exact(&mut segment[..])?; reader.read_exact(&mut segment[..])?;
@@ -453,16 +265,14 @@ impl JpegReader {
let mut jpeg_data = tables.clone(); let mut jpeg_data = tables.clone();
let truncated_length = jpeg_data.len() - 2; let truncated_length = jpeg_data.len() - 2;
jpeg_data.truncate(truncated_length); jpeg_data.truncate(truncated_length);
jpeg_data.extend_from_slice(&mut segment[2..]); jpeg_data.extend_from_slice(&segment[2..]);
Ok(JpegReader { Ok(JpegReader {
buffer: io::Cursor::new(jpeg_data), buffer: io::Cursor::new(jpeg_data),
byte_order: order,
}) })
} }
None => Ok(JpegReader { None => Ok(JpegReader {
buffer: io::Cursor::new(segment), 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 /// ## PackBits Reader
/// ///
@@ -489,58 +292,46 @@ impl EndianReader for JpegReader {
/// Reader that unpacks Apple's `PackBits` format /// Reader that unpacks Apple's `PackBits` format
pub struct PackBitsReader { pub struct PackBitsReader {
buffer: io::Cursor<Vec<u8>>, buffer: io::Cursor<Vec<u8>>,
byte_order: ByteOrder,
} }
impl PackBitsReader { impl PackBitsReader {
/// Wraps a reader /// Wraps a reader
pub fn new<R: Read + Seek>( pub fn new<R: Read + Seek>(
mut reader: R, mut reader: R,
byte_order: ByteOrder,
length: usize, length: usize,
) -> io::Result<(usize, PackBitsReader)> { ) -> io::Result<(usize, PackBitsReader)> {
let mut buffer = Vec::new(); let mut buffer = Vec::new();
let mut read: usize = 0; let mut header: [u8; 1] = [0];
while read < length { let mut data: [u8; 1] = [0];
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,
},
))
}
}
fn read_packbits_run<R: Read + Seek>(reader: &mut R, buffer: &mut Vec<u8>) -> io::Result<usize> { let mut bytes_read = 0;
let mut header: [u8; 1] = [0]; while bytes_read < length {
reader.read_exact(&mut header)?;
bytes_read += 1;
let bytes = reader.read(&mut header)?; let h = header[0] as i8;
if h >= -127 && h <= -1 {
match bytes {
0 => Ok(0),
_ => match header[0] as i8 {
-128 => Ok(1),
h if h >= -127 && h <= -1 => {
let new_len = buffer.len() + (1 - h as isize) as usize; let new_len = buffer.len() + (1 - h as isize) as usize;
reader.read_exact(&mut header)?; reader.read_exact(&mut data)?;
buffer.resize(new_len, header[0]); buffer.resize(new_len, data[0]);
Ok(2) bytes_read += 1;
} } else if h >= 0 {
h => {
let num_vals = h as usize + 1; let num_vals = h as usize + 1;
let start = buffer.len(); let start = buffer.len();
buffer.resize(start + num_vals, 0); buffer.resize(start + num_vals, 0);
reader.read_exact(&mut buffer[start..])?; 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 /// ## SmartReader Reader
/// ///
@@ -566,7 +350,7 @@ impl EndianReader for PackBitsReader {
#[derive(Debug)] #[derive(Debug)]
pub struct SmartReader<R> pub struct SmartReader<R>
where where
R: Read + Seek, R: Read,
{ {
reader: R, reader: R,
pub byte_order: ByteOrder, pub byte_order: ByteOrder,
@@ -574,7 +358,7 @@ where
impl<R> SmartReader<R> impl<R> SmartReader<R>
where where
R: Read + Seek, R: Read,
{ {
/// Wraps a reader /// Wraps a reader
pub fn wrap(reader: R, byte_order: ByteOrder) -> SmartReader<R> { pub fn wrap(reader: R, byte_order: ByteOrder) -> SmartReader<R> {
@@ -584,7 +368,7 @@ where
impl<R> EndianReader for SmartReader<R> impl<R> EndianReader for SmartReader<R>
where where
R: Read + Seek, R: Read,
{ {
#[inline(always)] #[inline(always)]
fn byte_order(&self) -> ByteOrder { fn byte_order(&self) -> ByteOrder {
@@ -592,7 +376,7 @@ where
} }
} }
impl<R: Read + Seek> Read for SmartReader<R> { impl<R: Read> Read for SmartReader<R> {
#[inline] #[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.reader.read(buf) self.reader.read(buf)
@@ -619,8 +403,7 @@ mod test {
let encoded_len = encoded.len(); let encoded_len = encoded.len();
let buff = io::Cursor::new(encoded); let buff = io::Cursor::new(encoded);
let (_, mut decoder) = let (_, mut decoder) = PackBitsReader::new(buff, encoded_len).unwrap();
PackBitsReader::new(buff, ByteOrder::LittleEndian, encoded_len).unwrap();
let mut decoded = Vec::new(); let mut decoded = Vec::new();
decoder.read_to_end(&mut decoded).unwrap(); decoder.read_to_end(&mut decoded).unwrap();