Stand-alone size computation of Type
This commit is contained in:
1 parent
2ccbe132e0
commit
2058b7f3ca
2 files changed
+58
-48
No files matched your search
+33
-48
@@ -376,7 +376,10 @@ impl Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mem_reader for the offset/value field
|
/// Returns a mem_reader for the offset/value field
|
||||||
fn r(&self, byte_order: ByteOrder) -> EndianReader<io::Cursor<Vec<u8>>> {
|
pub(crate) fn offset_field_reader(
|
||||||
|
&self,
|
||||||
|
byte_order: ByteOrder,
|
||||||
|
) -> EndianReader<io::Cursor<Vec<u8>>> {
|
||||||
EndianReader::new(io::Cursor::new(self.offset.to_vec()), byte_order)
|
EndianReader::new(io::Cursor::new(self.offset.to_vec()), byte_order)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,43 +395,25 @@ impl Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let bo = reader.byte_order;
|
let bo = reader.byte_order;
|
||||||
|
let value_bytes = self.type_.value_bytes(self.count)?;
|
||||||
let tag_size = match self.type_ {
|
|
||||||
Type::BYTE | Type::SBYTE | Type::ASCII | Type::UNDEFINED => 1,
|
|
||||||
Type::SHORT | Type::SSHORT => 2,
|
|
||||||
Type::LONG | Type::SLONG | Type::FLOAT | Type::IFD => 4,
|
|
||||||
Type::LONG8
|
|
||||||
| Type::SLONG8
|
|
||||||
| Type::DOUBLE
|
|
||||||
| Type::RATIONAL
|
|
||||||
| Type::SRATIONAL
|
|
||||||
| Type::IFD8 => 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
let value_bytes = match self.count.checked_mul(tag_size) {
|
|
||||||
Some(n) => n,
|
|
||||||
None => {
|
|
||||||
return Err(TiffError::LimitsExceeded);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Case 2: there is one value.
|
// Case 2: there is one value.
|
||||||
if self.count == 1 {
|
if self.count == 1 {
|
||||||
// 2a: the value is 5-8 bytes and we're in BigTiff mode.
|
// 2a: the value is 5-8 bytes and we're in BigTiff mode.
|
||||||
if bigtiff && value_bytes > 4 && value_bytes <= 8 {
|
if bigtiff && value_bytes > 4 && value_bytes <= 8 {
|
||||||
return Ok(match self.type_ {
|
return Ok(match self.type_ {
|
||||||
Type::LONG8 => UnsignedBig(self.r(bo).read_u64()?),
|
Type::LONG8 => UnsignedBig(self.offset_field_reader(bo).read_u64()?),
|
||||||
Type::SLONG8 => SignedBig(self.r(bo).read_i64()?),
|
Type::SLONG8 => SignedBig(self.offset_field_reader(bo).read_i64()?),
|
||||||
Type::DOUBLE => Double(self.r(bo).read_f64()?),
|
Type::DOUBLE => Double(self.offset_field_reader(bo).read_f64()?),
|
||||||
Type::RATIONAL => {
|
Type::RATIONAL => {
|
||||||
let mut r = self.r(bo);
|
let mut r = self.offset_field_reader(bo);
|
||||||
Rational(r.read_u32()?, r.read_u32()?)
|
Rational(r.read_u32()?, r.read_u32()?)
|
||||||
}
|
}
|
||||||
Type::SRATIONAL => {
|
Type::SRATIONAL => {
|
||||||
let mut r = self.r(bo);
|
let mut r = self.offset_field_reader(bo);
|
||||||
SRational(r.read_i32()?, r.read_i32()?)
|
SRational(r.read_i32()?, r.read_i32()?)
|
||||||
}
|
}
|
||||||
Type::IFD8 => IfdBig(self.r(bo).read_u64()?),
|
Type::IFD8 => IfdBig(self.offset_field_reader(bo).read_u64()?),
|
||||||
Type::BYTE
|
Type::BYTE
|
||||||
| Type::SBYTE
|
| Type::SBYTE
|
||||||
| Type::ASCII
|
| Type::ASCII
|
||||||
@@ -447,11 +432,11 @@ impl Entry {
|
|||||||
Type::BYTE => Byte(self.offset[0]),
|
Type::BYTE => Byte(self.offset[0]),
|
||||||
Type::SBYTE => SignedByte(self.offset[0] as i8),
|
Type::SBYTE => SignedByte(self.offset[0] as i8),
|
||||||
Type::UNDEFINED => Byte(self.offset[0]),
|
Type::UNDEFINED => Byte(self.offset[0]),
|
||||||
Type::SHORT => Short(self.r(bo).read_u16()?),
|
Type::SHORT => Short(self.offset_field_reader(bo).read_u16()?),
|
||||||
Type::SSHORT => SignedShort(self.r(bo).read_i16()?),
|
Type::SSHORT => SignedShort(self.offset_field_reader(bo).read_i16()?),
|
||||||
Type::LONG => Unsigned(self.r(bo).read_u32()?),
|
Type::LONG => Unsigned(self.offset_field_reader(bo).read_u32()?),
|
||||||
Type::SLONG => Signed(self.r(bo).read_i32()?),
|
Type::SLONG => Signed(self.offset_field_reader(bo).read_i32()?),
|
||||||
Type::FLOAT => Float(self.r(bo).read_f32()?),
|
Type::FLOAT => Float(self.offset_field_reader(bo).read_f32()?),
|
||||||
Type::ASCII => {
|
Type::ASCII => {
|
||||||
if self.offset[0] == 0 {
|
if self.offset[0] == 0 {
|
||||||
Ascii("".to_string())
|
Ascii("".to_string())
|
||||||
@@ -460,28 +445,28 @@ impl Entry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::LONG8 => {
|
Type::LONG8 => {
|
||||||
reader.goto_offset(self.r(bo).read_u32()?.into())?;
|
reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
|
||||||
UnsignedBig(reader.read_u64()?)
|
UnsignedBig(reader.read_u64()?)
|
||||||
}
|
}
|
||||||
Type::SLONG8 => {
|
Type::SLONG8 => {
|
||||||
reader.goto_offset(self.r(bo).read_u32()?.into())?;
|
reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
|
||||||
SignedBig(reader.read_i64()?)
|
SignedBig(reader.read_i64()?)
|
||||||
}
|
}
|
||||||
Type::DOUBLE => {
|
Type::DOUBLE => {
|
||||||
reader.goto_offset(self.r(bo).read_u32()?.into())?;
|
reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
|
||||||
Double(reader.read_f64()?)
|
Double(reader.read_f64()?)
|
||||||
}
|
}
|
||||||
Type::RATIONAL => {
|
Type::RATIONAL => {
|
||||||
reader.goto_offset(self.r(bo).read_u32()?.into())?;
|
reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
|
||||||
Rational(reader.read_u32()?, reader.read_u32()?)
|
Rational(reader.read_u32()?, reader.read_u32()?)
|
||||||
}
|
}
|
||||||
Type::SRATIONAL => {
|
Type::SRATIONAL => {
|
||||||
reader.goto_offset(self.r(bo).read_u32()?.into())?;
|
reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
|
||||||
SRational(reader.read_i32()?, reader.read_i32()?)
|
SRational(reader.read_i32()?, reader.read_i32()?)
|
||||||
}
|
}
|
||||||
Type::IFD => Ifd(self.r(bo).read_u32()?),
|
Type::IFD => Ifd(self.offset_field_reader(bo).read_u32()?),
|
||||||
Type::IFD8 => {
|
Type::IFD8 => {
|
||||||
reader.goto_offset(self.r(bo).read_u32()?.into())?;
|
reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
|
||||||
IfdBig(reader.read_u64()?)
|
IfdBig(reader.read_u64()?)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -512,7 +497,7 @@ impl Entry {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
Type::SHORT => {
|
Type::SHORT => {
|
||||||
let mut r = self.r(bo);
|
let mut r = self.offset_field_reader(bo);
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
for _ in 0..self.count {
|
for _ in 0..self.count {
|
||||||
v.push(Short(r.read_u16()?));
|
v.push(Short(r.read_u16()?));
|
||||||
@@ -520,7 +505,7 @@ impl Entry {
|
|||||||
return Ok(List(v));
|
return Ok(List(v));
|
||||||
}
|
}
|
||||||
Type::SSHORT => {
|
Type::SSHORT => {
|
||||||
let mut r = self.r(bo);
|
let mut r = self.offset_field_reader(bo);
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
for _ in 0..self.count {
|
for _ in 0..self.count {
|
||||||
v.push(SignedShort(r.read_i16()?));
|
v.push(SignedShort(r.read_i16()?));
|
||||||
@@ -528,7 +513,7 @@ impl Entry {
|
|||||||
return Ok(List(v));
|
return Ok(List(v));
|
||||||
}
|
}
|
||||||
Type::LONG => {
|
Type::LONG => {
|
||||||
let mut r = self.r(bo);
|
let mut r = self.offset_field_reader(bo);
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
for _ in 0..self.count {
|
for _ in 0..self.count {
|
||||||
v.push(Unsigned(r.read_u32()?));
|
v.push(Unsigned(r.read_u32()?));
|
||||||
@@ -536,7 +521,7 @@ impl Entry {
|
|||||||
return Ok(List(v));
|
return Ok(List(v));
|
||||||
}
|
}
|
||||||
Type::SLONG => {
|
Type::SLONG => {
|
||||||
let mut r = self.r(bo);
|
let mut r = self.offset_field_reader(bo);
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
for _ in 0..self.count {
|
for _ in 0..self.count {
|
||||||
v.push(Signed(r.read_i32()?));
|
v.push(Signed(r.read_i32()?));
|
||||||
@@ -544,7 +529,7 @@ impl Entry {
|
|||||||
return Ok(List(v));
|
return Ok(List(v));
|
||||||
}
|
}
|
||||||
Type::FLOAT => {
|
Type::FLOAT => {
|
||||||
let mut r = self.r(bo);
|
let mut r = self.offset_field_reader(bo);
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
for _ in 0..self.count {
|
for _ in 0..self.count {
|
||||||
v.push(Float(r.read_f32()?));
|
v.push(Float(r.read_f32()?));
|
||||||
@@ -552,7 +537,7 @@ impl Entry {
|
|||||||
return Ok(List(v));
|
return Ok(List(v));
|
||||||
}
|
}
|
||||||
Type::IFD => {
|
Type::IFD => {
|
||||||
let mut r = self.r(bo);
|
let mut r = self.offset_field_reader(bo);
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
for _ in 0..self.count {
|
for _ in 0..self.count {
|
||||||
v.push(Ifd(r.read_u32()?));
|
v.push(Ifd(r.read_u32()?));
|
||||||
@@ -636,9 +621,9 @@ impl Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if bigtiff {
|
if bigtiff {
|
||||||
reader.goto_offset(self.r(bo).read_u64()?)?
|
reader.goto_offset(self.offset_field_reader(bo).read_u64()?)?
|
||||||
} else {
|
} else {
|
||||||
reader.goto_offset(self.r(bo).read_u32()?.into())?
|
reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut out = vec![0; n];
|
let mut out = vec![0; n];
|
||||||
@@ -674,9 +659,9 @@ impl Entry {
|
|||||||
let mut v = Vec::with_capacity(value_count);
|
let mut v = Vec::with_capacity(value_count);
|
||||||
|
|
||||||
let offset = if bigtiff {
|
let offset = if bigtiff {
|
||||||
self.r(bo).read_u64()?
|
self.offset_field_reader(bo).read_u64()?
|
||||||
} else {
|
} else {
|
||||||
self.r(bo).read_u32()?.into()
|
self.offset_field_reader(bo).read_u32()?.into()
|
||||||
};
|
};
|
||||||
reader.goto_offset(offset)?;
|
reader.goto_offset(offset)?;
|
||||||
|
|
||||||
|
|||||||
+25
@@ -193,6 +193,31 @@ pub enum Type(u16) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Type {
|
||||||
|
pub(crate) fn byte_len(&self) -> u8 {
|
||||||
|
match *self {
|
||||||
|
Type::BYTE | Type::SBYTE | Type::ASCII | Type::UNDEFINED => 1,
|
||||||
|
Type::SHORT | Type::SSHORT => 2,
|
||||||
|
Type::LONG | Type::SLONG | Type::FLOAT | Type::IFD => 4,
|
||||||
|
Type::LONG8
|
||||||
|
| Type::SLONG8
|
||||||
|
| Type::DOUBLE
|
||||||
|
| Type::RATIONAL
|
||||||
|
| Type::SRATIONAL
|
||||||
|
| Type::IFD8 => 8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn value_bytes(&self, count: u64) -> Result<u64, crate::error::TiffError> {
|
||||||
|
let tag_size = u64::from(self.byte_len());
|
||||||
|
|
||||||
|
match count.checked_mul(tag_size) {
|
||||||
|
Some(n) => Ok(n),
|
||||||
|
None => Err(crate::error::TiffError::LimitsExceeded),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tags! {
|
tags! {
|
||||||
/// See [TIFF compression tags](https://www.awaresystems.be/imaging/tiff/tifftags/compression.html)
|
/// See [TIFF compression tags](https://www.awaresystems.be/imaging/tiff/tifftags/compression.html)
|
||||||
/// for reference.
|
/// for reference.
|
||||||
|
|||||||
Reference in new issue
Block a user