aboutsummaryrefslogtreecommitdiff
path: root/vendor/tiff/src/decoder
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
committerValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
commita990de90fe41456a23e58bd087d2f107d321f3a1 (patch)
tree15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/tiff/src/decoder
parent3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff)
downloadfparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz
fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip
Deleted vendor folder
Diffstat (limited to 'vendor/tiff/src/decoder')
-rw-r--r--vendor/tiff/src/decoder/ifd.rs670
-rw-r--r--vendor/tiff/src/decoder/image.rs601
-rw-r--r--vendor/tiff/src/decoder/mod.rs1176
-rw-r--r--vendor/tiff/src/decoder/stream.rs435
-rw-r--r--vendor/tiff/src/decoder/tag_reader.rs45
5 files changed, 0 insertions, 2927 deletions
diff --git a/vendor/tiff/src/decoder/ifd.rs b/vendor/tiff/src/decoder/ifd.rs
deleted file mode 100644
index b05513d..0000000
--- a/vendor/tiff/src/decoder/ifd.rs
+++ /dev/null
@@ -1,670 +0,0 @@
-//! Function for reading TIFF tags
-
-use std::collections::HashMap;
-use std::convert::{TryFrom, TryInto};
-use std::io::{self, Read, Seek};
-use std::mem;
-use std::str;
-
-use super::stream::{ByteOrder, EndianReader, SmartReader};
-use crate::tags::{Tag, Type};
-use crate::{TiffError, TiffFormatError, TiffResult};
-
-use self::Value::{
- Ascii, Byte, Double, Float, Ifd, IfdBig, List, Rational, RationalBig, SRational, SRationalBig,
- Short, Signed, SignedBig, Unsigned, UnsignedBig,
-};
-
-#[allow(unused_qualifications)]
-#[derive(Debug, Clone, PartialEq)]
-#[non_exhaustive]
-pub enum Value {
- Byte(u8),
- Short(u16),
- Signed(i32),
- SignedBig(i64),
- Unsigned(u32),
- UnsignedBig(u64),
- Float(f32),
- Double(f64),
- List(Vec<Value>),
- Rational(u32, u32),
- RationalBig(u64, u64),
- SRational(i32, i32),
- SRationalBig(i64, i64),
- Ascii(String),
- Ifd(u32),
- IfdBig(u64),
-}
-
-impl Value {
- pub fn into_u8(self) -> TiffResult<u8> {
- match self {
- Byte(val) => Ok(val),
- val => Err(TiffError::FormatError(TiffFormatError::ByteExpected(val))),
- }
- }
-
- pub fn into_u16(self) -> TiffResult<u16> {
- match self {
- Short(val) => Ok(val),
- Unsigned(val) => Ok(u16::try_from(val)?),
- UnsignedBig(val) => Ok(u16::try_from(val)?),
- val => Err(TiffError::FormatError(
- TiffFormatError::UnsignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_u32(self) -> TiffResult<u32> {
- match self {
- Short(val) => Ok(val.into()),
- Unsigned(val) => Ok(val),
- UnsignedBig(val) => Ok(u32::try_from(val)?),
- Ifd(val) => Ok(val),
- IfdBig(val) => Ok(u32::try_from(val)?),
- val => Err(TiffError::FormatError(
- TiffFormatError::UnsignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_i32(self) -> TiffResult<i32> {
- match self {
- Signed(val) => Ok(val),
- SignedBig(val) => Ok(i32::try_from(val)?),
- val => Err(TiffError::FormatError(
- TiffFormatError::SignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_u64(self) -> TiffResult<u64> {
- match self {
- Short(val) => Ok(val.into()),
- Unsigned(val) => Ok(val.into()),
- UnsignedBig(val) => Ok(val),
- Ifd(val) => Ok(val.into()),
- IfdBig(val) => Ok(val),
- val => Err(TiffError::FormatError(
- TiffFormatError::UnsignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_i64(self) -> TiffResult<i64> {
- match self {
- Signed(val) => Ok(val.into()),
- SignedBig(val) => Ok(val),
- val => Err(TiffError::FormatError(
- TiffFormatError::SignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_f32(self) -> TiffResult<f32> {
- match self {
- Float(val) => Ok(val),
- val => Err(TiffError::FormatError(
- TiffFormatError::SignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_f64(self) -> TiffResult<f64> {
- match self {
- Double(val) => Ok(val),
- val => Err(TiffError::FormatError(
- TiffFormatError::SignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_string(self) -> TiffResult<String> {
- match self {
- Ascii(val) => Ok(val),
- val => Err(TiffError::FormatError(
- TiffFormatError::SignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_u32_vec(self) -> TiffResult<Vec<u32>> {
- match self {
- List(vec) => {
- let mut new_vec = Vec::with_capacity(vec.len());
- for v in vec {
- new_vec.push(v.into_u32()?)
- }
- Ok(new_vec)
- }
- 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)?])
- }
- Ifd(val) => Ok(vec![val]),
- IfdBig(val) => Ok(vec![u32::try_from(val)?]),
- Ascii(val) => Ok(val.chars().map(u32::from).collect()),
- val => Err(TiffError::FormatError(
- TiffFormatError::UnsignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_u8_vec(self) -> TiffResult<Vec<u8>> {
- match self {
- List(vec) => {
- let mut new_vec = Vec::with_capacity(vec.len());
- for v in vec {
- new_vec.push(v.into_u8()?)
- }
- Ok(new_vec)
- }
- Byte(val) => Ok(vec![val]),
-
- val => Err(TiffError::FormatError(
- TiffFormatError::UnsignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_u16_vec(self) -> TiffResult<Vec<u16>> {
- match self {
- List(vec) => {
- let mut new_vec = Vec::with_capacity(vec.len());
- for v in vec {
- new_vec.push(v.into_u16()?)
- }
- Ok(new_vec)
- }
- Short(val) => Ok(vec![val]),
- val => Err(TiffError::FormatError(
- TiffFormatError::UnsignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_i32_vec(self) -> TiffResult<Vec<i32>> {
- match self {
- List(vec) => {
- let mut new_vec = Vec::with_capacity(vec.len());
- for v in vec {
- match v {
- SRational(numerator, denominator) => {
- new_vec.push(numerator);
- new_vec.push(denominator);
- }
- SRationalBig(numerator, denominator) => {
- new_vec.push(i32::try_from(numerator)?);
- new_vec.push(i32::try_from(denominator)?);
- }
- _ => new_vec.push(v.into_i32()?),
- }
- }
- Ok(new_vec)
- }
- 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)?])
- }
- val => Err(TiffError::FormatError(
- TiffFormatError::SignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_f32_vec(self) -> TiffResult<Vec<f32>> {
- match self {
- List(vec) => {
- let mut new_vec = Vec::with_capacity(vec.len());
- for v in vec {
- new_vec.push(v.into_f32()?)
- }
- Ok(new_vec)
- }
- Float(val) => Ok(vec![val]),
- val => Err(TiffError::FormatError(
- TiffFormatError::UnsignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_f64_vec(self) -> TiffResult<Vec<f64>> {
- match self {
- List(vec) => {
- let mut new_vec = Vec::with_capacity(vec.len());
- for v in vec {
- new_vec.push(v.into_f64()?)
- }
- Ok(new_vec)
- }
- Double(val) => Ok(vec![val]),
- val => Err(TiffError::FormatError(
- TiffFormatError::UnsignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_u64_vec(self) -> TiffResult<Vec<u64>> {
- match self {
- List(vec) => {
- let mut new_vec = Vec::with_capacity(vec.len());
- for v in vec {
- new_vec.push(v.into_u64()?)
- }
- Ok(new_vec)
- }
- Unsigned(val) => Ok(vec![val.into()]),
- UnsignedBig(val) => Ok(vec![val]),
- Rational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]),
- RationalBig(numerator, denominator) => Ok(vec![numerator, denominator]),
- Ifd(val) => Ok(vec![val.into()]),
- IfdBig(val) => Ok(vec![val]),
- Ascii(val) => Ok(val.chars().map(u32::from).map(u64::from).collect()),
- val => Err(TiffError::FormatError(
- TiffFormatError::UnsignedIntegerExpected(val),
- )),
- }
- }
-
- pub fn into_i64_vec(self) -> TiffResult<Vec<i64>> {
- match self {
- List(vec) => {
- let mut new_vec = Vec::with_capacity(vec.len());
- for v in vec {
- match v {
- SRational(numerator, denominator) => {
- new_vec.push(numerator.into());
- new_vec.push(denominator.into());
- }
- SRationalBig(numerator, denominator) => {
- new_vec.push(numerator);
- new_vec.push(denominator);
- }
- _ => new_vec.push(v.into_i64()?),
- }
- }
- Ok(new_vec)
- }
- Signed(val) => Ok(vec![val.into()]),
- SignedBig(val) => Ok(vec![val]),
- SRational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]),
- SRationalBig(numerator, denominator) => Ok(vec![numerator, denominator]),
- val => Err(TiffError::FormatError(
- TiffFormatError::SignedIntegerExpected(val),
- )),
- }
- }
-}
-
-#[derive(Clone)]
-pub struct Entry {
- type_: Type,
- count: u64,
- offset: [u8; 8],
-}
-
-impl ::std::fmt::Debug for Entry {
- fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
- fmt.write_str(&format!(
- "Entry {{ type_: {:?}, count: {:?}, offset: {:?} }}",
- self.type_, self.count, &self.offset
- ))
- }
-}
-
-impl Entry {
- pub fn new(type_: Type, count: u32, offset: [u8; 4]) -> Entry {
- let mut offset = offset.to_vec();
- offset.append(&mut vec![0; 4]);
- Entry::new_u64(type_, count.into(), offset[..].try_into().unwrap())
- }
-
- pub fn new_u64(type_: Type, count: u64, offset: [u8; 8]) -> Entry {
- Entry {
- type_,
- count,
- offset,
- }
- }
-
- /// Returns a mem_reader for the offset/value field
- fn r(&self, byte_order: ByteOrder) -> SmartReader<io::Cursor<Vec<u8>>> {
- SmartReader::wrap(io::Cursor::new(self.offset.to_vec()), byte_order)
- }
-
- pub fn val<R: Read + Seek>(
- &self,
- limits: &super::Limits,
- bigtiff: bool,
- reader: &mut SmartReader<R>,
- ) -> TiffResult<Value> {
- // Case 1: there are no values so we can return immediately.
- if self.count == 0 {
- return Ok(List(Vec::new()));
- }
-
- let bo = reader.byte_order();
-
- 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.
- if self.count == 1 {
- // 2a: the value is 5-8 bytes and we're in BigTiff mode.
- if bigtiff && value_bytes > 4 && value_bytes <= 8 {
- return Ok(match self.type_ {
- Type::LONG8 => UnsignedBig(self.r(bo).read_u64()?),
- Type::SLONG8 => SignedBig(self.r(bo).read_i64()?),
- Type::DOUBLE => Double(self.r(bo).read_f64()?),
- Type::RATIONAL => {
- let mut r = self.r(bo);
- Rational(r.read_u32()?, r.read_u32()?)
- }
- Type::SRATIONAL => {
- let mut r = self.r(bo);
- SRational(r.read_i32()?, r.read_i32()?)
- }
- Type::IFD8 => IfdBig(self.r(bo).read_u64()?),
- Type::BYTE
- | Type::SBYTE
- | Type::ASCII
- | Type::UNDEFINED
- | Type::SHORT
- | Type::SSHORT
- | Type::LONG
- | Type::SLONG
- | Type::FLOAT
- | Type::IFD => unreachable!(),
- });
- }
-
- // 2b: the value is at most 4 bytes or doesn't fit in the offset field.
- return Ok(match self.type_ {
- Type::BYTE => Unsigned(u32::from(self.offset[0])),
- Type::SBYTE => Signed(i32::from(self.offset[0] as i8)),
- Type::UNDEFINED => Byte(self.offset[0]),
- Type::SHORT => Unsigned(u32::from(self.r(bo).read_u16()?)),
- Type::SSHORT => Signed(i32::from(self.r(bo).read_i16()?)),
- Type::LONG => Unsigned(self.r(bo).read_u32()?),
- Type::SLONG => Signed(self.r(bo).read_i32()?),
- Type::FLOAT => Float(self.r(bo).read_f32()?),
- Type::ASCII => {
- if self.offset[0] == 0 {
- Ascii("".to_string())
- } else {
- return Err(TiffError::FormatError(TiffFormatError::InvalidTag));
- }
- }
- Type::LONG8 => {
- reader.goto_offset(self.r(bo).read_u32()?.into())?;
- UnsignedBig(reader.read_u64()?)
- }
- Type::SLONG8 => {
- reader.goto_offset(self.r(bo).read_u32()?.into())?;
- SignedBig(reader.read_i64()?)
- }
- Type::DOUBLE => {
- reader.goto_offset(self.r(bo).read_u32()?.into())?;
- Double(reader.read_f64()?)
- }
- Type::RATIONAL => {
- reader.goto_offset(self.r(bo).read_u32()?.into())?;
- Rational(reader.read_u32()?, reader.read_u32()?)
- }
- Type::SRATIONAL => {
- reader.goto_offset(self.r(bo).read_u32()?.into())?;
- SRational(reader.read_i32()?, reader.read_i32()?)
- }
- Type::IFD => Ifd(self.r(bo).read_u32()?),
- Type::IFD8 => {
- reader.goto_offset(self.r(bo).read_u32()?.into())?;
- IfdBig(reader.read_u64()?)
- }
- });
- }
-
- // Case 3: There is more than one value, but it fits in the offset field.
- if value_bytes <= 4 || bigtiff && value_bytes <= 8 {
- match self.type_ {
- Type::BYTE => return offset_to_bytes(self.count as usize, self),
- Type::SBYTE => return offset_to_sbytes(self.count as usize, self),
- Type::ASCII => {
- let mut buf = vec![0; self.count as usize];
- self.r(bo).read_exact(&mut buf)?;
- if buf.is_ascii() && buf.ends_with(&[0]) {
- let v = str::from_utf8(&buf)?;
- let v = v.trim_matches(char::from(0));
- return Ok(Ascii(v.into()));
- } else {
- return Err(TiffError::FormatError(TiffFormatError::InvalidTag));
- }
- }
- Type::UNDEFINED => {
- return Ok(List(
- self.offset[0..self.count as usize]
- .iter()
- .map(|&b| Byte(b))
- .collect(),
- ));
- }
- Type::SHORT => {
- let mut r = self.r(bo);
- let mut v = Vec::new();
- for _ in 0..self.count {
- v.push(Short(r.read_u16()?));
- }
- return Ok(List(v));
- }
- Type::SSHORT => {
- let mut r = self.r(bo);
- let mut v = Vec::new();
- for _ in 0..self.count {
- v.push(Signed(i32::from(r.read_i16()?)));
- }
- return Ok(List(v));
- }
- Type::LONG => {
- let mut r = self.r(bo);
- let mut v = Vec::new();
- for _ in 0..self.count {
- v.push(Unsigned(r.read_u32()?));
- }
- return Ok(List(v));
- }
- Type::SLONG => {
- let mut r = self.r(bo);
- let mut v = Vec::new();
- for _ in 0..self.count {
- v.push(Signed(r.read_i32()?));
- }
- return Ok(List(v));
- }
- Type::FLOAT => {
- let mut r = self.r(bo);
- let mut v = Vec::new();
- for _ in 0..self.count {
- v.push(Float(r.read_f32()?));
- }
- return Ok(List(v));
- }
- Type::IFD => {
- let mut r = self.r(bo);
- let mut v = Vec::new();
- for _ in 0..self.count {
- v.push(Ifd(r.read_u32()?));
- }
- return Ok(List(v));
- }
- Type::LONG8
- | Type::SLONG8
- | Type::RATIONAL
- | Type::SRATIONAL
- | Type::DOUBLE
- | Type::IFD8 => {
- unreachable!()
- }
- }
- }
-
- // Case 4: there is more than one value, and it doesn't fit in the offset field.
- match self.type_ {
- // TODO check if this could give wrong results
- // at a different endianess of file/computer.
- Type::BYTE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- let mut buf = [0; 1];
- reader.read_exact(&mut buf)?;
- Ok(UnsignedBig(u64::from(buf[0])))
- }),
- Type::SBYTE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(SignedBig(i64::from(reader.read_i8()? as i8)))
- }),
- Type::SHORT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(UnsignedBig(u64::from(reader.read_u16()?)))
- }),
- Type::SSHORT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(SignedBig(i64::from(reader.read_i16()?)))
- }),
- Type::LONG => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(Unsigned(reader.read_u32()?))
- }),
- Type::SLONG => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(Signed(reader.read_i32()?))
- }),
- Type::FLOAT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(Float(reader.read_f32()?))
- }),
- Type::DOUBLE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(Double(reader.read_f64()?))
- }),
- Type::RATIONAL => {
- self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(Rational(reader.read_u32()?, reader.read_u32()?))
- })
- }
- Type::SRATIONAL => {
- self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(SRational(reader.read_i32()?, reader.read_i32()?))
- })
- }
- Type::LONG8 => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(UnsignedBig(reader.read_u64()?))
- }),
- Type::SLONG8 => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(SignedBig(reader.read_i64()?))
- }),
- Type::IFD => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(Ifd(reader.read_u32()?))
- }),
- Type::IFD8 => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- Ok(IfdBig(reader.read_u64()?))
- }),
- Type::UNDEFINED => {
- self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
- let mut buf = [0; 1];
- reader.read_exact(&mut buf)?;
- Ok(Byte(buf[0]))
- })
- }
- Type::ASCII => {
- let n = usize::try_from(self.count)?;
- if n > limits.decoding_buffer_size {
- return Err(TiffError::LimitsExceeded);
- }
-
- if bigtiff {
- reader.goto_offset(self.r(bo).read_u64()?)?
- } else {
- reader.goto_offset(self.r(bo).read_u32()?.into())?
- }
-
- let mut out = vec![0; n];
- reader.read_exact(&mut out)?;
- // Strings may be null-terminated, so we trim anything downstream of the null byte
- if let Some(first) = out.iter().position(|&b| b == 0) {
- out.truncate(first);
- }
- Ok(Ascii(String::from_utf8(out)?))
- }
- }
- }
-
- #[inline]
- fn decode_offset<R, F>(
- &self,
- value_count: u64,
- bo: ByteOrder,
- bigtiff: bool,
- limits: &super::Limits,
- reader: &mut SmartReader<R>,
- decode_fn: F,
- ) -> TiffResult<Value>
- where
- R: Read + Seek,
- F: Fn(&mut SmartReader<R>) -> TiffResult<Value>,
- {
- let value_count = usize::try_from(value_count)?;
- if value_count > limits.decoding_buffer_size / mem::size_of::<Value>() {
- return Err(TiffError::LimitsExceeded);
- }
-
- let mut v = Vec::with_capacity(value_count);
-
- let offset = if bigtiff {
- self.r(bo).read_u64()?
- } else {
- self.r(bo).read_u32()?.into()
- };
- reader.goto_offset(offset)?;
-
- for _ in 0..value_count {
- v.push(decode_fn(reader)?)
- }
- Ok(List(v))
- }
-}
-
-/// Extracts a list of BYTE tags stored in an offset
-#[inline]
-fn offset_to_bytes(n: usize, entry: &Entry) -> TiffResult<Value> {
- Ok(List(
- entry.offset[0..n]
- .iter()
- .map(|&e| Unsigned(u32::from(e)))
- .collect(),
- ))
-}
-
-/// Extracts a list of SBYTE tags stored in an offset
-#[inline]
-fn offset_to_sbytes(n: usize, entry: &Entry) -> TiffResult<Value> {
- Ok(List(
- entry.offset[0..n]
- .iter()
- .map(|&e| Signed(i32::from(e as i8)))
- .collect(),
- ))
-}
-
-/// Type representing an Image File Directory
-pub type Directory = HashMap<Tag, Entry>;
diff --git a/vendor/tiff/src/decoder/image.rs b/vendor/tiff/src/decoder/image.rs
deleted file mode 100644
index c037e31..0000000
--- a/vendor/tiff/src/decoder/image.rs
+++ /dev/null
@@ -1,601 +0,0 @@
-use super::ifd::{Directory, Value};
-use super::stream::{ByteOrder, DeflateReader, JpegReader, LZWReader, PackBitsReader};
-use super::tag_reader::TagReader;
-use super::{fp_predict_f32, fp_predict_f64, DecodingBuffer, Limits};
-use super::{stream::SmartReader, ChunkType};
-use crate::tags::{CompressionMethod, PhotometricInterpretation, Predictor, SampleFormat, Tag};
-use crate::{ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError};
-use std::convert::{TryFrom, TryInto};
-use std::io::{self, Cursor, Read, Seek};
-use std::sync::Arc;
-
-#[derive(Debug)]
-pub(crate) struct StripDecodeState {
- pub rows_per_strip: u32,
-}
-
-#[derive(Debug)]
-/// Computed values useful for tile decoding
-pub(crate) struct TileAttributes {
- pub image_width: usize,
- pub image_height: usize,
-
- pub tile_width: usize,
- pub tile_length: usize,
-}
-
-impl TileAttributes {
- pub fn tiles_across(&self) -> usize {
- (self.image_width + self.tile_width - 1) / self.tile_width
- }
- pub fn tiles_down(&self) -> usize {
- (self.image_height + self.tile_length - 1) / self.tile_length
- }
- fn padding_right(&self) -> usize {
- (self.tile_width - self.image_width % self.tile_width) % self.tile_width
- }
- fn padding_down(&self) -> usize {
- (self.tile_length - self.image_height % self.tile_length) % self.tile_length
- }
- pub fn get_padding(&self, tile: usize) -> (usize, usize) {
- let row = tile / self.tiles_across();
- let column = tile % self.tiles_across();
-
- let padding_right = if column == self.tiles_across() - 1 {
- self.padding_right()
- } else {
- 0
- };
-
- let padding_down = if row == self.tiles_down() - 1 {
- self.padding_down()
- } else {
- 0
- };
-
- (padding_right, padding_down)
- }
-}
-
-#[derive(Debug)]
-pub(crate) struct Image {
- pub ifd: Option<Directory>,
- pub width: u32,
- pub height: u32,
- pub bits_per_sample: Vec<u8>,
- #[allow(unused)]
- pub samples: u8,
- pub sample_format: Vec<SampleFormat>,
- pub photometric_interpretation: PhotometricInterpretation,
- pub compression_method: CompressionMethod,
- pub predictor: Predictor,
- pub jpeg_tables: Option<Arc<Vec<u8>>>,
- pub chunk_type: ChunkType,
- pub strip_decoder: Option<StripDecodeState>,
- pub tile_attributes: Option<TileAttributes>,
- pub chunk_offsets: Vec<u64>,
- pub chunk_bytes: Vec<u64>,
-}
-
-impl Image {
- pub fn from_reader<R: Read + Seek>(
- reader: &mut SmartReader<R>,
- ifd: Directory,
- limits: &Limits,
- bigtiff: bool,
- ) -> TiffResult<Image> {
- let mut tag_reader = TagReader {
- reader,
- limits,
- ifd: &ifd,
- bigtiff,
- };
-
- let width = tag_reader.require_tag(Tag::ImageWidth)?.into_u32()?;
- let height = tag_reader.require_tag(Tag::ImageLength)?.into_u32()?;
- if width == 0 || height == 0 {
- return Err(TiffError::FormatError(TiffFormatError::InvalidDimensions(
- width, height,
- )));
- }
-
- let photometric_interpretation = tag_reader
- .find_tag(Tag::PhotometricInterpretation)?
- .map(Value::into_u16)
- .transpose()?
- .and_then(PhotometricInterpretation::from_u16)
- .ok_or(TiffUnsupportedError::UnknownInterpretation)?;
-
- // Try to parse both the compression method and the number, format, and bits of the included samples.
- // If they are not explicitly specified, those tags are reset to their default values and not carried from previous images.
- let compression_method = match tag_reader.find_tag(Tag::Compression)? {
- Some(val) => CompressionMethod::from_u16(val.into_u16()?)
- .ok_or(TiffUnsupportedError::UnknownCompressionMethod)?,
- None => CompressionMethod::None,
- };
-
- let jpeg_tables = if compression_method == CompressionMethod::ModernJPEG
- && ifd.contains_key(&Tag::JPEGTables)
- {
- let vec = tag_reader
- .find_tag(Tag::JPEGTables)?
- .unwrap()
- .into_u8_vec()?;
- if vec.len() < 2 {
- return Err(TiffError::FormatError(
- TiffFormatError::InvalidTagValueType(Tag::JPEGTables),
- ));
- }
-
- Some(Arc::new(vec))
- } else {
- None
- };
-
- let samples = tag_reader
- .find_tag(Tag::SamplesPerPixel)?
- .map(Value::into_u16)
- .transpose()?
- .unwrap_or(1)
- .try_into()?;
-
- let sample_format = match tag_reader.find_tag_uint_vec(Tag::SampleFormat)? {
- Some(vals) => {
- let sample_format: Vec<_> = vals
- .into_iter()
- .map(SampleFormat::from_u16_exhaustive)
- .collect();
-
- // TODO: for now, only homogenous formats across samples are supported.
- if !sample_format.windows(2).all(|s| s[0] == s[1]) {
- return Err(TiffUnsupportedError::UnsupportedSampleFormat(sample_format).into());
- }
-
- sample_format
- }
- None => vec![SampleFormat::Uint],
- };
-
- let bits_per_sample = match samples {
- 1 | 3 | 4 => tag_reader
- .find_tag_uint_vec(Tag::BitsPerSample)?
- .unwrap_or_else(|| vec![1]),
- _ => return Err(TiffUnsupportedError::UnsupportedSampleDepth(samples).into()),
- };
-
- let predictor = tag_reader
- .find_tag(Tag::Predictor)?
- .map(Value::into_u16)
- .transpose()?
- .map(|p| {
- Predictor::from_u16(p)
- .ok_or(TiffError::FormatError(TiffFormatError::UnknownPredictor(p)))
- })
- .transpose()?
- .unwrap_or(Predictor::None);
-
- let chunk_type;
- let chunk_offsets;
- let chunk_bytes;
- let strip_decoder;
- let tile_attributes;
- match (
- ifd.contains_key(&Tag::StripByteCounts),
- ifd.contains_key(&Tag::StripOffsets),
- ifd.contains_key(&Tag::TileByteCounts),
- ifd.contains_key(&Tag::TileOffsets),
- ) {
- (true, true, false, false) => {
- chunk_type = ChunkType::Strip;
-
- chunk_offsets = tag_reader
- .find_tag(Tag::StripOffsets)?
- .unwrap()
- .into_u64_vec()?;
- chunk_bytes = tag_reader
- .find_tag(Tag::StripByteCounts)?
- .unwrap()
- .into_u64_vec()?;
- let rows_per_strip = tag_reader
- .find_tag(Tag::RowsPerStrip)?
- .map(Value::into_u32)
- .transpose()?
- .unwrap_or(height);
- strip_decoder = Some(StripDecodeState { rows_per_strip });
- tile_attributes = None;
-
- if chunk_offsets.len() != chunk_bytes.len()
- || rows_per_strip == 0
- || u32::try_from(chunk_offsets.len())?
- != height.saturating_sub(1) / rows_per_strip + 1
- {
- return Err(TiffError::FormatError(
- TiffFormatError::InconsistentSizesEncountered,
- ));
- }
- }
- (false, false, true, true) => {
- chunk_type = ChunkType::Tile;
-
- let tile_width =
- usize::try_from(tag_reader.require_tag(Tag::TileWidth)?.into_u32()?)?;
- let tile_length =
- usize::try_from(tag_reader.require_tag(Tag::TileLength)?.into_u32()?)?;
-
- if tile_width == 0 {
- return Err(TiffFormatError::InvalidTagValueType(Tag::TileWidth).into());
- } else if tile_length == 0 {
- return Err(TiffFormatError::InvalidTagValueType(Tag::TileLength).into());
- }
-
- strip_decoder = None;
- tile_attributes = Some(TileAttributes {
- image_width: usize::try_from(width)?,
- image_height: usize::try_from(height)?,
- tile_width,
- tile_length,
- });
- chunk_offsets = tag_reader
- .find_tag(Tag::TileOffsets)?
- .unwrap()
- .into_u64_vec()?;
- chunk_bytes = tag_reader
- .find_tag(Tag::TileByteCounts)?
- .unwrap()
- .into_u64_vec()?;
-
- let tile = tile_attributes.as_ref().unwrap();
- if chunk_offsets.len() != chunk_bytes.len()
- || chunk_offsets.len() != tile.tiles_down() * tile.tiles_across()
- {
- return Err(TiffError::FormatError(
- TiffFormatError::InconsistentSizesEncountered,
- ));
- }
- }
- (_, _, _, _) => {
- return Err(TiffError::FormatError(
- TiffFormatError::StripTileTagConflict,
- ))
- }
- };
-
- Ok(Image {
- ifd: Some(ifd),
- width,
- height,
- bits_per_sample,
- samples,
- sample_format,
- photometric_interpretation,
- compression_method,
- jpeg_tables,
- predictor,
- chunk_type,
- strip_decoder,
- tile_attributes,
- chunk_offsets,
- chunk_bytes,
- })
- }
-
- pub(crate) fn colortype(&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)),
- // FIXME: We should _ignore_ other components. In particular:
- // > Beware of extra components. Some TIFF files may have more components per pixel
- // than you think. A Baseline TIFF reader must skip over them gracefully,using the
- // values of the SamplesPerPixel and BitsPerSample fields.
- // > -- TIFF 6.0 Specification, Section 7, Additional Baseline requirements.
- _ => 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::YCbCr => match self.bits_per_sample[..] {
- [y, cb, cr] if [y, y] == [cb, cr] => Ok(ColorType::YCbCr(y)),
- _ => Err(TiffError::UnsupportedError(
- TiffUnsupportedError::InterpretationWithBits(
- self.photometric_interpretation,
- self.bits_per_sample.clone(),
- ),
- )),
- },
- PhotometricInterpretation::BlackIsZero | PhotometricInterpretation::WhiteIsZero
- if self.bits_per_sample.len() == 1 =>
- {
- Ok(ColorType::Gray(self.bits_per_sample[0]))
- }
-
- // TODO: this is bad we should not fail at this point
- _ => Err(TiffError::UnsupportedError(
- TiffUnsupportedError::InterpretationWithBits(
- self.photometric_interpretation,
- self.bits_per_sample.clone(),
- ),
- )),
- }
- }
-
- fn create_reader<'r, R: 'r + Read>(
- reader: R,
- photometric_interpretation: PhotometricInterpretation,
- compression_method: CompressionMethod,
- compressed_length: u64,
- jpeg_tables: Option<Arc<Vec<u8>>>,
- ) -> 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)?))
- }
- CompressionMethod::PackBits => Box::new(PackBitsReader::new(reader, compressed_length)),
- CompressionMethod::Deflate | CompressionMethod::OldDeflate => {
- Box::new(DeflateReader::new(reader))
- }
- CompressionMethod::ModernJPEG => {
- if jpeg_tables.is_some() && compressed_length < 2 {
- return Err(TiffError::FormatError(
- TiffFormatError::InvalidTagValueType(Tag::JPEGTables),
- ));
- }
-
- let jpeg_reader = JpegReader::new(reader, compressed_length, jpeg_tables)?;
- let mut decoder = jpeg::Decoder::new(jpeg_reader);
-
- match photometric_interpretation {
- PhotometricInterpretation::RGB => {
- decoder.set_color_transform(jpeg::ColorTransform::RGB)
- }
- PhotometricInterpretation::WhiteIsZero => {
- decoder.set_color_transform(jpeg::ColorTransform::None)
- }
- PhotometricInterpretation::BlackIsZero => {
- decoder.set_color_transform(jpeg::ColorTransform::None)
- }
- PhotometricInterpretation::TransparencyMask => {
- decoder.set_color_transform(jpeg::ColorTransform::None)
- }
- PhotometricInterpretation::CMYK => {
- decoder.set_color_transform(jpeg::ColorTransform::CMYK)
- }
- PhotometricInterpretation::YCbCr => {
- decoder.set_color_transform(jpeg::ColorTransform::YCbCr)
- }
- photometric_interpretation => {
- return Err(TiffError::UnsupportedError(
- TiffUnsupportedError::UnsupportedInterpretation(
- photometric_interpretation,
- ),
- ));
- }
- }
-
- let data = decoder.decode()?;
-
- Box::new(Cursor::new(data))
- }
- method => {
- return Err(TiffError::UnsupportedError(
- TiffUnsupportedError::UnsupportedCompressionMethod(method),
- ))
- }
- })
- }
-
- pub(crate) fn chunk_file_range(&self, chunk: u32) -> TiffResult<(u64, u64)> {
- let file_offset = self
- .chunk_offsets
- .get(chunk as usize)
- .ok_or(TiffError::FormatError(
- TiffFormatError::InconsistentSizesEncountered,
- ))?;
-
- let compressed_bytes =
- self.chunk_bytes
- .get(chunk as usize)
- .ok_or(TiffError::FormatError(
- TiffFormatError::InconsistentSizesEncountered,
- ))?;
-
- Ok((*file_offset, *compressed_bytes))
- }
-
- pub(crate) fn chunk_dimensions(&self) -> TiffResult<(u32, u32)> {
- match self.chunk_type {
- ChunkType::Strip => {
- let strip_attrs = self.strip_decoder.as_ref().unwrap();
- Ok((self.width, strip_attrs.rows_per_strip))
- }
- ChunkType::Tile => {
- let tile_attrs = self.tile_attributes.as_ref().unwrap();
- Ok((
- u32::try_from(tile_attrs.tile_width)?,
- u32::try_from(tile_attrs.tile_length)?,
- ))
- }
- }
- }
-
- pub(crate) fn chunk_data_dimensions(&self, chunk_index: u32) -> TiffResult<(u32, u32)> {
- let dims = self.chunk_dimensions()?;
-
- match self.chunk_type {
- ChunkType::Strip => {
- let strip_height_without_padding = chunk_index
- .checked_mul(dims.1)
- .and_then(|x| self.height.checked_sub(x))
- .ok_or(TiffError::UsageError(UsageError::InvalidChunkIndex(
- chunk_index,
- )))?;
-
- // Ignore potential vertical padding on the bottommost strip
- let strip_height = dims.1.min(strip_height_without_padding);
-
- Ok((dims.0, strip_height))
- }
- ChunkType::Tile => {
- let tile_attrs = self.tile_attributes.as_ref().unwrap();
- let (padding_right, padding_down) = tile_attrs.get_padding(chunk_index as usize);
-
- let tile_width = tile_attrs.tile_width - padding_right;
- let tile_length = tile_attrs.tile_length - padding_down;
-
- Ok((u32::try_from(tile_width)?, u32::try_from(tile_length)?))
- }
- }
- }
-
- pub(crate) fn expand_chunk(
- &self,
- reader: impl Read,
- mut buffer: DecodingBuffer,
- output_width: usize,
- byte_order: ByteOrder,
- chunk_index: u32,
- ) -> TiffResult<()> {
- // Validate that the provided buffer is of the expected type.
- let color_type = self.colortype()?;
- match (color_type, &buffer) {
- (ColorType::RGB(n), _)
- | (ColorType::RGBA(n), _)
- | (ColorType::CMYK(n), _)
- | (ColorType::YCbCr(n), _)
- | (ColorType::Gray(n), _)
- if usize::from(n) == buffer.byte_len() * 8 => {}
- (ColorType::Gray(n), DecodingBuffer::U8(_)) if n < 8 => match self.predictor {
- Predictor::None => {}
- Predictor::Horizontal => {
- return Err(TiffError::UnsupportedError(
- TiffUnsupportedError::HorizontalPredictor(color_type),
- ))
- }
- Predictor::FloatingPoint => {
- return Err(TiffError::UnsupportedError(
- TiffUnsupportedError::FloatingPointPredictor(color_type),
- ));
- }
- },
- (type_, _) => {
- return Err(TiffError::UnsupportedError(
- TiffUnsupportedError::UnsupportedColorType(type_),
- ))
- }
- }
-
- // Validate that the predictor is supported for the sample type.
- match (self.predictor, &buffer) {
- (Predictor::Horizontal, DecodingBuffer::F32(_))
- | (Predictor::Horizontal, DecodingBuffer::F64(_)) => {
- return Err(TiffError::UnsupportedError(
- TiffUnsupportedError::HorizontalPredictor(color_type),
- ));
- }
- (Predictor::FloatingPoint, DecodingBuffer::F32(_))
- | (Predictor::FloatingPoint, DecodingBuffer::F64(_)) => {}
- (Predictor::FloatingPoint, _) => {
- return Err(TiffError::UnsupportedError(
- TiffUnsupportedError::FloatingPointPredictor(color_type),
- ));
- }
- _ => {}
- }
-
- let compressed_bytes =
- self.chunk_bytes
- .get(chunk_index as usize)
- .ok_or(TiffError::FormatError(
- TiffFormatError::InconsistentSizesEncountered,
- ))?;
-
- let byte_len = buffer.byte_len();
- let compression_method = self.compression_method;
- let photometric_interpretation = self.photometric_interpretation;
- let predictor = self.predictor;
- let samples = self.bits_per_sample.len();
-
- let chunk_dims = self.chunk_dimensions()?;
- let data_dims = self.chunk_data_dimensions(chunk_index)?;
-
- let padding_right = chunk_dims.0 - data_dims.0;
-
- let jpeg_tables = self.jpeg_tables.clone();
- let mut reader = Self::create_reader(
- reader,
- photometric_interpretation,
- compression_method,
- *compressed_bytes,
- jpeg_tables,
- )?;
-
- if output_width == data_dims.0 as usize && padding_right == 0 {
- let total_samples = data_dims.0 as usize * data_dims.1 as usize * samples;
- let tile = &mut buffer.as_bytes_mut()[..total_samples * byte_len];
- reader.read_exact(tile)?;
-
- for row in 0..data_dims.1 as usize {
- let row_start = row as usize * output_width as usize * samples;
- let row_end = (row + 1) * output_width as usize * samples;
- let row = buffer.subrange(row_start..row_end);
- super::fix_endianness_and_predict(row, samples, byte_order, predictor);
- }
- if photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
- super::invert_colors(&mut buffer.subrange(0..total_samples), color_type);
- }
- } else if padding_right > 0 && self.predictor == Predictor::FloatingPoint {
- // The floating point predictor shuffles the padding bytes into the encoded output, so
- // this case is handled specially when needed.
- let mut encoded = vec![0u8; chunk_dims.0 as usize * samples * byte_len];
-
- for row in 0..data_dims.1 as usize {
- let row_start = row * output_width as usize * samples;
- let row_end = row_start + data_dims.0 as usize * samples;
-
- reader.read_exact(&mut encoded)?;
- match buffer.subrange(row_start..row_end) {
- DecodingBuffer::F32(buf) => fp_predict_f32(&mut encoded, buf, samples),
- DecodingBuffer::F64(buf) => fp_predict_f64(&mut encoded, buf, samples),
- _ => unreachable!(),
- }
- if photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
- super::invert_colors(&mut buffer.subrange(row_start..row_end), color_type);
- }
- }
- } else {
- for row in 0..data_dims.1 as usize {
- let row_start = row * output_width as usize * samples;
- let row_end = row_start + data_dims.0 as usize * samples;
-
- let row = &mut buffer.as_bytes_mut()[(row_start * byte_len)..(row_end * byte_len)];
- reader.read_exact(row)?;
-
- // Skip horizontal padding
- if padding_right > 0 {
- let len = u64::try_from(padding_right as usize * samples * byte_len)?;
- io::copy(&mut reader.by_ref().take(len), &mut io::sink())?;
- }
-
- let mut row = buffer.subrange(row_start..row_end);
- super::fix_endianness_and_predict(row.copy(), samples, byte_order, predictor);
- if photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
- super::invert_colors(&mut row, color_type);
- }
- }
- }
-
- Ok(())
- }
-}
diff --git a/vendor/tiff/src/decoder/mod.rs b/vendor/tiff/src/decoder/mod.rs
deleted file mode 100644
index 5fa1812..0000000
--- a/vendor/tiff/src/decoder/mod.rs
+++ /dev/null
@@ -1,1176 +0,0 @@
-use std::collections::{HashMap, HashSet};
-use std::convert::TryFrom;
-use std::io::{self, Read, Seek};
-use std::ops::Range;
-
-use crate::{
- bytecast, ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError,
-};
-
-use self::ifd::Directory;
-use self::image::Image;
-use crate::tags::{
- CompressionMethod, PhotometricInterpretation, Predictor, SampleFormat, Tag, Type,
-};
-
-use self::stream::{ByteOrder, EndianReader, SmartReader};
-
-pub mod ifd;
-mod image;
-mod stream;
-mod tag_reader;
-
-/// Result of a decoding process
-#[derive(Debug)]
-pub enum DecodingResult {
- /// A vector of unsigned bytes
- U8(Vec<u8>),
- /// A vector of unsigned words
- U16(Vec<u16>),
- /// A vector of 32 bit unsigned ints
- U32(Vec<u32>),
- /// A vector of 64 bit unsigned ints
- U64(Vec<u64>),
- /// A vector of 32 bit IEEE floats
- F32(Vec<f32>),
- /// A vector of 64 bit IEEE floats
- F64(Vec<f64>),
- /// A vector of 8 bit signed ints
- I8(Vec<i8>),
- /// A vector of 16 bit signed ints
- I16(Vec<i16>),
- /// A vector of 32 bit signed ints
- I32(Vec<i32>),
- /// A vector of 64 bit signed ints
- I64(Vec<i64>),
-}
-
-impl DecodingResult {
- fn new_u8(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
- if size > limits.decoding_buffer_size {
- Err(TiffError::LimitsExceeded)
- } else {
- Ok(DecodingResult::U8(vec![0; size]))
- }
- }
-
- fn new_u16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
- if size > limits.decoding_buffer_size / 2 {
- Err(TiffError::LimitsExceeded)
- } else {
- Ok(DecodingResult::U16(vec![0; size]))
- }
- }
-
- fn new_u32(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
- if size > limits.decoding_buffer_size / 4 {
- Err(TiffError::LimitsExceeded)
- } else {
- Ok(DecodingResult::U32(vec![0; size]))
- }
- }
-
- fn new_u64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
- if size > limits.decoding_buffer_size / 8 {
- Err(TiffError::LimitsExceeded)
- } else {
- Ok(DecodingResult::U64(vec![0; size]))
- }
- }
-
- fn new_f32(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
- if size > limits.decoding_buffer_size / std::mem::size_of::<f32>() {
- Err(TiffError::LimitsExceeded)
- } else {
- Ok(DecodingResult::F32(vec![0.0; size]))
- }
- }
-
- fn new_f64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
- if size > limits.decoding_buffer_size / std::mem::size_of::<f64>() {
- Err(TiffError::LimitsExceeded)
- } else {
- Ok(DecodingResult::F64(vec![0.0; size]))
- }
- }
-
- fn new_i8(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
- if size > limits.decoding_buffer_size / std::mem::size_of::<i8>() {
- Err(TiffError::LimitsExceeded)
- } else {
- Ok(DecodingResult::I8(vec![0; size]))
- }
- }
-
- fn new_i16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
- if size > limits.decoding_buffer_size / 2 {
- Err(TiffError::LimitsExceeded)
- } else {
- Ok(DecodingResult::I16(vec![0; size]))
- }
- }
-
- fn new_i32(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
- if size > limits.decoding_buffer_size / 4 {
- Err(TiffError::LimitsExceeded)
- } else {
- Ok(DecodingResult::I32(vec![0; size]))
- }
- }
-
- fn new_i64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
- if size > limits.decoding_buffer_size / 8 {
- Err(TiffError::LimitsExceeded)
- } else {
- Ok(DecodingResult::I64(vec![0; size]))
- }
- }
-
- pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer {
- match *self {
- DecodingResult::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[start..]),
- DecodingResult::U16(ref mut buf) => DecodingBuffer::U16(&mut buf[start..]),
- DecodingResult::U32(ref mut buf) => DecodingBuffer::U32(&mut buf[start..]),
- DecodingResult::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[start..]),
- DecodingResult::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[start..]),
- DecodingResult::F64(ref mut buf) => DecodingBuffer::F64(&mut buf[start..]),
- DecodingResult::I8(ref mut buf) => DecodingBuffer::I8(&mut buf[start..]),
- DecodingResult::I16(ref mut buf) => DecodingBuffer::I16(&mut buf[start..]),
- DecodingResult::I32(ref mut buf) => DecodingBuffer::I32(&mut buf[start..]),
- DecodingResult::I64(ref mut buf) => DecodingBuffer::I64(&mut buf[start..]),
- }
- }
-}
-
-// A buffer for image decoding
-pub enum DecodingBuffer<'a> {
- /// A slice of unsigned bytes
- U8(&'a mut [u8]),
- /// A slice of unsigned words
- U16(&'a mut [u16]),
- /// A slice of 32 bit unsigned ints
- U32(&'a mut [u32]),
- /// A slice of 64 bit unsigned ints
- U64(&'a mut [u64]),
- /// A slice of 32 bit IEEE floats
- F32(&'a mut [f32]),
- /// A slice of 64 bit IEEE floats
- F64(&'a mut [f64]),
- /// A slice of 8 bits signed ints
- I8(&'a mut [i8]),
- /// A slice of 16 bits signed ints
- I16(&'a mut [i16]),
- /// A slice of 32 bits signed ints
- I32(&'a mut [i32]),
- /// A slice of 64 bits signed ints
- I64(&'a mut [i64]),
-}
-
-impl<'a> DecodingBuffer<'a> {
- fn byte_len(&self) -> usize {
- match *self {
- DecodingBuffer::U8(_) => 1,
- DecodingBuffer::U16(_) => 2,
- DecodingBuffer::U32(_) => 4,
- DecodingBuffer::U64(_) => 8,
- DecodingBuffer::F32(_) => 4,
- DecodingBuffer::F64(_) => 8,
- DecodingBuffer::I8(_) => 1,
- DecodingBuffer::I16(_) => 2,
- DecodingBuffer::I32(_) => 4,
- DecodingBuffer::I64(_) => 8,
- }
- }
-
- fn copy<'b>(&'b mut self) -> DecodingBuffer<'b>
- where
- 'a: 'b,
- {
- match *self {
- DecodingBuffer::U8(ref mut buf) => DecodingBuffer::U8(buf),
- DecodingBuffer::U16(ref mut buf) => DecodingBuffer::U16(buf),
- DecodingBuffer::U32(ref mut buf) => DecodingBuffer::U32(buf),
- DecodingBuffer::U64(ref mut buf) => DecodingBuffer::U64(buf),
- DecodingBuffer::F32(ref mut buf) => DecodingBuffer::F32(buf),
- DecodingBuffer::F64(ref mut buf) => DecodingBuffer::F64(buf),
- DecodingBuffer::I8(ref mut buf) => DecodingBuffer::I8(buf),
- DecodingBuffer::I16(ref mut buf) => DecodingBuffer::I16(buf),
- DecodingBuffer::I32(ref mut buf) => DecodingBuffer::I32(buf),
- DecodingBuffer::I64(ref mut buf) => DecodingBuffer::I64(buf),
- }
- }
-
- fn subrange<'b>(&'b mut self, range: Range<usize>) -> DecodingBuffer<'b>
- where
- 'a: 'b,
- {
- match *self {
- DecodingBuffer::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[range]),
- DecodingBuffer::U16(ref mut buf) => DecodingBuffer::U16(&mut buf[range]),
- DecodingBuffer::U32(ref mut buf) => DecodingBuffer::U32(&mut buf[range]),
- DecodingBuffer::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[range]),
- DecodingBuffer::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[range]),
- DecodingBuffer::F64(ref mut buf) => DecodingBuffer::F64(&mut buf[range]),
- DecodingBuffer::I8(ref mut buf) => DecodingBuffer::I8(&mut buf[range]),
- DecodingBuffer::I16(ref mut buf) => DecodingBuffer::I16(&mut buf[range]),
- DecodingBuffer::I32(ref mut buf) => DecodingBuffer::I32(&mut buf[range]),
- DecodingBuffer::I64(ref mut buf) => DecodingBuffer::I64(&mut buf[range]),
- }
- }
-
- fn as_bytes_mut(&mut self) -> &mut [u8] {
- match self {
- 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),
- }
- }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq)]
-/// Chunk type of the internal representation
-pub enum ChunkType {
- Strip,
- Tile,
-}
-
-/// Decoding limits
-#[derive(Clone, Debug)]
-pub struct Limits {
- /// The maximum size of any `DecodingResult` in bytes, the default is
- /// 256MiB. If the entire image is decoded at once, then this will
- /// be the maximum size of the image. If it is decoded one strip at a
- /// time, this will be the maximum size of a strip.
- pub decoding_buffer_size: usize,
- /// The maximum size of any ifd value in bytes, the default is
- /// 1MiB.
- pub ifd_value_size: usize,
- /// Maximum size for intermediate buffer which may be used to limit the amount of data read per
- /// segment even if the entire image is decoded at once.
- pub intermediate_buffer_size: usize,
- /// The purpose of this is to prevent all the fields of the struct from
- /// being public, as this would make adding new fields a major version
- /// bump.
- _non_exhaustive: (),
-}
-
-impl Limits {
- /// A configuration that does not impose any limits.
- ///
- /// This is a good start if the caller only wants to impose selective limits, contrary to the
- /// default limits which allows selectively disabling limits.
- ///
- /// Note that this configuration is likely to crash on excessively large images since,
- /// naturally, the machine running the program does not have infinite memory.
- pub fn unlimited() -> Limits {
- Limits {
- decoding_buffer_size: usize::max_value(),
- ifd_value_size: usize::max_value(),
- intermediate_buffer_size: usize::max_value(),
- _non_exhaustive: (),
- }
- }
-}
-
-impl Default for Limits {
- fn default() -> Limits {
- Limits {
- decoding_buffer_size: 256 * 1024 * 1024,
- intermediate_buffer_size: 128 * 1024 * 1024,
- ifd_value_size: 1024 * 1024,
- _non_exhaustive: (),
- }
- }
-}
-
-/// The representation of a TIFF decoder
-///
-/// Currently does not support decoding of interlaced images
-#[derive(Debug)]
-pub struct Decoder<R>
-where
- R: Read + Seek,
-{
- reader: SmartReader<R>,
- bigtiff: bool,
- limits: Limits,
- next_ifd: Option<u64>,
- ifd_offsets: Vec<u64>,
- seen_ifds: HashSet<u64>,
- image: Image,
-}
-
-trait Wrapping {
- fn wrapping_add(&self, other: Self) -> Self;
-}
-
-impl Wrapping for u8 {
- fn wrapping_add(&self, other: Self) -> Self {
- u8::wrapping_add(*self, other)
- }
-}
-
-impl Wrapping for u16 {
- fn wrapping_add(&self, other: Self) -> Self {
- u16::wrapping_add(*self, other)
- }
-}
-
-impl Wrapping for u32 {
- fn wrapping_add(&self, other: Self) -> Self {
- u32::wrapping_add(*self, other)
- }
-}
-
-impl Wrapping for u64 {
- fn wrapping_add(&self, other: Self) -> Self {
- u64::wrapping_add(*self, other)
- }
-}
-
-impl Wrapping for i8 {
- fn wrapping_add(&self, other: Self) -> Self {
- i8::wrapping_add(*self, other)
- }
-}
-
-impl Wrapping for i16 {
- fn wrapping_add(&self, other: Self) -> Self {
- i16::wrapping_add(*self, other)
- }
-}
-
-impl Wrapping for i32 {
- fn wrapping_add(&self, other: Self) -> Self {
- i32::wrapping_add(*self, other)
- }
-}
-
-impl Wrapping for i64 {
- fn wrapping_add(&self, other: Self) -> Self {
- i64::wrapping_add(*self, other)
- }
-}
-
-fn rev_hpredict_nsamp<T: Copy + Wrapping>(image: &mut [T], samples: usize) {
- for col in samples..image.len() {
- image[col] = image[col].wrapping_add(image[col - samples]);
- }
-}
-
-pub fn fp_predict_f32(input: &mut [u8], output: &mut [f32], samples: usize) {
- rev_hpredict_nsamp(input, samples);
- for i in 0..output.len() {
- // TODO: use f32::from_be_bytes() when we can (version 1.40)
- output[i] = f32::from_bits(u32::from_be_bytes([
- input[input.len() / 4 * 0 + i],
- input[input.len() / 4 * 1 + i],
- input[input.len() / 4 * 2 + i],
- input[input.len() / 4 * 3 + i],
- ]));
- }
-}
-
-pub fn fp_predict_f64(input: &mut [u8], output: &mut [f64], samples: usize) {
- rev_hpredict_nsamp(input, samples);
- for i in 0..output.len() {
- // TODO: use f64::from_be_bytes() when we can (version 1.40)
- output[i] = f64::from_bits(u64::from_be_bytes([
- input[input.len() / 8 * 0 + i],
- input[input.len() / 8 * 1 + i],
- input[input.len() / 8 * 2 + i],
- input[input.len() / 8 * 3 + i],
- input[input.len() / 8 * 4 + i],
- input[input.len() / 8 * 5 + i],
- input[input.len() / 8 * 6 + i],
- input[input.len() / 8 * 7 + i],
- ]));
- }
-}
-
-fn fix_endianness_and_predict(
- mut image: DecodingBuffer,
- samples: usize,
- byte_order: ByteOrder,
- predictor: Predictor,
-) {
- match predictor {
- Predictor::None => {
- fix_endianness(&mut image, byte_order);
- }
- Predictor::Horizontal => {
- fix_endianness(&mut image, byte_order);
- match image {
- DecodingBuffer::U8(buf) => rev_hpredict_nsamp(buf, samples),
- DecodingBuffer::U16(buf) => rev_hpredict_nsamp(buf, samples),
- DecodingBuffer::U32(buf) => rev_hpredict_nsamp(buf, samples),
- DecodingBuffer::U64(buf) => rev_hpredict_nsamp(buf, samples),
- DecodingBuffer::I8(buf) => rev_hpredict_nsamp(buf, samples),
- DecodingBuffer::I16(buf) => rev_hpredict_nsamp(buf, samples),
- DecodingBuffer::I32(buf) => rev_hpredict_nsamp(buf, samples),
- DecodingBuffer::I64(buf) => rev_hpredict_nsamp(buf, samples),
- DecodingBuffer::F32(_) | DecodingBuffer::F64(_) => {
- unreachable!("Caller should have validated arguments. Please file a bug.")
- }
- }
- }
- Predictor::FloatingPoint => {
- let mut buffer_copy = image.as_bytes_mut().to_vec();
- match image {
- DecodingBuffer::F32(buf) => fp_predict_f32(&mut buffer_copy, buf, samples),
- DecodingBuffer::F64(buf) => fp_predict_f64(&mut buffer_copy, buf, samples),
- _ => unreachable!("Caller should have validated arguments. Please file a bug."),
- }
- }
- }
-}
-
-fn invert_colors_unsigned<T>(buffer: &mut [T], max: T)
-where
- T: std::ops::Sub<T> + std::ops::Sub<Output = T> + Copy,
-{
- for datum in buffer.iter_mut() {
- *datum = max - *datum
- }
-}
-
-fn invert_colors_fp<T>(buffer: &mut [T], max: T)
-where
- T: std::ops::Sub<T> + std::ops::Sub<Output = T> + Copy,
-{
- for datum in buffer.iter_mut() {
- // FIXME: assumes [0, 1) range for floats
- *datum = max - *datum
- }
-}
-
-fn invert_colors(buf: &mut DecodingBuffer, color_type: ColorType) {
- match (color_type, buf) {
- (ColorType::Gray(64), DecodingBuffer::U64(ref mut buffer)) => {
- invert_colors_unsigned(buffer, 0xffff_ffff_ffff_ffff);
- }
- (ColorType::Gray(32), DecodingBuffer::U32(ref mut buffer)) => {
- invert_colors_unsigned(buffer, 0xffff_ffff);
- }
- (ColorType::Gray(16), DecodingBuffer::U16(ref mut buffer)) => {
- invert_colors_unsigned(buffer, 0xffff);
- }
- (ColorType::Gray(n), DecodingBuffer::U8(ref mut buffer)) if n <= 8 => {
- invert_colors_unsigned(buffer, 0xff);
- }
- (ColorType::Gray(32), DecodingBuffer::F32(ref mut buffer)) => {
- invert_colors_fp(buffer, 1.0);
- }
- (ColorType::Gray(64), DecodingBuffer::F64(ref mut buffer)) => {
- invert_colors_fp(buffer, 1.0);
- }
- _ => {}
- }
-}
-
-/// Fix endianness. If `byte_order` matches the host, then conversion is a no-op.
-fn fix_endianness(buf: &mut DecodingBuffer, byte_order: ByteOrder) {
- match byte_order {
- ByteOrder::LittleEndian => match buf {
- DecodingBuffer::U8(_) | DecodingBuffer::I8(_) => {}
- DecodingBuffer::U16(b) => b.iter_mut().for_each(|v| *v = u16::from_le(*v)),
- DecodingBuffer::I16(b) => b.iter_mut().for_each(|v| *v = i16::from_le(*v)),
- DecodingBuffer::U32(b) => b.iter_mut().for_each(|v| *v = u32::from_le(*v)),
- DecodingBuffer::I32(b) => b.iter_mut().for_each(|v| *v = i32::from_le(*v)),
- DecodingBuffer::U64(b) => b.iter_mut().for_each(|v| *v = u64::from_le(*v)),
- DecodingBuffer::I64(b) => b.iter_mut().for_each(|v| *v = i64::from_le(*v)),
- DecodingBuffer::F32(b) => b
- .iter_mut()
- .for_each(|v| *v = f32::from_bits(u32::from_le(v.to_bits()))),
- DecodingBuffer::F64(b) => b
- .iter_mut()
- .for_each(|v| *v = f64::from_bits(u64::from_le(v.to_bits()))),
- },
- ByteOrder::BigEndian => match buf {
- DecodingBuffer::U8(_) | DecodingBuffer::I8(_) => {}
- DecodingBuffer::U16(b) => b.iter_mut().for_each(|v| *v = u16::from_be(*v)),
- DecodingBuffer::I16(b) => b.iter_mut().for_each(|v| *v = i16::from_be(*v)),
- DecodingBuffer::U32(b) => b.iter_mut().for_each(|v| *v = u32::from_be(*v)),
- DecodingBuffer::I32(b) => b.iter_mut().for_each(|v| *v = i32::from_be(*v)),
- DecodingBuffer::U64(b) => b.iter_mut().for_each(|v| *v = u64::from_be(*v)),
- DecodingBuffer::I64(b) => b.iter_mut().for_each(|v| *v = i64::from_be(*v)),
- DecodingBuffer::F32(b) => b
- .iter_mut()
- .for_each(|v| *v = f32::from_bits(u32::from_be(v.to_bits()))),
- DecodingBuffer::F64(b) => b
- .iter_mut()
- .for_each(|v| *v = f64::from_bits(u64::from_be(v.to_bits()))),
- },
- };
-}
-
-impl<R: Read + Seek> Decoder<R> {
- /// Create a new decoder that decodes from the stream ```r```
- pub fn new(mut r: R) -> TiffResult<Decoder<R>> {
- let mut endianess = Vec::with_capacity(2);
- (&mut r).take(2).read_to_end(&mut endianess)?;
- let byte_order = match &*endianess {
- b"II" => ByteOrder::LittleEndian,
- b"MM" => ByteOrder::BigEndian,
- _ => {
- return Err(TiffError::FormatError(
- TiffFormatError::TiffSignatureNotFound,
- ))
- }
- };
- let mut reader = SmartReader::wrap(r, byte_order);
-
- let bigtiff = match reader.read_u16()? {
- 42 => false,
- 43 => {
- // Read bytesize of offsets (in bigtiff it's alway 8 but provide a way to move to 16 some day)
- if reader.read_u16()? != 8 {
- return Err(TiffError::FormatError(
- TiffFormatError::TiffSignatureNotFound,
- ));
- }
- // This constant should always be 0
- if reader.read_u16()? != 0 {
- return Err(TiffError::FormatError(
- TiffFormatError::TiffSignatureNotFound,
- ));
- }
- true
- }
- _ => {
- return Err(TiffError::FormatError(
- TiffFormatError::TiffSignatureInvalid,
- ))
- }
- };
- let next_ifd = if bigtiff {
- Some(reader.read_u64()?)
- } else {
- Some(u64::from(reader.read_u32()?))
- };
-
- let mut seen_ifds = HashSet::new();
- seen_ifds.insert(*next_ifd.as_ref().unwrap());
- let ifd_offsets = vec![*next_ifd.as_ref().unwrap()];
-
- let mut decoder = Decoder {
- reader,
- bigtiff,
- limits: Default::default(),
- next_ifd,
- ifd_offsets,
- seen_ifds,
- image: Image {
- ifd: None,
- width: 0,
- height: 0,
- bits_per_sample: vec![1],
- samples: 1,
- sample_format: vec![SampleFormat::Uint],
- photometric_interpretation: PhotometricInterpretation::BlackIsZero,
- compression_method: CompressionMethod::None,
- jpeg_tables: None,
- predictor: Predictor::None,
- chunk_type: ChunkType::Strip,
- strip_decoder: None,
- tile_attributes: None,
- chunk_offsets: Vec::new(),
- chunk_bytes: Vec::new(),
- },
- };
- decoder.next_image()?;
- Ok(decoder)
- }
-
- pub fn with_limits(mut self, limits: Limits) -> Decoder<R> {
- self.limits = limits;
- self
- }
-
- pub fn dimensions(&mut self) -> TiffResult<(u32, u32)> {
- Ok((self.image().width, self.image().height))
- }
-
- pub fn colortype(&mut self) -> TiffResult<ColorType> {
- self.image().colortype()
- }
-
- fn image(&self) -> &Image {
- &self.image
- }
-
- /// Loads the IFD at the specified index in the list, if one exists
- pub fn seek_to_image(&mut self, ifd_index: usize) -> TiffResult<()> {
- // Check whether we have seen this IFD before, if so then the index will be less than the length of the list of ifd offsets
- if ifd_index >= self.ifd_offsets.len() {
- // We possibly need to load in the next IFD
- if self.next_ifd.is_none() {
- return Err(TiffError::FormatError(
- TiffFormatError::ImageFileDirectoryNotFound,
- ));
- }
-
- loop {
- // Follow the list until we find the one we want, or we reach the end, whichever happens first
- let (_ifd, next_ifd) = self.next_ifd()?;
-
- if next_ifd.is_none() {
- break;
- }
-
- if ifd_index < self.ifd_offsets.len() {
- break;
- }
- }
- }
-
- // If the index is within the list of ifds then we can load the selected image/IFD
- if let Some(ifd_offset) = self.ifd_offsets.get(ifd_index) {
- let (ifd, _next_ifd) = Self::read_ifd(&mut self.reader, self.bigtiff, *ifd_offset)?;
-
- self.image = Image::from_reader(&mut self.reader, ifd, &self.limits, self.bigtiff)?;
-
- Ok(())
- } else {
- Err(TiffError::FormatError(
- TiffFormatError::ImageFileDirectoryNotFound,
- ))
- }
- }
-
- fn next_ifd(&mut self) -> TiffResult<(Directory, Option<u64>)> {
- if self.next_ifd.is_none() {
- return Err(TiffError::FormatError(
- TiffFormatError::ImageFileDirectoryNotFound,
- ));
- }
-
- let (ifd, next_ifd) = Self::read_ifd(
- &mut self.reader,
- self.bigtiff,
- self.next_ifd.take().unwrap(),
- )?;
-
- if let Some(next) = next_ifd {
- if !self.seen_ifds.insert(next) {
- return Err(TiffError::FormatError(TiffFormatError::CycleInOffsets));
- }
- self.next_ifd = Some(next);
- self.ifd_offsets.push(next);
- }
-
- Ok((ifd, next_ifd))
- }
-
- /// Reads in the next image.
- /// If there is no further image in the TIFF file a format error is returned.
- /// To determine whether there are more images call `TIFFDecoder::more_images` instead.
- pub fn next_image(&mut self) -> TiffResult<()> {
- let (ifd, _next_ifd) = self.next_ifd()?;
-
- self.image = Image::from_reader(&mut self.reader, ifd, &self.limits, self.bigtiff)?;
- Ok(())
- }
-
- /// Returns `true` if there is at least one more image available.
- pub fn more_images(&self) -> bool {
- self.next_ifd.is_some()
- }
-
- /// Returns the byte_order
- pub fn byte_order(&self) -> ByteOrder {
- self.reader.byte_order
- }
-
- #[inline]
- pub fn read_ifd_offset(&mut self) -> Result<u64, io::Error> {
- if self.bigtiff {
- self.read_long8()
- } else {
- self.read_long().map(u64::from)
- }
- }
-
- /// Reads a TIFF byte value
- #[inline]
- pub fn read_byte(&mut self) -> Result<u8, io::Error> {
- let mut buf = [0; 1];
- self.reader.read_exact(&mut buf)?;
- Ok(buf[0])
- }
-
- /// Reads a TIFF short value
- #[inline]
- pub fn read_short(&mut self) -> Result<u16, io::Error> {
- self.reader.read_u16()
- }
-
- /// Reads a TIFF sshort value
- #[inline]
- pub fn read_sshort(&mut self) -> Result<i16, io::Error> {
- self.reader.read_i16()
- }
-
- /// Reads a TIFF long value
- #[inline]
- pub fn read_long(&mut self) -> Result<u32, io::Error> {
- self.reader.read_u32()
- }
-
- /// Reads a TIFF slong value
- #[inline]
- pub fn read_slong(&mut self) -> Result<i32, io::Error> {
- self.reader.read_i32()
- }
-
- /// Reads a TIFF float value
- #[inline]
- pub fn read_float(&mut self) -> Result<f32, io::Error> {
- self.reader.read_f32()
- }
-
- /// Reads a TIFF double value
- #[inline]
- pub fn read_double(&mut self) -> Result<f64, io::Error> {
- self.reader.read_f64()
- }
-
- #[inline]
- pub fn read_long8(&mut self) -> Result<u64, io::Error> {
- self.reader.read_u64()
- }
-
- #[inline]
- pub fn read_slong8(&mut self) -> Result<i64, io::Error> {
- self.reader.read_i64()
- }
-
- /// Reads a string
- #[inline]
- pub fn read_string(&mut self, length: usize) -> TiffResult<String> {
- let mut out = vec![0; length];
- self.reader.read_exact(&mut out)?;
- // Strings may be null-terminated, so we trim anything downstream of the null byte
- if let Some(first) = out.iter().position(|&b| b == 0) {
- out.truncate(first);
- }
- Ok(String::from_utf8(out)?)
- }
-
- /// Reads a TIFF IFA offset/value field
- #[inline]
- pub fn read_offset(&mut self) -> TiffResult<[u8; 4]> {
- if self.bigtiff {
- return Err(TiffError::FormatError(
- TiffFormatError::InconsistentSizesEncountered,
- ));
- }
- let mut val = [0; 4];
- self.reader.read_exact(&mut val)?;
- Ok(val)
- }
-
- /// Reads a TIFF IFA offset/value field
- #[inline]
- pub fn read_offset_u64(&mut self) -> Result<[u8; 8], io::Error> {
- let mut val = [0; 8];
- self.reader.read_exact(&mut val)?;
- Ok(val)
- }
-
- /// Moves the cursor to the specified offset
- #[inline]
- pub fn goto_offset(&mut self, offset: u32) -> io::Result<()> {
- self.goto_offset_u64(offset.into())
- }
-
- #[inline]
- pub fn goto_offset_u64(&mut self, offset: u64) -> io::Result<()> {
- self.reader.seek(io::SeekFrom::Start(offset)).map(|_| ())
- }
-
- /// Reads a IFD entry.
- // An IFD entry has four fields:
- //
- // Tag 2 bytes
- // Type 2 bytes
- // Count 4 bytes
- // Value 4 bytes either a pointer the value itself
- fn read_entry(
- reader: &mut SmartReader<R>,
- bigtiff: bool,
- ) -> TiffResult<Option<(Tag, ifd::Entry)>> {
- let tag = Tag::from_u16_exhaustive(reader.read_u16()?);
- let type_ = match Type::from_u16(reader.read_u16()?) {
- Some(t) => t,
- None => {
- // Unknown type. Skip this entry according to spec.
- reader.read_u32()?;
- reader.read_u32()?;
- return Ok(None);
- }
- };
- let entry = if bigtiff {
- let mut offset = [0; 8];
-
- let count = reader.read_u64()?;
- reader.read_exact(&mut offset)?;
- ifd::Entry::new_u64(type_, count, offset)
- } else {
- let mut offset = [0; 4];
-
- let count = reader.read_u32()?;
- reader.read_exact(&mut offset)?;
- ifd::Entry::new(type_, count, offset)
- };
- Ok(Some((tag, entry)))
- }
-
- /// Reads the IFD starting at the indicated location.
- fn read_ifd(
- reader: &mut SmartReader<R>,
- bigtiff: bool,
- ifd_location: u64,
- ) -> TiffResult<(Directory, Option<u64>)> {
- reader.goto_offset(ifd_location)?;
-
- let mut dir: Directory = HashMap::new();
-
- let num_tags = if bigtiff {
- reader.read_u64()?
- } else {
- reader.read_u16()?.into()
- };
- for _ in 0..num_tags {
- let (tag, entry) = match Self::read_entry(reader, bigtiff)? {
- Some(val) => val,
- None => {
- continue;
- } // Unknown data type in tag, skip
- };
- dir.insert(tag, entry);
- }
-
- let next_ifd = if bigtiff {
- reader.read_u64()?
- } else {
- reader.read_u32()?.into()
- };
-
- let next_ifd = match next_ifd {
- 0 => None,
- _ => Some(next_ifd),
- };
-
- Ok((dir, next_ifd))
- }
-
- /// Tries to retrieve a tag.
- /// Return `Ok(None)` if the tag is not present.
- pub fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<ifd::Value>> {
- let entry = match self.image().ifd.as_ref().unwrap().get(&tag) {
- None => return Ok(None),
- Some(entry) => entry.clone(),
- };
-
- Ok(Some(entry.val(
- &self.limits,
- self.bigtiff,
- &mut self.reader,
- )?))
- }
-
- /// 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())
- })
- .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>>> {
- 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()
- })
- .transpose()
- }
-
- /// Tries to retrieve a tag and convert it to the desired unsigned type.
- /// Returns an error if the tag is not present.
- pub fn get_tag_unsigned<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<T> {
- self.find_tag_unsigned(tag)?
- .ok_or_else(|| TiffFormatError::RequiredTagNotFound(tag).into())
- }
-
- /// Tries to retrieve a tag.
- /// Returns an error if the tag is not present
- pub fn get_tag(&mut self, tag: Tag) -> TiffResult<ifd::Value> {
- match self.find_tag(tag)? {
- Some(val) => Ok(val),
- None => Err(TiffError::FormatError(
- TiffFormatError::RequiredTagNotFound(tag),
- )),
- }
- }
-
- /// Tries to retrieve a tag and convert it to the desired type.
- pub fn get_tag_u32(&mut self, tag: Tag) -> TiffResult<u32> {
- self.get_tag(tag)?.into_u32()
- }
- pub fn get_tag_u64(&mut self, tag: Tag) -> TiffResult<u64> {
- self.get_tag(tag)?.into_u64()
- }
-
- /// Tries to retrieve a tag and convert it to the desired type.
- pub fn get_tag_f32(&mut self, tag: Tag) -> TiffResult<f32> {
- self.get_tag(tag)?.into_f32()
- }
-
- /// Tries to retrieve a tag and convert it to the desired type.
- pub fn get_tag_f64(&mut self, tag: Tag) -> TiffResult<f64> {
- self.get_tag(tag)?.into_f64()
- }
-
- /// Tries to retrieve a tag and convert it to the desired type.
- pub fn get_tag_u32_vec(&mut self, tag: Tag) -> TiffResult<Vec<u32>> {
- self.get_tag(tag)?.into_u32_vec()
- }
-
- pub fn get_tag_u16_vec(&mut self, tag: Tag) -> TiffResult<Vec<u16>> {
- self.get_tag(tag)?.into_u16_vec()
- }
- pub fn get_tag_u64_vec(&mut self, tag: Tag) -> TiffResult<Vec<u64>> {
- self.get_tag(tag)?.into_u64_vec()
- }
-
- /// Tries to retrieve a tag and convert it to the desired type.
- pub fn get_tag_f32_vec(&mut self, tag: Tag) -> TiffResult<Vec<f32>> {
- self.get_tag(tag)?.into_f32_vec()
- }
-
- /// Tries to retrieve a tag and convert it to the desired type.
- pub fn get_tag_f64_vec(&mut self, tag: Tag) -> TiffResult<Vec<f64>> {
- self.get_tag(tag)?.into_f64_vec()
- }
-
- /// Tries to retrieve a tag and convert it to a 8bit vector.
- pub fn get_tag_u8_vec(&mut self, tag: Tag) -> TiffResult<Vec<u8>> {
- self.get_tag(tag)?.into_u8_vec()
- }
-
- /// Tries to retrieve a tag and convert it to a ascii vector.
- pub fn get_tag_ascii_string(&mut self, tag: Tag) -> TiffResult<String> {
- self.get_tag(tag)?.into_string()
- }
-
- fn check_chunk_type(&self, expected: ChunkType) -> TiffResult<()> {
- if expected != self.image().chunk_type {
- return Err(TiffError::UsageError(UsageError::InvalidChunkType(
- expected,
- self.image().chunk_type,
- )));
- }
-
- Ok(())
- }
-
- /// The chunk type (Strips / Tiles) of the image
- pub fn get_chunk_type(&self) -> ChunkType {
- self.image().chunk_type
- }
-
- /// Number of strips in image
- pub fn strip_count(&mut self) -> TiffResult<u32> {
- self.check_chunk_type(ChunkType::Strip)?;
- let rows_per_strip = self.image().strip_decoder.as_ref().unwrap().rows_per_strip;
-
- if rows_per_strip == 0 {
- return Ok(0);
- }
-
- // rows_per_strip - 1 can never fail since we know it's at least 1
- let height = match self.image().height.checked_add(rows_per_strip - 1) {
- Some(h) => h,
- None => return Err(TiffError::IntSizeError),
- };
-
- Ok(height / rows_per_strip)
- }
-
- /// Number of tiles in image
- pub fn tile_count(&mut self) -> TiffResult<u32> {
- self.check_chunk_type(ChunkType::Tile)?;
- Ok(u32::try_from(self.image().chunk_offsets.len())?)
- }
-
- pub fn read_chunk_to_buffer(
- &mut self,
- mut buffer: DecodingBuffer,
- chunk_index: u32,
- output_width: usize,
- ) -> TiffResult<()> {
- let offset = self.image.chunk_file_range(chunk_index)?.0;
- self.goto_offset_u64(offset)?;
-
- let byte_order = self.reader.byte_order;
-
- self.image.expand_chunk(
- &mut self.reader,
- buffer.copy(),
- output_width,
- byte_order,
- chunk_index,
- )?;
-
- Ok(())
- }
-
- fn result_buffer(&self, width: usize, height: usize) -> TiffResult<DecodingResult> {
- let buffer_size = match width
- .checked_mul(height)
- .and_then(|x| x.checked_mul(self.image().bits_per_sample.len()))
- {
- Some(s) => s,
- None => return Err(TiffError::LimitsExceeded),
- };
-
- let max_sample_bits = self
- .image()
- .bits_per_sample
- .iter()
- .cloned()
- .max()
- .unwrap_or(8);
- match self
- .image()
- .sample_format
- .first()
- .unwrap_or(&SampleFormat::Uint)
- {
- SampleFormat::Uint => match max_sample_bits {
- n if n <= 8 => DecodingResult::new_u8(buffer_size, &self.limits),
- 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),
- )),
- },
- 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),
- )),
- },
- SampleFormat::Int => match max_sample_bits {
- n if n <= 8 => DecodingResult::new_i8(buffer_size, &self.limits),
- n if n <= 16 => DecodingResult::new_i16(buffer_size, &self.limits),
- n if n <= 32 => DecodingResult::new_i32(buffer_size, &self.limits),
- n if n <= 64 => DecodingResult::new_i64(buffer_size, &self.limits),
- n => Err(TiffError::UnsupportedError(
- TiffUnsupportedError::UnsupportedBitsPerChannel(n),
- )),
- },
- format => {
- Err(TiffUnsupportedError::UnsupportedSampleFormat(vec![format.clone()]).into())
- }
- }
- }
-
- /// Read the specified chunk (at index `chunk_index`) and return the binary data as a Vector.
- pub fn read_chunk(&mut self, chunk_index: u32) -> TiffResult<DecodingResult> {
- let data_dims = self.image().chunk_data_dimensions(chunk_index)?;
-
- let mut result = self.result_buffer(data_dims.0 as usize, data_dims.1 as usize)?;
-
- self.read_chunk_to_buffer(result.as_buffer(0), chunk_index, data_dims.0 as usize)?;
-
- Ok(result)
- }
-
- /// Returns the default chunk size for the current image. Any given chunk in the image is at most as large as
- /// the value returned here. For the size of the data (chunk minus padding), use `chunk_data_dimensions`.
- pub fn chunk_dimensions(&self) -> (u32, u32) {
- self.image().chunk_dimensions().unwrap()
- }
-
- /// Returns the size of the data in the chunk with the specified index. This is the default size of the chunk,
- /// minus any padding.
- pub fn chunk_data_dimensions(&self, chunk_index: u32) -> (u32, u32) {
- self.image()
- .chunk_data_dimensions(chunk_index)
- .expect("invalid chunk_index")
- }
-
- /// Decodes the entire image and return it as a Vector
- pub fn read_image(&mut self) -> TiffResult<DecodingResult> {
- let width = self.image().width;
- let height = self.image().height;
- let mut result = self.result_buffer(width as usize, height as usize)?;
- if width == 0 || height == 0 {
- return Ok(result);
- }
-
- let chunk_dimensions = self.image().chunk_dimensions()?;
- let chunk_dimensions = (
- chunk_dimensions.0.min(width),
- chunk_dimensions.1.min(height),
- );
- if chunk_dimensions.0 == 0 || chunk_dimensions.1 == 0 {
- return Err(TiffError::FormatError(
- TiffFormatError::InconsistentSizesEncountered,
- ));
- }
-
- let samples = self.image().bits_per_sample.len();
- if samples == 0 {
- return Err(TiffError::FormatError(
- TiffFormatError::InconsistentSizesEncountered,
- ));
- }
-
- let chunks_across = ((width - 1) / chunk_dimensions.0 + 1) as usize;
- let strip_samples = width as usize * chunk_dimensions.1 as usize * samples;
-
- for chunk in 0..self.image().chunk_offsets.len() {
- self.goto_offset_u64(self.image().chunk_offsets[chunk])?;
-
- let x = chunk % chunks_across;
- let y = chunk / chunks_across;
- let buffer_offset = y * strip_samples + x * chunk_dimensions.0 as usize * samples;
- let byte_order = self.reader.byte_order;
- self.image.expand_chunk(
- &mut self.reader,
- result.as_buffer(buffer_offset).copy(),
- width as usize,
- byte_order,
- chunk as u32,
- )?;
- }
-
- Ok(result)
- }
-}
diff --git a/vendor/tiff/src/decoder/stream.rs b/vendor/tiff/src/decoder/stream.rs
deleted file mode 100644
index e0323c2..0000000
--- a/vendor/tiff/src/decoder/stream.rs
+++ /dev/null
@@ -1,435 +0,0 @@
-//! All IO functionality needed for TIFF decoding
-
-use std::convert::TryFrom;
-use std::io::{self, BufRead, BufReader, Read, Seek, SeekFrom, Take};
-use std::sync::Arc;
-
-/// Byte order of the TIFF file.
-#[derive(Clone, Copy, Debug)]
-pub enum ByteOrder {
- /// little endian byte order
- LittleEndian,
- /// big endian byte order
- BigEndian,
-}
-
-/// Reader that is aware of the byte order.
-pub trait EndianReader: Read {
- /// Byte order that should be adhered to
- fn byte_order(&self) -> ByteOrder;
-
- /// Reads an u16
- #[inline(always)]
- fn read_u16(&mut self) -> Result<u16, io::Error> {
- let mut n = [0u8; 2];
- self.read_exact(&mut n)?;
- Ok(match self.byte_order() {
- ByteOrder::LittleEndian => u16::from_le_bytes(n),
- ByteOrder::BigEndian => u16::from_be_bytes(n),
- })
- }
-
- /// Reads an i8
- #[inline(always)]
- fn read_i8(&mut self) -> Result<i8, io::Error> {
- let mut n = [0u8; 1];
- self.read_exact(&mut n)?;
- Ok(match self.byte_order() {
- ByteOrder::LittleEndian => i8::from_le_bytes(n),
- ByteOrder::BigEndian => i8::from_be_bytes(n),
- })
- }
-
- /// Reads an i16
- #[inline(always)]
- fn read_i16(&mut self) -> Result<i16, io::Error> {
- let mut n = [0u8; 2];
- self.read_exact(&mut n)?;
- Ok(match self.byte_order() {
- ByteOrder::LittleEndian => i16::from_le_bytes(n),
- ByteOrder::BigEndian => i16::from_be_bytes(n),
- })
- }
-
- /// Reads an u32
- #[inline(always)]
- fn read_u32(&mut self) -> Result<u32, io::Error> {
- let mut n = [0u8; 4];
- self.read_exact(&mut n)?;
- Ok(match self.byte_order() {
- ByteOrder::LittleEndian => u32::from_le_bytes(n),
- ByteOrder::BigEndian => u32::from_be_bytes(n),
- })
- }
-
- /// Reads an i32
- #[inline(always)]
- fn read_i32(&mut self) -> Result<i32, io::Error> {
- let mut n = [0u8; 4];
- self.read_exact(&mut n)?;
- Ok(match self.byte_order() {
- ByteOrder::LittleEndian => i32::from_le_bytes(n),
- ByteOrder::BigEndian => i32::from_be_bytes(n),
- })
- }
-
- /// Reads an u64
- #[inline(always)]
- fn read_u64(&mut self) -> Result<u64, io::Error> {
- let mut n = [0u8; 8];
- self.read_exact(&mut n)?;
- Ok(match self.byte_order() {
- ByteOrder::LittleEndian => u64::from_le_bytes(n),
- ByteOrder::BigEndian => u64::from_be_bytes(n),
- })
- }
-
- /// Reads an i64
- #[inline(always)]
- fn read_i64(&mut self) -> Result<i64, io::Error> {
- let mut n = [0u8; 8];
- self.read_exact(&mut n)?;
- Ok(match self.byte_order() {
- ByteOrder::LittleEndian => i64::from_le_bytes(n),
- ByteOrder::BigEndian => i64::from_be_bytes(n),
- })
- }
-
- /// Reads an f32
- #[inline(always)]
- fn read_f32(&mut self) -> Result<f32, io::Error> {
- let mut n = [0u8; 4];
- self.read_exact(&mut n)?;
- Ok(f32::from_bits(match self.byte_order() {
- ByteOrder::LittleEndian => u32::from_le_bytes(n),
- ByteOrder::BigEndian => u32::from_be_bytes(n),
- }))
- }
-
- /// Reads an f64
- #[inline(always)]
- fn read_f64(&mut self) -> Result<f64, io::Error> {
- let mut n = [0u8; 8];
- self.read_exact(&mut n)?;
- Ok(f64::from_bits(match self.byte_order() {
- ByteOrder::LittleEndian => u64::from_le_bytes(n),
- ByteOrder::BigEndian => u64::from_be_bytes(n),
- }))
- }
-}
-
-///
-/// # READERS
-///
-
-///
-/// ## Deflate Reader
-///
-
-pub type DeflateReader<R> = flate2::read::ZlibDecoder<R>;
-
-///
-/// ## LZW Reader
-///
-
-/// Reader that decompresses LZW streams
-pub struct LZWReader<R: Read> {
- reader: BufReader<Take<R>>,
- decoder: weezl::decode::Decoder,
-}
-
-impl<R: Read> LZWReader<R> {
- /// Wraps a reader
- pub fn new(reader: R, compressed_length: usize) -> LZWReader<R> {
- Self {
- reader: BufReader::with_capacity(
- (32 * 1024).min(compressed_length),
- reader.take(u64::try_from(compressed_length).unwrap()),
- ),
- decoder: weezl::decode::Decoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8),
- }
- }
-}
-
-impl<R: Read> Read for LZWReader<R> {
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- loop {
- let result = self.decoder.decode_bytes(self.reader.fill_buf()?, buf);
- self.reader.consume(result.consumed_in);
-
- match result.status {
- Ok(weezl::LzwStatus::Ok) => {
- if result.consumed_out == 0 {
- continue;
- } else {
- return Ok(result.consumed_out);
- }
- }
- Ok(weezl::LzwStatus::NoProgress) => {
- assert_eq!(result.consumed_in, 0);
- assert_eq!(result.consumed_out, 0);
- assert!(self.reader.buffer().is_empty());
- return Err(io::Error::new(
- io::ErrorKind::UnexpectedEof,
- "no lzw end code found",
- ));
- }
- Ok(weezl::LzwStatus::Done) => {
- return Ok(result.consumed_out);
- }
- Err(err) => return Err(io::Error::new(io::ErrorKind::InvalidData, err)),
- }
- }
- }
-}
-
-///
-/// ## JPEG Reader (for "new-style" JPEG format (TIFF compression tag 7))
-///
-
-pub(crate) struct JpegReader {
- jpeg_tables: Option<Arc<Vec<u8>>>,
-
- buffer: io::Cursor<Vec<u8>>,
-
- offset: usize,
-}
-
-impl JpegReader {
- /// Constructs new JpegReader wrapping a SmartReader.
- /// Because JPEG compression in TIFF allows to save quantization and/or huffman tables in one
- /// central location, the constructor accepts this data as `jpeg_tables` here containing either
- /// or both.
- /// These `jpeg_tables` are simply prepended to the remaining jpeg image data.
- /// Because these `jpeg_tables` start with a `SOI` (HEX: `0xFFD8`) or __start of image__ marker
- /// which is also at the beginning of the remaining JPEG image data and would
- /// confuse the JPEG renderer, one of these has to be taken off. In this case the first two
- /// bytes of the remaining JPEG data is removed because it follows `jpeg_tables`.
- /// Similary, `jpeg_tables` ends with a `EOI` (HEX: `0xFFD9`) or __end of image__ marker,
- /// this has to be removed as well (last two bytes of `jpeg_tables`).
- pub fn new<R: Read>(
- mut reader: R,
- length: u64,
- jpeg_tables: Option<Arc<Vec<u8>>>,
- ) -> io::Result<JpegReader> {
- // Read jpeg image data
- let mut segment = vec![0; length as usize];
-
- reader.read_exact(&mut segment[..])?;
-
- match jpeg_tables {
- Some(jpeg_tables) => {
- assert!(
- jpeg_tables.len() >= 2,
- "jpeg_tables, if given, must be at least 2 bytes long. Got {:?}",
- jpeg_tables
- );
-
- assert!(
- length >= 2,
- "if jpeg_tables is given, length must be at least 2 bytes long, got {}",
- length
- );
-
- let mut buffer = io::Cursor::new(segment);
- // Skip the first two bytes (marker bytes)
- buffer.seek(SeekFrom::Start(2))?;
-
- Ok(JpegReader {
- buffer,
- jpeg_tables: Some(jpeg_tables),
- offset: 0,
- })
- }
- None => Ok(JpegReader {
- buffer: io::Cursor::new(segment),
- jpeg_tables: None,
- offset: 0,
- }),
- }
- }
-}
-
-impl Read for JpegReader {
- // #[inline]
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- let mut start = 0;
-
- if let Some(jpeg_tables) = &self.jpeg_tables {
- if jpeg_tables.len() - 2 > self.offset {
- // Read (rest of) jpeg_tables to buf (without the last two bytes)
- let size_remaining = jpeg_tables.len() - self.offset - 2;
- let to_copy = size_remaining.min(buf.len());
-
- buf[start..start + to_copy]
- .copy_from_slice(&jpeg_tables[self.offset..self.offset + to_copy]);
-
- self.offset += to_copy;
-
- if to_copy == buf.len() {
- return Ok(to_copy);
- }
-
- start += to_copy;
- }
- }
-
- let read = self.buffer.read(&mut buf[start..])?;
- self.offset += read;
-
- Ok(read + start)
- }
-}
-
-///
-/// ## PackBits Reader
-///
-
-enum PackBitsReaderState {
- Header,
- Literal,
- Repeat { value: u8 },
-}
-
-/// Reader that unpacks Apple's `PackBits` format
-pub struct PackBitsReader<R: Read> {
- reader: Take<R>,
- state: PackBitsReaderState,
- count: usize,
-}
-
-impl<R: Read> PackBitsReader<R> {
- /// Wraps a reader
- pub fn new(reader: R, length: u64) -> Self {
- Self {
- reader: reader.take(length),
- state: PackBitsReaderState::Header,
- count: 0,
- }
- }
-}
-
-impl<R: Read> Read for PackBitsReader<R> {
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- while let PackBitsReaderState::Header = self.state {
- if self.reader.limit() == 0 {
- return Ok(0);
- }
- let mut header: [u8; 1] = [0];
- self.reader.read_exact(&mut header)?;
- let h = header[0] as i8;
- if h >= -127 && h <= -1 {
- let mut data: [u8; 1] = [0];
- self.reader.read_exact(&mut data)?;
- self.state = PackBitsReaderState::Repeat { value: data[0] };
- self.count = (1 - h as isize) as usize;
- } else if h >= 0 {
- self.state = PackBitsReaderState::Literal;
- self.count = h as usize + 1;
- } else {
- // h = -128 is a no-op.
- }
- }
-
- let length = buf.len().min(self.count);
- let actual = match self.state {
- PackBitsReaderState::Literal => self.reader.read(&mut buf[..length])?,
- PackBitsReaderState::Repeat { value } => {
- for b in &mut buf[..length] {
- *b = value;
- }
-
- length
- }
- PackBitsReaderState::Header => unreachable!(),
- };
-
- self.count -= actual;
- if self.count == 0 {
- self.state = PackBitsReaderState::Header;
- }
- return Ok(actual);
- }
-}
-
-///
-/// ## SmartReader Reader
-///
-
-/// Reader that is aware of the byte order.
-#[derive(Debug)]
-pub struct SmartReader<R>
-where
- R: Read,
-{
- reader: R,
- pub byte_order: ByteOrder,
-}
-
-impl<R> SmartReader<R>
-where
- R: Read,
-{
- /// Wraps a reader
- pub fn wrap(reader: R, byte_order: ByteOrder) -> SmartReader<R> {
- SmartReader { reader, byte_order }
- }
- pub fn into_inner(self) -> R {
- self.reader
- }
-}
-impl<R: Read + Seek> SmartReader<R> {
- pub fn goto_offset(&mut self, offset: u64) -> io::Result<()> {
- self.seek(io::SeekFrom::Start(offset)).map(|_| ())
- }
-}
-
-impl<R> EndianReader for SmartReader<R>
-where
- R: Read,
-{
- #[inline(always)]
- fn byte_order(&self) -> ByteOrder {
- self.byte_order
- }
-}
-
-impl<R: Read> Read for SmartReader<R> {
- #[inline]
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- self.reader.read(buf)
- }
-}
-
-impl<R: Read + Seek> Seek for SmartReader<R> {
- #[inline]
- fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
- self.reader.seek(pos)
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
-
- #[test]
- fn test_packbits() {
- let encoded = vec![
- 0xFE, 0xAA, 0x02, 0x80, 0x00, 0x2A, 0xFD, 0xAA, 0x03, 0x80, 0x00, 0x2A, 0x22, 0xF7,
- 0xAA,
- ];
- let encoded_len = encoded.len();
-
- let buff = io::Cursor::new(encoded);
- let mut decoder = PackBitsReader::new(buff, encoded_len as u64);
-
- let mut decoded = Vec::new();
- decoder.read_to_end(&mut decoded).unwrap();
-
- let expected = vec![
- 0xAA, 0xAA, 0xAA, 0x80, 0x00, 0x2A, 0xAA, 0xAA, 0xAA, 0xAA, 0x80, 0x00, 0x2A, 0x22,
- 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
- ];
- assert_eq!(decoded, expected);
- }
-}
diff --git a/vendor/tiff/src/decoder/tag_reader.rs b/vendor/tiff/src/decoder/tag_reader.rs
deleted file mode 100644
index 837da40..0000000
--- a/vendor/tiff/src/decoder/tag_reader.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-use std::convert::TryFrom;
-use std::io::{Read, Seek};
-
-use crate::tags::Tag;
-use crate::{TiffError, TiffFormatError, TiffResult};
-
-use super::ifd::{Directory, Value};
-use super::stream::SmartReader;
-use super::Limits;
-
-pub(crate) struct TagReader<'a, R: Read + Seek> {
- pub reader: &'a mut SmartReader<R>,
- pub ifd: &'a Directory,
- pub limits: &'a Limits,
- pub bigtiff: bool,
-}
-impl<'a, R: Read + Seek> TagReader<'a, R> {
- pub(crate) fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<Value>> {
- Ok(match self.ifd.get(&tag) {
- Some(entry) => Some(entry.clone().val(self.limits, self.bigtiff, self.reader)?),
- None => None,
- })
- }
- pub(crate) fn require_tag(&mut self, tag: Tag) -> TiffResult<Value> {
- match self.find_tag(tag)? {
- Some(val) => Ok(val),
- None => Err(TiffError::FormatError(
- TiffFormatError::RequiredTagNotFound(tag),
- )),
- }
- }
- pub fn find_tag_uint_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()
- })
- .transpose()
- }
-}