rustiff 0.1.2

TIFF decoding/encoding library in Rust.
Documentation

use std::fmt::{
    self,
    Display,
};
use std::io::{
    Read,
    Seek,
};
use error::{
    DecodeResult,
    DecodeError,
    DecodeErrorKind,
};
use ifd::DataType;
use byte::{
    Endian,
    EndianReadExt,
    SeekExt,
};

pub trait TagType: Clone + Copy {
    type Value;

    fn id(&self) -> u16;
    fn default_value() -> Option<Self::Value>;
    fn decode<'a, R: Read + Seek + 'a>(&'a self, reader: R, offset: &'a [u8], endian: Endian, datatype: DataType, count: usize) -> DecodeResult<Self::Value>;
}

macro_rules! define_tags {
    ($($name:ident, $id:expr;)*) => {
        $(#[derive(Debug, Clone, Copy, PartialEq, Eq, Fail)]
        pub struct $name;

        impl Display for $name {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "{}", $name)
            }
        })*
        
        #[derive(Debug, Fail)]
        pub enum AnyTag {
            $($name,)*
            Unknown(u16),
        }

        impl AnyTag {
            pub fn id(&self) -> u16 {
                match *self {
                    $(AnyTag::$name => $id,)*
                    AnyTag::Unknown(n) => n,
                }
            }
        }

        impl Display for AnyTag {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                match *self {
                    $(AnyTag::$name => $name.fmt(f),)*
                    AnyTag::Unknown(n) => write!(f, "Unknown tag: {}", n),
                }
            }
        }

        impl<T> From<T> for AnyTag where T: TagType {
            fn from(x: T) -> AnyTag {
                match x.id() {
                    $($id => AnyTag::$name,)*
                    _ => AnyTag::Unknown(x.id()),
                }
            }
        }

        impl From<u16> for AnyTag {
            fn from(n: u16) -> AnyTag {
                match n {
                    $($id => AnyTag::$name,)*
                    _ => AnyTag::Unknown(n),
                }
            }
        }
    }
}

macro_rules! tag_short_or_long_value {
    ($($name:ident, $id:expr, $def:expr;)*) => {
        $(impl TagType for $name {
            type Value = u32;

            fn id(&self) -> u16 { $id }
            fn default_value() -> Option<u32> { $def }
            fn decode<'a, R: Read + Seek + 'a>(&'a self, mut _reader: R, mut offset: &'a [u8], endian: Endian, datatype: DataType, count: usize) -> DecodeResult<Self::Value> {
                match datatype {
                    DataType::Short if count == 1 => Ok(offset.read_u16(endian)? as u32),
                    DataType::Long if count == 1 => Ok(offset.read_u32(endian)?),
                    _ => Err(DecodeError::from(DecodeErrorKind::NoSupportDataType { tag: AnyTag::from(*self), datatype: datatype, count: count })),
                }
            }
        })*
    };
}

macro_rules! tag_short_value {
    ($($name:ident, $id:expr, $def:expr;)*) => {
        $(impl TagType for $name {
            type Value = u16;

            fn id(&self) -> u16 { $id }
            fn default_value() -> Option<u16> { $def }
            fn decode<'a, R: Read + Seek + 'a>(&'a self, mut _reader: R, mut offset: &'a [u8], endian: Endian, datatype: DataType, count: usize) -> DecodeResult<Self::Value> {
                match datatype {
                    DataType::Short if count == 1 => Ok(offset.read_u16(endian)?),
                    _ => Err(DecodeError::from(DecodeErrorKind::NoSupportDataType { tag: AnyTag::from(*self), datatype: datatype, count: count })),
                }
            }
        })*
    };
}

macro_rules! tag_short_or_long_values {
    ($($name:ident, $id:expr, $def:expr;)*) => {
        $(impl TagType for $name {
            type Value = Vec<u32>;

            fn id(&self) -> u16 { $id }
            fn default_value() -> Option<Vec<u32>> { $def }
            fn decode<'a, R: Read + Seek + 'a>(&'a self, mut reader: R, mut offset: &'a [u8], endian: Endian, datatype: DataType, count: usize) -> DecodeResult<Self::Value> {
                match datatype {
                    DataType::Short if count == 1 => Ok(vec![offset.read_u16(endian)? as u32]),
                    DataType::Short if count == 2 => Ok(vec![
                        offset.read_u16(endian)? as u32,
                        offset.read_u16(endian)? as u32,
                    ]),
                    DataType::Short if count > 2 => {
                        let offset = offset.read_u32(endian)? as u64;
                        reader.goto(offset)?;
                        let mut v = Vec::with_capacity(count);
                        for _ in 0..count {
                            v.push(reader.read_u16(endian)? as u32);
                        }

                        Ok(v)
                    }
                    DataType::Long if count == 1 => Ok(vec![offset.read_u32(endian)?]),
                    DataType::Long if count > 1 => {
                        let offset = offset.read_u32(endian)? as u64;
                        reader.goto(offset)?;
                        let mut v = Vec::with_capacity(count);
                        for _ in 0..count {
                            v.push(reader.read_u32(endian)?);
                        }

                        Ok(v)
                    }
                    _ => Err(DecodeError::from(DecodeErrorKind::NoSupportDataType { tag: AnyTag::from(*self), datatype: datatype, count: count })),
                }
            }
        })*
    };
}

macro_rules! tag_short_values {
    ($($name:ident, $id:expr, $def:expr;)*) => {
        $(impl TagType for $name {
            type Value = Vec<u16>;

            fn id(&self) -> u16 { $id }
            fn default_value() -> Option<Vec<u16>> { $def }
            fn decode<'a, R: Read + Seek + 'a>(&'a self, mut reader: R, mut offset: &'a [u8], endian: Endian, datatype: DataType, count: usize) -> DecodeResult<Self::Value> {
                match datatype {
                    DataType::Short if count == 1 => Ok(vec![offset.read_u16(endian)?]),
                    DataType::Short if count == 2 => Ok(vec![
                        offset.read_u16(endian)?,
                        offset.read_u16(endian)?,
                    ]),
                    DataType::Short if count > 2 => {
                        let offset = offset.read_u32(endian)? as u64;
                        reader.goto(offset)?;
                        let mut v = Vec::with_capacity(count);
                        for _ in 0..count {
                            v.push(reader.read_u16(endian)?);
                        }

                        Ok(v)
                    }
                    _ => Err(DecodeError::from(DecodeErrorKind::NoSupportDataType { tag: AnyTag::from(*self), datatype: datatype, count: count })),
                }
            }
        })*
    };
}

define_tags! {
    ImageWidth, 256;
    ImageLength, 257;
    BitsPerSample, 258;
    Compression, 259;
    PhotometricInterpretation, 262;
    StripOffsets, 273;
    SamplesPerPixel, 277;
    RowsPerStrip, 278;
    StripByteCounts, 279;
}

tag_short_or_long_value! {
    ImageWidth, 256, None;
    ImageLength, 257, None;
    RowsPerStrip, 278, Some(u32::max_value());
}

tag_short_or_long_values! {
    StripOffsets, 273, None;
    StripByteCounts, 279, None;
}

tag_short_value! {
    PhotometricInterpretation, 262, None;
    Compression, 259, Some(1);
    SamplesPerPixel, 277, Some(1);
}

tag_short_values! {
    BitsPerSample, 258, Some(vec![1]);
}