Add TIFF compression and corresponding tests
This commit is contained in:
1 parent
d7d63e648b
commit
99b2aa9b3a
10 files changed
+676
-135
No files matched your search
+153
-107
@@ -1,4 +1,4 @@
|
||||
use std::io::Write;
|
||||
use std::{borrow::Cow, io::Write};
|
||||
|
||||
use crate::{bytecast, tags::Type, TiffError, TiffFormatError, TiffResult};
|
||||
|
||||
@@ -12,7 +12,18 @@ pub trait TiffValue {
|
||||
fn bytes(&self) -> usize {
|
||||
self.count() * usize::from(Self::BYTE_LEN)
|
||||
}
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()>;
|
||||
|
||||
/// Access this value as an contiguous sequence of bytes.
|
||||
/// If their is no trivial representation, allocate it on the heap.
|
||||
fn data(&self) -> Cow<[u8]>;
|
||||
|
||||
/// Write this value to a TiffWriter.
|
||||
/// While the default implementation will work in all cases, it may require unnecessary allocations.
|
||||
/// The written bytes of any custom implementation MUST be the same as yielded by `self.data()`.
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
writer.write_bytes(&self.data())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for [u8] {
|
||||
@@ -23,9 +34,8 @@ impl TiffValue for [u8] {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
writer.write_bytes(self)?;
|
||||
Ok(())
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Borrowed(self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,10 +47,8 @@ impl TiffValue for [i8] {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
let slice = bytecast::i8_as_ne_bytes(self);
|
||||
writer.write_bytes(slice)?;
|
||||
Ok(())
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Borrowed(bytecast::i8_as_ne_bytes(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,10 +60,8 @@ impl TiffValue for [u16] {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
let slice = bytecast::u16_as_ne_bytes(self);
|
||||
writer.write_bytes(slice)?;
|
||||
Ok(())
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Borrowed(bytecast::u16_as_ne_bytes(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,10 +73,8 @@ impl TiffValue for [i16] {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
let slice = bytecast::i16_as_ne_bytes(self);
|
||||
writer.write_bytes(slice)?;
|
||||
Ok(())
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Borrowed(bytecast::i16_as_ne_bytes(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,10 +86,8 @@ impl TiffValue for [u32] {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
let slice = bytecast::u32_as_ne_bytes(self);
|
||||
writer.write_bytes(slice)?;
|
||||
Ok(())
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Borrowed(bytecast::u32_as_ne_bytes(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,10 +99,8 @@ impl TiffValue for [i32] {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
let slice = bytecast::i32_as_ne_bytes(self);
|
||||
writer.write_bytes(slice)?;
|
||||
Ok(())
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Borrowed(bytecast::i32_as_ne_bytes(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,10 +112,8 @@ impl TiffValue for [u64] {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
let slice = bytecast::u64_as_ne_bytes(self);
|
||||
writer.write_bytes(slice)?;
|
||||
Ok(())
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Borrowed(bytecast::u64_as_ne_bytes(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,10 +125,8 @@ impl TiffValue for [i64] {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
let slice = bytecast::i64_as_ne_bytes(self);
|
||||
writer.write_bytes(slice)?;
|
||||
Ok(())
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Borrowed(bytecast::i64_as_ne_bytes(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,11 +138,9 @@ impl TiffValue for [f32] {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
// We write using nativeedian so this sould be safe
|
||||
let slice = bytecast::f32_as_ne_bytes(self);
|
||||
writer.write_bytes(slice)?;
|
||||
Ok(())
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
// We write using native endian so this should be safe
|
||||
Cow::Borrowed(bytecast::f32_as_ne_bytes(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,75 +152,9 @@ impl TiffValue for [f64] {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
// We write using nativeedian so this sould be safe
|
||||
let slice = bytecast::f64_as_ne_bytes(self);
|
||||
writer.write_bytes(slice)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for [Ifd] {
|
||||
const BYTE_LEN: u8 = 4;
|
||||
const FIELD_TYPE: Type = Type::IFD;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
for x in self {
|
||||
x.write(writer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for [Ifd8] {
|
||||
const BYTE_LEN: u8 = 8;
|
||||
const FIELD_TYPE: Type = Type::IFD8;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
for x in self {
|
||||
x.write(writer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for [Rational] {
|
||||
const BYTE_LEN: u8 = 8;
|
||||
const FIELD_TYPE: Type = Type::RATIONAL;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
for x in self {
|
||||
x.write(writer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for [SRational] {
|
||||
const BYTE_LEN: u8 = 8;
|
||||
const FIELD_TYPE: Type = Type::SRATIONAL;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
for x in self {
|
||||
x.write(writer)?;
|
||||
}
|
||||
Ok(())
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
// We write using native endian so this should be safe
|
||||
Cow::Borrowed(bytecast::f64_as_ne_bytes(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,6 +170,10 @@ impl TiffValue for u8 {
|
||||
writer.write_u8(*self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned(vec![*self])
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for i8 {
|
||||
@@ -256,6 +188,10 @@ impl TiffValue for i8 {
|
||||
writer.write_i8(*self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned(self.to_ne_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for u16 {
|
||||
@@ -270,6 +206,10 @@ impl TiffValue for u16 {
|
||||
writer.write_u16(*self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned(self.to_ne_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for i16 {
|
||||
@@ -284,6 +224,10 @@ impl TiffValue for i16 {
|
||||
writer.write_i16(*self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned(self.to_ne_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for u32 {
|
||||
@@ -298,6 +242,10 @@ impl TiffValue for u32 {
|
||||
writer.write_u32(*self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned(self.to_ne_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for i32 {
|
||||
@@ -312,6 +260,10 @@ impl TiffValue for i32 {
|
||||
writer.write_i32(*self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned(self.to_ne_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for u64 {
|
||||
@@ -326,6 +278,10 @@ impl TiffValue for u64 {
|
||||
writer.write_u64(*self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned(self.to_ne_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for i64 {
|
||||
@@ -340,6 +296,10 @@ impl TiffValue for i64 {
|
||||
writer.write_i64(*self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned(self.to_ne_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for f32 {
|
||||
@@ -354,6 +314,10 @@ impl TiffValue for f32 {
|
||||
writer.write_f32(*self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned(self.to_ne_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for f64 {
|
||||
@@ -368,6 +332,10 @@ impl TiffValue for f64 {
|
||||
writer.write_f64(*self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned(self.to_ne_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for Ifd {
|
||||
@@ -382,6 +350,13 @@ impl TiffValue for Ifd {
|
||||
writer.write_u32(self.0)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned({
|
||||
let dword: [u8; 4] = self.0.to_ne_bytes();
|
||||
dword.to_vec()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for Ifd8 {
|
||||
@@ -396,6 +371,13 @@ impl TiffValue for Ifd8 {
|
||||
writer.write_u64(self.0)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned({
|
||||
let qword: [u8; 8] = self.0.to_ne_bytes();
|
||||
qword.to_vec()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for Rational {
|
||||
@@ -411,6 +393,14 @@ impl TiffValue for Rational {
|
||||
writer.write_u32(self.d)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned({
|
||||
let first_dword: [u8; 4] = self.n.to_ne_bytes();
|
||||
let second_dword: [u8; 4] = self.d.to_ne_bytes();
|
||||
[first_dword, second_dword].concat()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for SRational {
|
||||
@@ -426,6 +416,14 @@ impl TiffValue for SRational {
|
||||
writer.write_i32(self.d)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned({
|
||||
let first_dword: [u8; 4] = self.n.to_ne_bytes();
|
||||
let second_dword: [u8; 4] = self.d.to_ne_bytes();
|
||||
[first_dword, second_dword].concat()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TiffValue for str {
|
||||
@@ -445,6 +443,17 @@ impl TiffValue for str {
|
||||
Err(TiffError::FormatError(TiffFormatError::InvalidTag))
|
||||
}
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
Cow::Owned({
|
||||
if self.is_ascii() && !self.bytes().any(|b| b == 0) {
|
||||
let bytes: &[u8] = self.as_bytes();
|
||||
[bytes, &[0]].concat()
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: TiffValue + ?Sized> TiffValue for &'a T {
|
||||
@@ -458,8 +467,45 @@ impl<'a, T: TiffValue + ?Sized> TiffValue for &'a T {
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
(*self).write(writer)
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
T::data(self)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_tiff_value_for_contiguous_sequence {
|
||||
($inner_type:ty; $bytes:expr; $field_type:expr) => {
|
||||
impl $crate::encoder::TiffValue for [$inner_type] {
|
||||
const BYTE_LEN: u8 = $bytes;
|
||||
const FIELD_TYPE: Type = $field_type;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
|
||||
for x in self {
|
||||
x.write(writer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data(&self) -> Cow<[u8]> {
|
||||
let mut buf: Vec<u8> = Vec::with_capacity(Self::BYTE_LEN as usize * self.len());
|
||||
for x in self {
|
||||
buf.extend_from_slice(&x.data());
|
||||
}
|
||||
Cow::Owned(buf)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_tiff_value_for_contiguous_sequence!(Ifd; 4; Type::IFD);
|
||||
impl_tiff_value_for_contiguous_sequence!(Ifd8; 8; Type::IFD8);
|
||||
impl_tiff_value_for_contiguous_sequence!(Rational; 8; Type::RATIONAL);
|
||||
impl_tiff_value_for_contiguous_sequence!(SRational; 8; Type::SRATIONAL);
|
||||
|
||||
/// Type to represent tiff values of type `IFD`
|
||||
#[derive(Clone)]
|
||||
pub struct Ifd(pub u32);
|
||||
|
||||
Reference in new issue
Block a user