Merge remote-tracking branch 'upstream/master' into tiles
This commit is contained in:
commit
d4ce174236
2 files changed
+383
-622
No files matched your search
+348
-370
@@ -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) {
|
||||||
|
|||||||
+35
-252
@@ -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;
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_packbits_run<R: Read + Seek>(reader: &mut R, buffer: &mut Vec<u8>) -> io::Result<usize> {
|
|
||||||
let mut header: [u8; 1] = [0];
|
let mut header: [u8; 1] = [0];
|
||||||
|
let mut data: [u8; 1] = [0];
|
||||||
|
|
||||||
let bytes = reader.read(&mut header)?;
|
let mut bytes_read = 0;
|
||||||
|
while bytes_read < length {
|
||||||
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;
|
|
||||||
reader.read_exact(&mut header)?;
|
reader.read_exact(&mut header)?;
|
||||||
buffer.resize(new_len, header[0]);
|
bytes_read += 1;
|
||||||
Ok(2)
|
|
||||||
}
|
let h = header[0] as i8;
|
||||||
h => {
|
if h >= -127 && h <= -1 {
|
||||||
|
let new_len = buffer.len() + (1 - h as isize) as usize;
|
||||||
|
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 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();
|
||||||
|
|||||||
Reference in new issue
Block a user