Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: add encoding with compression, additional tags, float support and bigtiff #80

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ exclude = ["tests/images/*", "tests/fuzz_images/*"]

[dependencies]
byteorder = "1.2"
lzw = "0.10"
lzw = { git = "https://github.com/Rogach/lzw" }
miniz_oxide = "0.3"
94 changes: 76 additions & 18 deletions src/decoder/ifd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ use super::stream::{ByteOrder, EndianReader, SmartReader};
use tags::{Tag, Type};
use {TiffError, TiffFormatError, TiffResult, TiffUnsupportedError};

use self::Value::{Ascii, List, Rational, Unsigned, Signed, SRational};

use self::Value::{Ascii, List, Rational, SRational, Signed, Unsigned, Float, Double};

#[allow(unused_qualifications)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Signed(i32),
Unsigned(u32),
Float(f32),
Double(f64),
List(Vec<Value>),
Rational(u32, u32),
SRational(i32, i32),
Expand Down Expand Up @@ -44,6 +45,24 @@ impl Value {
}
}

pub fn into_f32(self) -> TiffResult<f32> {
match self {
Float(val) => Ok(val),
val => Err(TiffError::FormatError(
TiffFormatError::FloatExpected(val),
)),
}
}

pub fn into_f64(self) -> TiffResult<f64> {
match self {
Double(val) => Ok(val),
val => Err(TiffError::FormatError(
TiffFormatError::DoubleExpected(val),
)),
}
}

pub fn into_u32_vec(self) -> TiffResult<Vec<u32>> {
match self {
List(vec) => {
Expand Down Expand Up @@ -72,7 +91,7 @@ impl Value {
new_vec.push(numerator);
new_vec.push(denominator);
}
_ => new_vec.push(v.into_i32()?)
_ => new_vec.push(v.into_i32()?),
}
}
Ok(new_vec)
Expand All @@ -84,6 +103,38 @@ impl Value {
)),
}
}

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),
)),
}
}
}

#[derive(Clone)]
Expand Down Expand Up @@ -169,6 +220,12 @@ impl Entry {
(Type::SLONG, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
Ok(Signed(decoder.read_slong()?))
}),
(Type::FLOAT, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
Ok(Float(decoder.read_float()?))
}),
(Type::DOUBLE, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
Ok(Double(decoder.read_double()?))
}),
(Type::RATIONAL, 1) => {
decoder.goto_offset(self.r(bo).read_u32()?)?;
let numerator = decoder.read_long()?;
Expand All @@ -182,16 +239,10 @@ impl Entry {
Ok(SRational(numerator, denominator))
}
(Type::RATIONAL, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
Ok(Rational(
decoder.read_long()?,
decoder.read_long()?,
))
Ok(Rational(decoder.read_long()?, decoder.read_long()?))
}),
(Type::SRATIONAL, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
Ok(SRational(
decoder.read_slong()?,
decoder.read_slong()?,
))
Ok(SRational(decoder.read_slong()?, decoder.read_slong()?))
}),
(Type::ASCII, n) => {
let n = usize::try_from(n)?;
Expand All @@ -209,10 +260,17 @@ impl Entry {
}

#[inline]
fn decode_offset<R, F>(&self, value_count: u32, bo: ByteOrder, limits: &super::Limits, decoder: &mut super::Decoder<R>, decode_fn: F) -> TiffResult<Value>
where
R: Read + Seek,
F: Fn(&mut super::Decoder<R>) -> TiffResult<Value>,
fn decode_offset<R, F>(
&self,
value_count: u32,
bo: ByteOrder,
limits: &super::Limits,
decoder: &mut super::Decoder<R>,
decode_fn: F,
) -> TiffResult<Value>
where
R: Read + Seek,
F: Fn(&mut super::Decoder<R>) -> TiffResult<Value>,
{
let value_count = usize::try_from(value_count)?;
if value_count > limits.decoding_buffer_size / mem::size_of::<Value>() {
Expand All @@ -235,7 +293,7 @@ fn offset_to_bytes(n: usize, entry: &Entry) -> TiffResult<Value> {
entry.offset[0..n]
.iter()
.map(|&e| Unsigned(u32::from(e)))
.collect()
.collect(),
))
}

Expand All @@ -246,7 +304,7 @@ fn offset_to_sbytes(n: usize, entry: &Entry) -> TiffResult<Value> {
entry.offset[0..n]
.iter()
.map(|&e| Signed(i32::from(e as i8)))
.collect()
.collect(),
))
}

Expand Down
14 changes: 13 additions & 1 deletion src/decoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,18 @@ impl<R: Read + Seek> Decoder<R> {
self.reader.read_i32()
}

/// Reads a TIFF float valu
#[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()
}

/// Reads a string
#[inline]
pub fn read_string(&mut self, length: usize) -> TiffResult<String> {
Expand Down Expand Up @@ -572,7 +584,7 @@ impl<R: Read + Seek> Decoder<R> {
) -> TiffResult<usize> {
let color_type = self.colortype()?;
self.goto_offset(offset)?;
let (bytes, mut reader): (usize, Box<EndianReader>) = match self.compression_method {
let (bytes, mut reader): (usize, Box<dyn EndianReader>) = match self.compression_method {
CompressionMethod::None => {
let order = self.reader.byte_order;
(
Expand Down
18 changes: 18 additions & 0 deletions src/decoder/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,24 @@ pub trait EndianReader: Read {
ByteOrder::BigEndian => <Self as ReadBytesExt>::read_i32::<BigEndian>(self),
}
}

/// Reads an f32
#[inline(always)]
fn read_f32(&mut self) -> Result<f32, io::Error> {
match self.byte_order() {
ByteOrder::LittleEndian => <Self as ReadBytesExt>::read_f32::<LittleEndian>(self),
ByteOrder::BigEndian => <Self as ReadBytesExt>::read_f32::<BigEndian>(self),
}
}

/// Reads an f64
#[inline(always)]
fn read_f64(&mut self) -> Result<f64, io::Error> {
match self.byte_order() {
ByteOrder::LittleEndian => <Self as ReadBytesExt>::read_f64::<LittleEndian>(self),
ByteOrder::BigEndian => <Self as ReadBytesExt>::read_f64::<BigEndian>(self),
}
}
}

/// Reader that decompresses DEFLATE streams
Expand Down
Loading