Do a clippy pass
This commit is contained in:
1 parent
2b12c1b162
commit
bf24b3f935
10 files changed
+352
-225
No files matched your search
+30
-23
@@ -1,7 +1,7 @@
|
||||
//! Function for reading TIFF tags
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::convert::{TryInto, TryFrom};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::io::{self, Read, Seek};
|
||||
use std::mem;
|
||||
|
||||
@@ -9,8 +9,10 @@ use super::stream::{ByteOrder, EndianReader, SmartReader};
|
||||
use tags::{Tag, Type};
|
||||
use {TiffError, TiffFormatError, TiffResult, TiffUnsupportedError};
|
||||
|
||||
use self::Value::{Ascii, List, Float, Double, Rational, Unsigned, Signed, SRational, RationalBig, UnsignedBig, SignedBig, SRationalBig};
|
||||
|
||||
use self::Value::{
|
||||
Ascii, Double, Float, List, Rational, RationalBig, SRational, SRationalBig, Signed, SignedBig,
|
||||
Unsigned, UnsignedBig,
|
||||
};
|
||||
|
||||
#[allow(unused_qualifications)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@@ -102,7 +104,9 @@ impl Value {
|
||||
Unsigned(val) => Ok(vec![val]),
|
||||
UnsignedBig(val) => Ok(vec![u32::try_from(val)?]),
|
||||
Rational(numerator, denominator) => Ok(vec![numerator, denominator]),
|
||||
RationalBig(numerator, denominator) => Ok(vec![u32::try_from(numerator)?, u32::try_from(denominator)?]),
|
||||
RationalBig(numerator, denominator) => {
|
||||
Ok(vec![u32::try_from(numerator)?, u32::try_from(denominator)?])
|
||||
}
|
||||
Ascii(val) => Ok(val.chars().map(u32::from).collect()),
|
||||
val => Err(TiffError::FormatError(
|
||||
TiffFormatError::UnsignedIntegerExpected(val),
|
||||
@@ -132,7 +136,9 @@ impl Value {
|
||||
Signed(val) => Ok(vec![val]),
|
||||
SignedBig(val) => Ok(vec![i32::try_from(val)?]),
|
||||
SRational(numerator, denominator) => Ok(vec![numerator, denominator]),
|
||||
SRationalBig(numerator, denominator) => Ok(vec![i32::try_from(numerator)?, i32::try_from(denominator)?]),
|
||||
SRationalBig(numerator, denominator) => {
|
||||
Ok(vec![i32::try_from(numerator)?, i32::try_from(denominator)?])
|
||||
}
|
||||
val => Err(TiffError::FormatError(
|
||||
TiffFormatError::SignedIntegerExpected(val),
|
||||
)),
|
||||
@@ -220,7 +226,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Entry {
|
||||
type_: Type,
|
||||
@@ -309,17 +315,11 @@ impl Entry {
|
||||
}
|
||||
(Type::LONG, 2) => {
|
||||
let mut r = self.r(bo);
|
||||
Some(List(vec![
|
||||
Unsigned(r.read_u32()?),
|
||||
Unsigned(r.read_u32()?),
|
||||
]))
|
||||
Some(List(vec![Unsigned(r.read_u32()?), Unsigned(r.read_u32()?)]))
|
||||
}
|
||||
(Type::SLONG, 2) => {
|
||||
let mut r = self.r(bo);
|
||||
Some(List(vec![
|
||||
Signed(r.read_i32()?),
|
||||
Signed(r.read_i32()?),
|
||||
]))
|
||||
Some(List(vec![Signed(r.read_i32()?), Signed(r.read_i32()?)]))
|
||||
}
|
||||
(Type::RATIONAL, 1) => {
|
||||
let mut r = self.r(bo);
|
||||
@@ -333,7 +333,7 @@ impl Entry {
|
||||
let denominator = r.read_i32()?;
|
||||
Some(SRational(numerator, denominator))
|
||||
}
|
||||
_ => None
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
@@ -409,10 +409,10 @@ impl Entry {
|
||||
if n > limits.decoding_buffer_size {
|
||||
return Err(TiffError::LimitsExceeded);
|
||||
}
|
||||
|
||||
|
||||
if (n <= 4 && !decoder.bigtiff) || (n <= 8 && decoder.bigtiff) {
|
||||
let mut buf = vec![0; n];
|
||||
self.r(bo).read_exact(&mut buf )?;
|
||||
self.r(bo).read_exact(&mut buf)?;
|
||||
let v = String::from_utf8(buf)?;
|
||||
let v = v.trim_matches(char::from(0));
|
||||
Ok(Ascii(v.into()))
|
||||
@@ -434,10 +434,17 @@ impl Entry {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn decode_offset<R, F>(&self, value_count: u64, bo: ByteOrder, limits: &super::Limits, decoder: &mut super::Decoder<R>, decode_fn: F) -> TiffResult<Value>
|
||||
where
|
||||
R: Read + Seek,
|
||||
F: Fn(&mut super::Decoder<R>) -> TiffResult<Value>,
|
||||
fn decode_offset<R, F>(
|
||||
&self,
|
||||
value_count: u64,
|
||||
bo: ByteOrder,
|
||||
limits: &super::Limits,
|
||||
decoder: &mut super::Decoder<R>,
|
||||
decode_fn: F,
|
||||
) -> TiffResult<Value>
|
||||
where
|
||||
R: Read + Seek,
|
||||
F: Fn(&mut super::Decoder<R>) -> TiffResult<Value>,
|
||||
{
|
||||
let value_count = usize::try_from(value_count)?;
|
||||
if value_count > limits.decoding_buffer_size / mem::size_of::<Value>() {
|
||||
@@ -464,7 +471,7 @@ fn offset_to_bytes(n: usize, entry: &Entry) -> TiffResult<Value> {
|
||||
entry.offset[0..n]
|
||||
.iter()
|
||||
.map(|&e| Unsigned(u32::from(e)))
|
||||
.collect()
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -475,7 +482,7 @@ fn offset_to_sbytes(n: usize, entry: &Entry) -> TiffResult<Value> {
|
||||
entry.offset[0..n]
|
||||
.iter()
|
||||
.map(|&e| Signed(i32::from(e as i8)))
|
||||
.collect()
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
+103
-97
@@ -1,14 +1,16 @@
|
||||
use std::convert::TryFrom;
|
||||
use std::collections::HashMap;
|
||||
use std::io::{self, Read, Seek};
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::io::{self, Read, Seek};
|
||||
|
||||
use {ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError};
|
||||
|
||||
use self::ifd::Directory;
|
||||
use tags::{CompressionMethod, PhotometricInterpretation, Predictor, SampleFormat, Tag, Type};
|
||||
|
||||
use self::stream::{ByteOrder, EndianReader, LZWReader, DeflateReader, PackBitsReader, SmartReader};
|
||||
use self::stream::{
|
||||
ByteOrder, DeflateReader, EndianReader, LZWReader, PackBitsReader, SmartReader,
|
||||
};
|
||||
|
||||
pub mod ifd;
|
||||
mod stream;
|
||||
@@ -263,8 +265,14 @@ fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType)
|
||||
let samples = match color_type {
|
||||
ColorType::Gray(8) | ColorType::Gray(16) | ColorType::Gray(32) | ColorType::Gray(64) => 1,
|
||||
ColorType::RGB(8) | ColorType::RGB(16) | ColorType::RGB(32) | ColorType::RGB(64) => 3,
|
||||
ColorType::RGBA(8) | ColorType::RGBA(16) | ColorType::RGBA(32) | ColorType::RGBA(64)
|
||||
| ColorType::CMYK(8) | ColorType::CMYK(16) | ColorType::CMYK(32) | ColorType::CMYK(64) => 4,
|
||||
ColorType::RGBA(8)
|
||||
| ColorType::RGBA(16)
|
||||
| ColorType::RGBA(32)
|
||||
| ColorType::RGBA(64)
|
||||
| ColorType::CMYK(8)
|
||||
| ColorType::CMYK(16)
|
||||
| ColorType::CMYK(32)
|
||||
| ColorType::CMYK(64) => 4,
|
||||
_ => {
|
||||
return Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::HorizontalPredictor(color_type),
|
||||
@@ -289,7 +297,7 @@ fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType)
|
||||
// See issue #89.
|
||||
// rev_hpredict_nsamp(buf, size, samples)?;
|
||||
return Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::HorizontalPredictor(color_type)
|
||||
TiffUnsupportedError::HorizontalPredictor(color_type),
|
||||
));
|
||||
}
|
||||
DecodingBuffer::F64(_buf) => {
|
||||
@@ -297,7 +305,7 @@ fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType)
|
||||
// See issue #89.
|
||||
// rev_hpredict_nsamp(buf, size, samples)?;
|
||||
return Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::HorizontalPredictor(color_type)
|
||||
TiffUnsupportedError::HorizontalPredictor(color_type),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -337,28 +345,24 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
|
||||
pub fn colortype(&mut self) -> TiffResult<ColorType> {
|
||||
match self.photometric_interpretation {
|
||||
PhotometricInterpretation::RGB => {
|
||||
match self.bits_per_sample[..] {
|
||||
[r, g, b] if [r, r] == [g, b] => Ok(ColorType::RGB(r)),
|
||||
[r, g, b, a] if [r, r, r] == [g, b, a] => Ok(ColorType::RGBA(r)),
|
||||
_ => Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::InterpretationWithBits(
|
||||
self.photometric_interpretation,
|
||||
self.bits_per_sample.clone(),
|
||||
),
|
||||
)),
|
||||
}
|
||||
PhotometricInterpretation::RGB => match self.bits_per_sample[..] {
|
||||
[r, g, b] if [r, r] == [g, b] => Ok(ColorType::RGB(r)),
|
||||
[r, g, b, a] if [r, r, r] == [g, b, a] => Ok(ColorType::RGBA(r)),
|
||||
_ => Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::InterpretationWithBits(
|
||||
self.photometric_interpretation,
|
||||
self.bits_per_sample.clone(),
|
||||
),
|
||||
)),
|
||||
},
|
||||
PhotometricInterpretation::CMYK => {
|
||||
match self.bits_per_sample[..] {
|
||||
[c, m, y, k] if [c, c, c] == [m, y, k] => Ok(ColorType::CMYK(c)),
|
||||
_ => Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::InterpretationWithBits(
|
||||
self.photometric_interpretation,
|
||||
self.bits_per_sample.clone(),
|
||||
),
|
||||
)),
|
||||
}
|
||||
PhotometricInterpretation::CMYK => match self.bits_per_sample[..] {
|
||||
[c, m, y, k] if [c, c, c] == [m, y, k] => Ok(ColorType::CMYK(c)),
|
||||
_ => Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::InterpretationWithBits(
|
||||
self.photometric_interpretation,
|
||||
self.bits_per_sample.clone(),
|
||||
),
|
||||
)),
|
||||
},
|
||||
PhotometricInterpretation::BlackIsZero | PhotometricInterpretation::WhiteIsZero
|
||||
if self.bits_per_sample.len() == 1 =>
|
||||
@@ -402,18 +406,20 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
if self.read_short()? != 8 {
|
||||
return Err(TiffError::FormatError(
|
||||
TiffFormatError::TiffSignatureNotFound,
|
||||
))
|
||||
));
|
||||
}
|
||||
// This constant should always be 0
|
||||
if self.read_short()? != 0 {
|
||||
return Err(TiffError::FormatError(
|
||||
TiffFormatError::TiffSignatureNotFound,
|
||||
))
|
||||
));
|
||||
}
|
||||
},
|
||||
_ => return Err(TiffError::FormatError(
|
||||
TiffFormatError::TiffSignatureInvalid,
|
||||
))
|
||||
}
|
||||
_ => {
|
||||
return Err(TiffError::FormatError(
|
||||
TiffFormatError::TiffSignatureInvalid,
|
||||
))
|
||||
}
|
||||
}
|
||||
self.next_ifd = match self.read_ifd_offset()? {
|
||||
0 => None,
|
||||
@@ -451,19 +457,25 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
self.samples = val;
|
||||
}
|
||||
if let Some(vals) = self.find_tag_unsigned_vec(Tag::SampleFormat)? {
|
||||
self.sample_format = vals.into_iter()
|
||||
self.sample_format = vals
|
||||
.into_iter()
|
||||
.map(SampleFormat::from_u16_exhaustive)
|
||||
.collect();
|
||||
|
||||
// TODO: for now, only homogenous formats across samples are supported.
|
||||
if !self.sample_format.windows(2).all(|s| s[0] == s[1]) {
|
||||
return Err(TiffUnsupportedError::UnsupportedSampleFormat(self.sample_format.clone()).into())
|
||||
return Err(TiffUnsupportedError::UnsupportedSampleFormat(
|
||||
self.sample_format.clone(),
|
||||
)
|
||||
.into());
|
||||
}
|
||||
}
|
||||
match self.samples {
|
||||
1 | 3 | 4 => if let Some(val) = self.find_tag_unsigned_vec(Tag::BitsPerSample)? {
|
||||
self.bits_per_sample = val;
|
||||
},
|
||||
1 | 3 | 4 => {
|
||||
if let Some(val) = self.find_tag_unsigned_vec(Tag::BitsPerSample)? {
|
||||
self.bits_per_sample = val;
|
||||
}
|
||||
}
|
||||
_ => return Err(TiffUnsupportedError::UnsupportedSampleDepth(self.samples).into()),
|
||||
}
|
||||
Ok(())
|
||||
@@ -553,7 +565,9 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
#[inline]
|
||||
pub fn read_offset(&mut self) -> TiffResult<[u8; 4]> {
|
||||
if self.bigtiff {
|
||||
return Err(TiffError::FormatError(TiffFormatError::InconsistentSizesEncountered))
|
||||
return Err(TiffError::FormatError(
|
||||
TiffFormatError::InconsistentSizesEncountered,
|
||||
));
|
||||
}
|
||||
let mut val = [0; 4];
|
||||
self.reader.read_exact(&mut val)?;
|
||||
@@ -576,9 +590,7 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
|
||||
#[inline]
|
||||
pub fn goto_offset_u64(&mut self, offset: u64) -> io::Result<()> {
|
||||
self.reader
|
||||
.seek(io::SeekFrom::Start(offset))
|
||||
.map(|_| ())
|
||||
self.reader.seek(io::SeekFrom::Start(offset)).map(|_| ())
|
||||
}
|
||||
|
||||
/// Reads a IFD entry.
|
||||
@@ -600,22 +612,11 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
}
|
||||
};
|
||||
let entry = if self.bigtiff {
|
||||
ifd::Entry::new_u64(
|
||||
type_,
|
||||
self.read_long8()?,
|
||||
self.read_offset_u64()?
|
||||
)
|
||||
ifd::Entry::new_u64(type_, self.read_long8()?, self.read_offset_u64()?)
|
||||
} else {
|
||||
ifd::Entry::new(
|
||||
type_,
|
||||
self.read_long()?,
|
||||
self.read_offset()?
|
||||
)
|
||||
ifd::Entry::new(type_, self.read_long()?, self.read_offset()?)
|
||||
};
|
||||
Ok(Some((
|
||||
tag,
|
||||
entry,
|
||||
)))
|
||||
Ok(Some((tag, entry)))
|
||||
}
|
||||
|
||||
/// Reads the next IFD
|
||||
@@ -629,7 +630,11 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
}
|
||||
Some(offset) => self.goto_offset_u64(offset)?,
|
||||
}
|
||||
let num_tags = if self.bigtiff { self.read_long8()? } else { self.read_short()?.into() };
|
||||
let num_tags = if self.bigtiff {
|
||||
self.read_long8()?
|
||||
} else {
|
||||
self.read_short()?.into()
|
||||
};
|
||||
for _ in 0..num_tags {
|
||||
let (tag, entry) = match self.read_entry()? {
|
||||
Some(val) => val,
|
||||
@@ -660,20 +665,30 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
/// Tries to retrieve a tag and convert it to the desired unsigned type.
|
||||
pub fn find_tag_unsigned<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<Option<T>> {
|
||||
self.find_tag(tag)?
|
||||
.map(|v| v.into_u64()).transpose()?
|
||||
.map(|value| T::try_from(value)
|
||||
.map_err(|_| TiffFormatError::InvalidTagValueType(tag).into()))
|
||||
.map(|v| v.into_u64())
|
||||
.transpose()?
|
||||
.map(|value| {
|
||||
T::try_from(value).map_err(|_| TiffFormatError::InvalidTagValueType(tag).into())
|
||||
})
|
||||
.transpose()
|
||||
}
|
||||
|
||||
/// Tries to retrieve a vector of all a tag's values and convert them to
|
||||
/// the desired unsigned type.
|
||||
pub fn find_tag_unsigned_vec<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<Option<Vec<T>>> {
|
||||
pub fn find_tag_unsigned_vec<T: TryFrom<u64>>(
|
||||
&mut self,
|
||||
tag: Tag,
|
||||
) -> TiffResult<Option<Vec<T>>> {
|
||||
self.find_tag(tag)?
|
||||
.map(|v| v.into_u64_vec()).transpose()?
|
||||
.map(|v| v.into_iter()
|
||||
.map(|u| T::try_from(u).map_err(|_| TiffFormatError::InvalidTagValueType(tag).into()))
|
||||
.collect())
|
||||
.map(|v| v.into_u64_vec())
|
||||
.transpose()?
|
||||
.map(|v| {
|
||||
v.into_iter()
|
||||
.map(|u| {
|
||||
T::try_from(u).map_err(|_| TiffFormatError::InvalidTagValueType(tag).into())
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.transpose()
|
||||
}
|
||||
|
||||
@@ -754,21 +769,19 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
let (bytes, reader) = LZWReader::new(
|
||||
&mut self.reader,
|
||||
usize::try_from(length)?,
|
||||
max_uncompressed_length * buffer.byte_len()
|
||||
max_uncompressed_length * buffer.byte_len(),
|
||||
)?;
|
||||
(bytes, Box::new(reader))
|
||||
}
|
||||
CompressionMethod::PackBits => {
|
||||
let order = self.reader.byte_order;
|
||||
let (bytes, reader) = PackBitsReader::new(
|
||||
&mut self.reader,
|
||||
order,
|
||||
usize::try_from(length)?,
|
||||
)?;
|
||||
let (bytes, reader) =
|
||||
PackBitsReader::new(&mut self.reader, order, usize::try_from(length)?)?;
|
||||
(bytes, Box::new(reader))
|
||||
}
|
||||
CompressionMethod::OldDeflate => {
|
||||
let (bytes, reader) = DeflateReader::new(&mut self.reader, max_uncompressed_length)?;
|
||||
let (bytes, reader) =
|
||||
DeflateReader::new(&mut self.reader, max_uncompressed_length)?;
|
||||
(bytes, Box::new(reader))
|
||||
}
|
||||
method => {
|
||||
@@ -887,9 +900,7 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
|
||||
/// Number of strips in image
|
||||
pub fn strip_count(&mut self) -> TiffResult<u32> {
|
||||
let rows_per_strip = self
|
||||
.get_tag_u32(Tag::RowsPerStrip)
|
||||
.unwrap_or(self.height);
|
||||
let rows_per_strip = self.get_tag_u32(Tag::RowsPerStrip).unwrap_or(self.height);
|
||||
|
||||
if rows_per_strip == 0 {
|
||||
return Ok(0);
|
||||
@@ -935,9 +946,8 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
TiffFormatError::InconsistentSizesEncountered,
|
||||
))?;
|
||||
|
||||
let rows_per_strip = usize::try_from(self
|
||||
.get_tag_u32(Tag::RowsPerStrip)
|
||||
.unwrap_or(self.height))?;
|
||||
let rows_per_strip =
|
||||
usize::try_from(self.get_tag_u32(Tag::RowsPerStrip).unwrap_or(self.height))?;
|
||||
|
||||
let strip_height = cmp::min(
|
||||
rows_per_strip,
|
||||
@@ -996,22 +1006,20 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
n if n <= 16 => DecodingResult::new_u16(buffer_size, &self.limits),
|
||||
n if n <= 32 => DecodingResult::new_u32(buffer_size, &self.limits),
|
||||
n if n <= 64 => DecodingResult::new_u64(buffer_size, &self.limits),
|
||||
n => {
|
||||
Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::UnsupportedBitsPerChannel(n),
|
||||
))
|
||||
}
|
||||
n => Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::UnsupportedBitsPerChannel(n),
|
||||
)),
|
||||
},
|
||||
SampleFormat::IEEEFP => match max_sample_bits {
|
||||
32 => DecodingResult::new_f32(buffer_size, &self.limits),
|
||||
64 => DecodingResult::new_f64(buffer_size, &self.limits),
|
||||
n => {
|
||||
Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::UnsupportedBitsPerChannel(n),
|
||||
))
|
||||
}
|
||||
n => Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::UnsupportedBitsPerChannel(n),
|
||||
)),
|
||||
},
|
||||
format => Err(TiffUnsupportedError::UnsupportedSampleFormat(vec![format.clone()]).into()),
|
||||
format => {
|
||||
Err(TiffUnsupportedError::UnsupportedSampleFormat(vec![format.clone()]).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1020,9 +1028,8 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
self.initialize_strip_decoder()?;
|
||||
let index = self.strip_decoder.as_ref().unwrap().strip_index;
|
||||
|
||||
let rows_per_strip = usize::try_from(self
|
||||
.get_tag_u32(Tag::RowsPerStrip)
|
||||
.unwrap_or(self.height))?;
|
||||
let rows_per_strip =
|
||||
usize::try_from(self.get_tag_u32(Tag::RowsPerStrip).unwrap_or(self.height))?;
|
||||
|
||||
let strip_height = cmp::min(
|
||||
rows_per_strip,
|
||||
@@ -1039,9 +1046,8 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
/// Decodes the entire image and return it as a Vector
|
||||
pub fn read_image(&mut self) -> TiffResult<DecodingResult> {
|
||||
self.initialize_strip_decoder()?;
|
||||
let rows_per_strip = usize::try_from(self
|
||||
.get_tag_u32(Tag::RowsPerStrip)
|
||||
.unwrap_or(self.height))?;
|
||||
let rows_per_strip =
|
||||
usize::try_from(self.get_tag_u32(Tag::RowsPerStrip).unwrap_or(self.height))?;
|
||||
|
||||
let samples_per_strip =
|
||||
usize::try_from(self.width)? * rows_per_strip * self.bits_per_sample.len();
|
||||
|
||||
+41
-26
@@ -34,14 +34,16 @@ pub trait EndianReader: Read {
|
||||
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 =>
|
||||
ByteOrder::LittleEndian => {
|
||||
for n in buffer {
|
||||
*n = u16::from_le(*n);
|
||||
},
|
||||
ByteOrder::BigEndian =>
|
||||
}
|
||||
}
|
||||
ByteOrder::BigEndian => {
|
||||
for n in buffer {
|
||||
*n = u16::from_be(*n);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -72,14 +74,16 @@ pub trait EndianReader: Read {
|
||||
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 =>
|
||||
ByteOrder::LittleEndian => {
|
||||
for n in buffer {
|
||||
*n = u32::from_le(*n);
|
||||
},
|
||||
ByteOrder::BigEndian =>
|
||||
}
|
||||
}
|
||||
ByteOrder::BigEndian => {
|
||||
for n in buffer {
|
||||
*n = u32::from_be(*n);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -110,14 +114,16 @@ pub trait EndianReader: Read {
|
||||
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 =>
|
||||
ByteOrder::LittleEndian => {
|
||||
for n in buffer {
|
||||
*n = u64::from_le(*n);
|
||||
},
|
||||
ByteOrder::BigEndian =>
|
||||
}
|
||||
}
|
||||
ByteOrder::BigEndian => {
|
||||
for n in buffer {
|
||||
*n = u64::from_be(*n);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -137,14 +143,16 @@ pub trait EndianReader: Read {
|
||||
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 =>
|
||||
ByteOrder::LittleEndian => {
|
||||
for n in buffer {
|
||||
*n = f32::from_bits(u32::from_le(n.to_bits()));
|
||||
},
|
||||
ByteOrder::BigEndian =>
|
||||
}
|
||||
}
|
||||
ByteOrder::BigEndian => {
|
||||
for n in buffer {
|
||||
*n = f32::from_bits(u32::from_be(n.to_bits()));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -164,14 +172,16 @@ pub trait EndianReader: Read {
|
||||
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 =>
|
||||
ByteOrder::LittleEndian => {
|
||||
for n in buffer {
|
||||
*n = f64::from_bits(u64::from_le(n.to_bits()));
|
||||
},
|
||||
ByteOrder::BigEndian =>
|
||||
}
|
||||
}
|
||||
ByteOrder::BigEndian => {
|
||||
for n in buffer {
|
||||
*n = f64::from_bits(u64::from_be(n.to_bits()));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -251,17 +261,22 @@ impl LZWReader {
|
||||
let buffer_space = uncompressed.capacity();
|
||||
uncompressed.resize(buffer_space, 0u8);
|
||||
|
||||
let result = decoder.decode_bytes(&compressed[bytes_read..], &mut uncompressed[bytes_written..]);
|
||||
let result = decoder.decode_bytes(
|
||||
&compressed[bytes_read..],
|
||||
&mut uncompressed[bytes_written..],
|
||||
);
|
||||
bytes_read += result.consumed_in;
|
||||
uncompressed.truncate(bytes_written + result.consumed_out);
|
||||
|
||||
match result.status {
|
||||
Ok(weezl::LzwStatus::Ok) => {},
|
||||
Ok(weezl::LzwStatus::Ok) => {}
|
||||
Ok(weezl::LzwStatus::Done) => break,
|
||||
Ok(weezl::LzwStatus::NoProgress) => return Err(io::Error::new(
|
||||
io::ErrorKind::UnexpectedEof,
|
||||
"no lzw end code found",
|
||||
)),
|
||||
Ok(weezl::LzwStatus::NoProgress) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::UnexpectedEof,
|
||||
"no lzw end code found",
|
||||
))
|
||||
}
|
||||
Err(err) => return Err(io::Error::new(io::ErrorKind::InvalidData, err)),
|
||||
}
|
||||
}
|
||||
|
||||
+34
-14
@@ -4,8 +4,8 @@ use std::io::{Seek, Write};
|
||||
use std::mem;
|
||||
|
||||
use bytecast;
|
||||
use tags::{self, ResolutionUnit, Tag, Type};
|
||||
use error::{TiffError, TiffFormatError, TiffResult};
|
||||
use tags::{self, ResolutionUnit, Tag, Type};
|
||||
|
||||
pub mod colortype;
|
||||
mod writer;
|
||||
@@ -495,8 +495,10 @@ impl<'a, W: 'a + Write + Seek> DirectoryEncoder<'a, W> {
|
||||
value.write(&mut writer)?;
|
||||
}
|
||||
|
||||
self.ifd
|
||||
.insert(tag.to_u16(), (<T>::FIELD_TYPE.to_u16(), value.count(), bytes));
|
||||
self.ifd.insert(
|
||||
tag.to_u16(),
|
||||
(<T>::FIELD_TYPE.to_u16(), value.count(), bytes),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -636,7 +638,10 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
|
||||
|
||||
encoder.write_tag(Tag::RowsPerStrip, u32::try_from(rows_per_strip)?)?;
|
||||
|
||||
encoder.write_tag(Tag::SamplesPerPixel, u16::try_from(<T>::BITS_PER_SAMPLE.len())?)?;
|
||||
encoder.write_tag(
|
||||
Tag::SamplesPerPixel,
|
||||
u16::try_from(<T>::BITS_PER_SAMPLE.len())?,
|
||||
)?;
|
||||
encoder.write_tag(Tag::XResolution, Rational { n: 1, d: 1 })?;
|
||||
encoder.write_tag(Tag::YResolution, Rational { n: 1, d: 1 })?;
|
||||
encoder.write_tag(Tag::ResolutionUnit, ResolutionUnit::None.to_u16())?;
|
||||
@@ -662,7 +667,8 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let start_row = ::std::cmp::min(u64::from(self.height), self.strip_idx * self.rows_per_strip);
|
||||
let start_row =
|
||||
::std::cmp::min(u64::from(self.height), self.strip_idx * self.rows_per_strip);
|
||||
let end_row = ::std::cmp::min(
|
||||
u64::from(self.height),
|
||||
(self.strip_idx + 1) * self.rows_per_strip,
|
||||
@@ -681,7 +687,9 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
|
||||
if u64::try_from(value.len())? != samples {
|
||||
return Err(::std::io::Error::new(
|
||||
::std::io::ErrorKind::InvalidData,
|
||||
"Slice is wrong size for strip").into());
|
||||
"Slice is wrong size for strip",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let offset = self.encoder.write_data(value)?;
|
||||
@@ -697,14 +705,20 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
|
||||
where
|
||||
[T::Inner]: TiffValue,
|
||||
{
|
||||
let num_pix = usize::try_from(self.width)?.checked_mul(usize::try_from(self.height)?)
|
||||
.ok_or_else(|| ::std::io::Error::new(
|
||||
::std::io::ErrorKind::InvalidInput,
|
||||
"Image width * height exceeds usize"))?;
|
||||
let num_pix = usize::try_from(self.width)?
|
||||
.checked_mul(usize::try_from(self.height)?)
|
||||
.ok_or_else(|| {
|
||||
::std::io::Error::new(
|
||||
::std::io::ErrorKind::InvalidInput,
|
||||
"Image width * height exceeds usize",
|
||||
)
|
||||
})?;
|
||||
if data.len() < num_pix {
|
||||
return Err(::std::io::Error::new(
|
||||
::std::io::ErrorKind::InvalidData,
|
||||
"Input data slice is undersized for provided dimensions").into());
|
||||
"Input data slice is undersized for provided dimensions",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
let mut idx = 0;
|
||||
while self.next_strip_sample_count() > 0 {
|
||||
@@ -718,14 +732,20 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
|
||||
|
||||
/// Set image resolution
|
||||
pub fn resolution(&mut self, unit: ResolutionUnit, value: Rational) {
|
||||
self.encoder.write_tag(Tag::ResolutionUnit, unit.to_u16()).unwrap();
|
||||
self.encoder.write_tag(Tag::XResolution, value.clone()).unwrap();
|
||||
self.encoder
|
||||
.write_tag(Tag::ResolutionUnit, unit.to_u16())
|
||||
.unwrap();
|
||||
self.encoder
|
||||
.write_tag(Tag::XResolution, value.clone())
|
||||
.unwrap();
|
||||
self.encoder.write_tag(Tag::YResolution, value).unwrap();
|
||||
}
|
||||
|
||||
/// Set image resolution unit
|
||||
pub fn resolution_unit(&mut self, unit: ResolutionUnit) {
|
||||
self.encoder.write_tag(Tag::ResolutionUnit, unit.to_u16()).unwrap();
|
||||
self.encoder
|
||||
.write_tag(Tag::ResolutionUnit, unit.to_u16())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Set image x-resolution
|
||||
|
||||
+5
-4
@@ -3,9 +3,9 @@ use std::fmt;
|
||||
use std::io;
|
||||
use std::string;
|
||||
|
||||
use decoder::ifd::{Value};
|
||||
use tags::{CompressionMethod, PhotometricInterpretation, PlanarConfiguration, SampleFormat, Tag};
|
||||
use decoder::ifd::Value;
|
||||
use miniz_oxide::inflate::TINFLStatus;
|
||||
use tags::{CompressionMethod, PhotometricInterpretation, PlanarConfiguration, SampleFormat, Tag};
|
||||
use ColorType;
|
||||
|
||||
/// Tiff error kinds.
|
||||
@@ -62,8 +62,9 @@ impl fmt::Display for TiffFormatError {
|
||||
ImageFileDirectoryNotFound => write!(fmt, "Image file directory not found."),
|
||||
InconsistentSizesEncountered => write!(fmt, "Inconsistent sizes encountered."),
|
||||
InvalidTag => write!(fmt, "Image contains invalid tag."),
|
||||
InvalidTagValueType(ref tag) =>
|
||||
write!(fmt, "Tag `{:?}` did not have the expected value type.", tag),
|
||||
InvalidTagValueType(ref tag) => {
|
||||
write!(fmt, "Tag `{:?}` did not have the expected value type.", tag)
|
||||
}
|
||||
RequiredTagNotFound(ref tag) => write!(fmt, "Required tag `{:?}` not found.", tag),
|
||||
UnknownPredictor(ref predictor) => {
|
||||
write!(fmt, "Unknown predictor “{}” encountered", predictor)
|
||||
|
||||
+1
-1
@@ -6,8 +6,8 @@
|
||||
//! # Related Links
|
||||
//! * <https://www.adobe.io/open/standards/TIFF.html> - The TIFF specification
|
||||
|
||||
extern crate weezl;
|
||||
extern crate miniz_oxide;
|
||||
extern crate weezl;
|
||||
|
||||
mod bytecast;
|
||||
pub mod decoder;
|
||||
|
||||
+2
-3
@@ -140,7 +140,6 @@ pub enum Type(u16) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tags! {
|
||||
pub enum CompressionMethod(u16) {
|
||||
None = 1,
|
||||
@@ -182,7 +181,7 @@ pub enum Predictor(u16) {
|
||||
}
|
||||
}
|
||||
|
||||
tags!{
|
||||
tags! {
|
||||
/// Type to represent resolution units
|
||||
pub enum ResolutionUnit(u16) {
|
||||
None = 1,
|
||||
@@ -198,4 +197,4 @@ pub enum SampleFormat(u16) unknown("An unknown extension sample format") {
|
||||
IEEEFP = 3,
|
||||
Void = 4,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user