//! Function for reading TIFF tags use std::io::{self, Read, Seek}; use std::collections::{HashMap}; use super::stream::{ByteOrder, SmartReader, EndianReader}; use ::{TiffError, TiffResult}; use self::Value::{Unsigned, List}; macro_rules! tags { {$( $tag:ident $val:expr; )*} => { /// TIFF tag #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub enum Tag { $($tag,)* Unknown(u16) } impl Tag { pub fn from_u16(n: u16) -> Tag { $(if n == $val { Tag::$tag } else)* { Tag::Unknown(n) } } } } } // Note: These tags appear in the order they are mentioned in the TIFF reference tags!{ // Baseline tags: Artist 315; // TODO add support // grayscale images PhotometricInterpretation 1 or 3 BitsPerSample 258; CellLength 265; // TODO add support CellWidth 264; // TODO add support // palette-color images (PhotometricInterpretation 3) ColorMap 320; // TODO add support Compression 259; // TODO add support for 2 and 32773 Copyright 33_432; // TODO add support DateTime 306; // TODO add support ExtraSamples 338; // TODO add support FillOrder 266; // TODO add support FreeByteCounts 289; // TODO add support FreeOffsets 288; // TODO add support GrayResponseCurve 291; // TODO add support GrayResponseUnit 290; // TODO add support HostComputer 316; // TODO add support ImageDescription 270; // TODO add support ImageLength 257; ImageWidth 256; Make 271; // TODO add support MaxSampleValue 281; // TODO add support MinSampleValue 280; // TODO add support Model 272; // TODO add support NewSubfileType 254; // TODO add support Orientation 274; // TODO add support PhotometricInterpretation 262; PlanarConfiguration 284; ResolutionUnit 296; // TODO add support RowsPerStrip 278; SamplesPerPixel 277; Software 305; StripByteCounts 279; StripOffsets 273; SubfileType 255; // TODO add support Threshholding 263; // TODO add support XResolution 282; YResolution 283; // Advanced tags Predictor 317; } #[derive(Clone, Copy, Debug, FromPrimitive)] pub enum Type { BYTE = 1, ASCII = 2, SHORT = 3, LONG = 4, RATIONAL = 5, } #[allow(unused_qualifications)] #[derive(Debug)] pub enum Value { //Signed(i32), Unsigned(u32), List(Vec) } impl Value { pub fn into_u32(self) -> TiffResult { match self { Unsigned(val) => Ok(val), val => Err(TiffError::FormatError(format!( "Expected unsigned integer, {:?} found.", val ))) } } pub fn into_u32_vec(self) -> TiffResult> { 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]), //_ => Err(::image::FormatError("Tag data malformed.".to_string())) } } } pub struct Entry { type_: Type, count: u32, offset: [u8; 4], } 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 { Entry { type_, count, offset } } /// Returns a mem_reader for the offset/value field fn r(&self, byte_order: ByteOrder) -> SmartReader>> { SmartReader::wrap( io::Cursor::new(self.offset.to_vec()), byte_order ) } pub fn val(&self, decoder: &mut super::Decoder) -> TiffResult { let bo = decoder.byte_order(); match (self.type_, self.count) { // TODO check if this could give wrong results // at a different endianess of file/computer. (Type::BYTE, 1) => Ok(Unsigned(u32::from(self.offset[0]))), (Type::SHORT, 1) => Ok(Unsigned(u32::from(self.r(bo).read_u16()?))), (Type::SHORT, 2) => { let mut r = self.r(bo); Ok(List(vec![ Unsigned(u32::from(r.read_u16()?)), Unsigned(u32::from(r.read_u16()?)) ])) }, (Type::SHORT, n) => { let mut v = Vec::with_capacity(n as usize); try!(decoder.goto_offset(try!(self.r(bo).read_u32()))); for _ in 0 .. n { v.push(Unsigned(u32::from(decoder.read_short()?))) } Ok(List(v)) }, (Type::LONG, 1) => Ok(Unsigned(try!(self.r(bo).read_u32()))), (Type::LONG, n) => { let mut v = Vec::with_capacity(n as usize); try!(decoder.goto_offset(try!(self.r(bo).read_u32()))); for _ in 0 .. n { v.push(Unsigned(try!(decoder.read_long()))) } Ok(List(v)) } _ => Err(TiffError::UnsupportedError("Unsupported data type.".to_string())) } } } /// Type representing an Image File Directory pub type Directory = HashMap;