From f92be13f6cd8554b97c6179fd555722dd9ed609d Mon Sep 17 00:00:00 2001 From: Andrew Champion Date: Fri, 13 Dec 2019 16:37:38 +0000 Subject: [PATCH] Factor tags into own module Tag representations are not decoder- or encoder-specific, so should live in their own module accessible to both for reuse. The decoder::ifd module remains since this module is mainly dedicated to decoding the IFD. --- src/decoder/ifd.rs | 139 +---------------------------- src/decoder/mod.rs | 91 ++++++------------- src/encoder/colortype.rs | 2 +- src/encoder/mod.rs | 51 +++++------ src/error.rs | 4 +- src/lib.rs | 1 + src/tags.rs | 188 +++++++++++++++++++++++++++++++++++++++ tests/decode_images.rs | 2 +- tests/encode_images.rs | 2 +- 9 files changed, 242 insertions(+), 238 deletions(-) create mode 100644 src/tags.rs diff --git a/src/decoder/ifd.rs b/src/decoder/ifd.rs index f6f0f0d..73b6e97 100644 --- a/src/decoder/ifd.rs +++ b/src/decoder/ifd.rs @@ -5,148 +5,11 @@ use std::io::{self, Read, Seek}; use std::mem; use super::stream::{ByteOrder, EndianReader, SmartReader}; +use tags::{Tag, Type}; use {TiffError, TiffFormatError, TiffResult, TiffUnsupportedError}; use self::Value::{Ascii, List, Rational, Unsigned, Signed, SRational}; -pub(crate) mod seals { - pub trait TagConversion: Sized { - fn __from_inner_type(T) -> Result; - - fn __to_inner_type(&self) -> T; - } -} - -pub trait U16Tag: Sized { - fn from_u16(val: u16) -> Option; - - fn to_u16(&self) -> u16; -} - -impl> U16Tag for T { - fn from_u16(val: u16) -> Option { - Self::__from_inner_type(val).ok() - } - - fn to_u16(&self) -> u16 { - Self::__to_inner_type(self) - } -} - -macro_rules! tags { - { - // Permit arbitrary meta items, which include documentation. - $( #[$enum_attr:meta] )* - $vis:vis enum $name:ident($ty:ty) $(unknown($unknown_doc:literal))* { - // Each of the `Name = Val,` permitting documentation. - $($(#[$ident_attr:meta])* $tag:ident = $val:expr,)* - } - } => { - $( #[$enum_attr] )* - #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] - pub enum $name { - $($(#[$ident_attr])* $tag,)* - // FIXME: switch to non_exhaustive once stabilized and compiler requirement new enough - #[doc(hidden)] - __NonExhaustive, - $( - #[doc = $unknown_doc] - Unknown($ty), - )* - } - - impl ::decoder::ifd::seals::TagConversion<$ty> for $name { - #[inline(always)] - fn __from_inner_type(n: $ty) -> Result { - match n { - $( $val => Ok($name::$tag), )* - n => Err(n), - } - } - - #[inline(always)] - fn __to_inner_type(&self) -> $ty { - match *self { - $( $name::$tag => $val, )* - $( $name::Unknown(n) => { $unknown_doc; n }, )* - $name::__NonExhaustive => unreachable!(), - } - } - } - } -} - -// Note: These tags appear in the order they are mentioned in the TIFF reference -tags! { -/// TIFF tags -pub enum Tag(u16) unknown("A private or extension tag") { - // Baseline tags: - Artist = 315, - // 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, - DateTime = 306, - 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, - ImageDescription = 270, - ImageLength = 257, - ImageWidth = 256, - Make = 271, - MaxSampleValue = 281, // TODO add support - MinSampleValue = 280, // TODO add support - Model = 272, - 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, -} -} - -impl Tag { - pub fn from_u16_exhaustive(val: u16) -> Self { - Self::from_u16(val).unwrap_or_else(|| Tag::Unknown(val)) - } -} - -tags! { -/// The type of an IFD entry (a 2 byte field). -pub enum Type(u16) { - BYTE = 1, - ASCII = 2, - SHORT = 3, - LONG = 4, - RATIONAL = 5, - SBYTE = 6, - SSHORT = 8, - SLONG = 9, - SRATIONAL = 10, - /// BigTIFF 64-bit unsigned integer - LONG8 = 16, -} -} - #[allow(unused_qualifications)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index f4e757d..e7fdfb2 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -5,11 +5,11 @@ use std::cmp; use {ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError}; -use self::ifd::{Directory, U16Tag}; +use self::ifd::Directory; +use tags::{CompressionMethod, PhotometricInterpretation, Predictor, Tag, Type, U16Tag}; use self::stream::{ByteOrder, EndianReader, LZWReader, DeflateReader, PackBitsReader, SmartReader}; -#[macro_use] pub mod ifd; mod stream; @@ -113,47 +113,6 @@ impl<'a> DecodingBuffer<'a> { } } -tags! { -pub enum PhotometricInterpretation(u16) { - WhiteIsZero = 0, - BlackIsZero = 1, - RGB = 2, - RGBPalette = 3, - TransparencyMask = 4, - CMYK = 5, - YCbCr = 6, - CIELab = 8, -} -} - -tags! { -pub enum CompressionMethod(u16) { - None = 1, - Huffman = 2, - Fax3 = 3, - Fax4 = 4, - LZW = 5, - JPEG = 6, - Deflate = 8, - OldDeflate = 0x80B2, - PackBits = 0x8005, -} -} - -tags! { -pub enum PlanarConfiguration(u16) { - Chunky = 1, - Planar = 2, -} -} - -tags! { -enum Predictor(u16) { - None = 1, - Horizontal = 2, -} -} - #[derive(Debug)] struct StripDecodeState { strip_index: usize, @@ -385,24 +344,24 @@ impl Decoder { /// To determine whether there are more images call `TIFFDecoder::more_images` instead. pub fn next_image(&mut self) -> TiffResult<()> { self.ifd = Some(self.read_ifd()?); - self.width = self.get_tag_u32(ifd::Tag::ImageWidth)?; - self.height = self.get_tag_u32(ifd::Tag::ImageLength)?; + self.width = self.get_tag_u32(Tag::ImageWidth)?; + self.height = self.get_tag_u32(Tag::ImageLength)?; self.strip_decoder = None; self.photometric_interpretation = self - .find_tag_unsigned(ifd::Tag::PhotometricInterpretation)? + .find_tag_unsigned(Tag::PhotometricInterpretation)? .and_then(PhotometricInterpretation::from_u16) .ok_or(TiffUnsupportedError::UnknownInterpretation)?; - if let Some(val) = self.find_tag_unsigned(ifd::Tag::Compression)? { + if let Some(val) = self.find_tag_unsigned(Tag::Compression)? { self.compression_method = CompressionMethod::from_u16(val) .ok_or(TiffUnsupportedError::UnknownCompressionMethod)?; } - if let Some(val) = self.find_tag_unsigned(ifd::Tag::SamplesPerPixel)? { + if let Some(val) = self.find_tag_unsigned(Tag::SamplesPerPixel)? { self.samples = val; } match self.samples { - 1 | 3 | 4 => if let Some(val) = self.find_tag_unsigned_vec(ifd::Tag::BitsPerSample)? { + 1 | 3 | 4 => if let Some(val) = self.find_tag_unsigned_vec(Tag::BitsPerSample)? { self.bits_per_sample = val; }, _ => return Err(TiffUnsupportedError::UnsupportedSampleDepth(self.samples).into()), @@ -485,9 +444,9 @@ impl Decoder { // Type 2 bytes // Count 4 bytes // Value 4 bytes either a pointer the value itself - fn read_entry(&mut self) -> TiffResult> { - let tag = ifd::Tag::from_u16_exhaustive(self.read_short()?); - let type_ = match ifd::Type::from_u16(self.read_short()?) { + fn read_entry(&mut self) -> TiffResult> { + let tag = Tag::from_u16_exhaustive(self.read_short()?); + let type_ = match Type::from_u16(self.read_short()?) { Some(t) => t, None => { // Unknown type. Skip this entry according to spec. @@ -533,7 +492,7 @@ impl Decoder { /// Tries to retrieve a tag. /// Return `Ok(None)` if the tag is not present. - pub fn find_tag(&mut self, tag: ifd::Tag) -> TiffResult> { + pub fn find_tag(&mut self, tag: Tag) -> TiffResult> { let entry = match self.ifd.as_ref().unwrap().get(&tag) { None => return Ok(None), Some(entry) => entry.clone(), @@ -545,7 +504,7 @@ impl Decoder { } /// Tries to retrieve a tag and convert it to the desired unsigned type. - pub fn find_tag_unsigned>(&mut self, tag: ifd::Tag) -> TiffResult> { + pub fn find_tag_unsigned>(&mut self, tag: Tag) -> TiffResult> { self.find_tag(tag)? .map(|v| v.into_u32()).transpose()? .map(|value| T::try_from(value) @@ -555,7 +514,7 @@ impl Decoder { /// 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>(&mut self, tag: ifd::Tag) -> TiffResult>> { + pub fn find_tag_unsigned_vec>(&mut self, tag: Tag) -> TiffResult>> { self.find_tag(tag)? .map(|v| v.into_u32_vec()).transpose()? .map(|v| v.into_iter() @@ -566,14 +525,14 @@ impl Decoder { /// 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>(&mut self, tag: ifd::Tag) -> TiffResult { + pub fn get_tag_unsigned>(&mut self, tag: Tag) -> TiffResult { 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: ifd::Tag) -> TiffResult { + pub fn get_tag(&mut self, tag: Tag) -> TiffResult { match self.find_tag(tag)? { Some(val) => Ok(val), None => Err(TiffError::FormatError( @@ -583,12 +542,12 @@ impl Decoder { } /// Tries to retrieve a tag and convert it to the desired type. - pub fn get_tag_u32(&mut self, tag: ifd::Tag) -> TiffResult { + pub fn get_tag_u32(&mut self, tag: Tag) -> TiffResult { self.get_tag(tag)?.into_u32() } /// Tries to retrieve a tag and convert it to the desired type. - pub fn get_tag_u32_vec(&mut self, tag: ifd::Tag) -> TiffResult> { + pub fn get_tag_u32_vec(&mut self, tag: Tag) -> TiffResult> { self.get_tag(tag)?.into_u32_vec() } @@ -714,7 +673,7 @@ impl Decoder { /// Number of strips in image pub fn strip_count(&mut self) -> TiffResult { let rows_per_strip = self - .get_tag_u32(ifd::Tag::RowsPerStrip) + .get_tag_u32(Tag::RowsPerStrip) .unwrap_or(self.height); if rows_per_strip == 0 { @@ -726,8 +685,8 @@ impl Decoder { fn initialize_strip_decoder(&mut self) -> TiffResult<()> { if self.strip_decoder.is_none() { - let strip_offsets = self.get_tag_u32_vec(ifd::Tag::StripOffsets)?; - let strip_bytes = self.get_tag_u32_vec(ifd::Tag::StripByteCounts)?; + let strip_offsets = self.get_tag_u32_vec(Tag::StripOffsets)?; + let strip_bytes = self.get_tag_u32_vec(Tag::StripByteCounts)?; self.strip_decoder = Some(StripDecodeState { strip_index: 0, @@ -762,7 +721,7 @@ impl Decoder { ))?; let rows_per_strip = self - .get_tag_u32(ifd::Tag::RowsPerStrip) + .get_tag_u32(Tag::RowsPerStrip) .unwrap_or(self.height) as usize; let strip_height = cmp::min( @@ -791,7 +750,7 @@ impl Decoder { TiffFormatError::InconsistentSizesEncountered, )); } - if let Ok(predictor) = self.get_tag_unsigned(ifd::Tag::Predictor) { + if let Ok(predictor) = self.get_tag_unsigned(Tag::Predictor) { match Predictor::from_u16(predictor) { Some(Predictor::None) => (), Some(Predictor::Horizontal) => { @@ -834,7 +793,7 @@ impl Decoder { let index = self.strip_decoder.as_ref().unwrap().strip_index; let rows_per_strip = self - .get_tag_u32(ifd::Tag::RowsPerStrip) + .get_tag_u32(Tag::RowsPerStrip) .unwrap_or(self.height) as usize; let strip_height = cmp::min( @@ -853,7 +812,7 @@ impl Decoder { pub fn read_image(&mut self) -> TiffResult { self.initialize_strip_decoder()?; let rows_per_strip = self - .get_tag_u32(ifd::Tag::RowsPerStrip) + .get_tag_u32(Tag::RowsPerStrip) .unwrap_or(self.height) as usize; let samples_per_strip = diff --git a/src/encoder/colortype.rs b/src/encoder/colortype.rs index 2f49fdb..4055fdf 100644 --- a/src/encoder/colortype.rs +++ b/src/encoder/colortype.rs @@ -1,4 +1,4 @@ -use decoder::PhotometricInterpretation; +use tags::PhotometricInterpretation; /// Trait for different colortypes that can be encoded. pub trait ColorType { diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs index 3055c13..6f3c63a 100644 --- a/src/encoder/mod.rs +++ b/src/encoder/mod.rs @@ -3,7 +3,7 @@ use std::collections::BTreeMap; use std::io::{Seek, Write}; use std::mem; -use decoder::ifd::{self, Tag, U16Tag}; +use tags::{self, ResolutionUnit, Tag, Type, U16Tag}; use error::{TiffError, TiffFormatError, TiffResult}; pub mod colortype; @@ -25,17 +25,10 @@ pub struct SRational { pub d: i32, } -/// Type to represent resolution units -pub enum ResolutionUnit { - None = 1, - Inch = 2, - Centimeter = 3, -} - /// Trait for types that can be encoded in a tiff file pub trait TiffValue { const BYTE_LEN: u32; - const FIELD_TYPE: ifd::Type; + const FIELD_TYPE: Type; fn count(&self) -> u32; fn bytes(&self) -> u32 { self.count() * Self::BYTE_LEN @@ -45,7 +38,7 @@ pub trait TiffValue { impl TiffValue for [u8] { const BYTE_LEN: u32 = 1; - const FIELD_TYPE: ifd::Type = ifd::Type::BYTE; + const FIELD_TYPE: Type = Type::BYTE; fn count(&self) -> u32 { self.len() as u32 @@ -59,7 +52,7 @@ impl TiffValue for [u8] { impl TiffValue for [i8] { const BYTE_LEN: u32 = 1; - const FIELD_TYPE: ifd::Type = ifd::Type::SBYTE; + const FIELD_TYPE: Type = Type::SBYTE; fn count(&self) -> u32 { self.len() as u32 @@ -76,7 +69,7 @@ impl TiffValue for [i8] { impl TiffValue for [u16] { const BYTE_LEN: u32 = 2; - const FIELD_TYPE: ifd::Type = ifd::Type::SHORT; + const FIELD_TYPE: Type = Type::SHORT; fn count(&self) -> u32 { self.len() as u32 @@ -93,7 +86,7 @@ impl TiffValue for [u16] { impl TiffValue for [i16] { const BYTE_LEN: u32 = 2; - const FIELD_TYPE: ifd::Type = ifd::Type::SSHORT; + const FIELD_TYPE: Type = Type::SSHORT; fn count(&self) -> u32 { self.len() as u32 @@ -110,7 +103,7 @@ impl TiffValue for [i16] { impl TiffValue for [u32] { const BYTE_LEN: u32 = 4; - const FIELD_TYPE: ifd::Type = ifd::Type::LONG; + const FIELD_TYPE: Type = Type::LONG; fn count(&self) -> u32 { self.len() as u32 @@ -127,7 +120,7 @@ impl TiffValue for [u32] { impl TiffValue for [i32] { const BYTE_LEN: u32 = 4; - const FIELD_TYPE: ifd::Type = ifd::Type::SLONG; + const FIELD_TYPE: Type = Type::SLONG; fn count(&self) -> u32 { self.len() as u32 @@ -144,7 +137,7 @@ impl TiffValue for [i32] { impl TiffValue for [u64] { const BYTE_LEN: u32 = 8; - const FIELD_TYPE: ifd::Type = ifd::Type::LONG8; + const FIELD_TYPE: Type = Type::LONG8; fn count(&self) -> u32 { self.len() as u32 @@ -161,7 +154,7 @@ impl TiffValue for [u64] { impl TiffValue for [Rational] { const BYTE_LEN: u32 = 8; - const FIELD_TYPE: ifd::Type = ifd::Type::RATIONAL; + const FIELD_TYPE: Type = Type::RATIONAL; fn count(&self) -> u32 { self.len() as u32 @@ -177,7 +170,7 @@ impl TiffValue for [Rational] { impl TiffValue for [SRational] { const BYTE_LEN: u32 = 8; - const FIELD_TYPE: ifd::Type = ifd::Type::SRATIONAL; + const FIELD_TYPE: Type = Type::SRATIONAL; fn count(&self) -> u32 { self.len() as u32 @@ -193,7 +186,7 @@ impl TiffValue for [SRational] { impl TiffValue for u8 { const BYTE_LEN: u32 = 1; - const FIELD_TYPE: ifd::Type = ifd::Type::BYTE; + const FIELD_TYPE: Type = Type::BYTE; fn count(&self) -> u32 { 1 @@ -207,7 +200,7 @@ impl TiffValue for u8 { impl TiffValue for i8 { const BYTE_LEN: u32 = 1; - const FIELD_TYPE: ifd::Type = ifd::Type::SBYTE; + const FIELD_TYPE: Type = Type::SBYTE; fn count(&self) -> u32 { 1 @@ -221,7 +214,7 @@ impl TiffValue for i8 { impl TiffValue for u16 { const BYTE_LEN: u32 = 2; - const FIELD_TYPE: ifd::Type = ifd::Type::SHORT; + const FIELD_TYPE: Type = Type::SHORT; fn count(&self) -> u32 { 1 @@ -235,7 +228,7 @@ impl TiffValue for u16 { impl TiffValue for i16 { const BYTE_LEN: u32 = 2; - const FIELD_TYPE: ifd::Type = ifd::Type::SSHORT; + const FIELD_TYPE: Type = Type::SSHORT; fn count(&self) -> u32 { 1 @@ -249,7 +242,7 @@ impl TiffValue for i16 { impl TiffValue for u32 { const BYTE_LEN: u32 = 4; - const FIELD_TYPE: ifd::Type = ifd::Type::LONG; + const FIELD_TYPE: Type = Type::LONG; fn count(&self) -> u32 { 1 @@ -263,7 +256,7 @@ impl TiffValue for u32 { impl TiffValue for i32 { const BYTE_LEN: u32 = 4; - const FIELD_TYPE: ifd::Type = ifd::Type::SLONG; + const FIELD_TYPE: Type = Type::SLONG; fn count(&self) -> u32 { 1 @@ -277,7 +270,7 @@ impl TiffValue for i32 { impl TiffValue for u64 { const BYTE_LEN: u32 = 8; - const FIELD_TYPE: ifd::Type = ifd::Type::LONG8; + const FIELD_TYPE: Type = Type::LONG8; fn count(&self) -> u32 { 1 @@ -291,7 +284,7 @@ impl TiffValue for u64 { impl TiffValue for Rational { const BYTE_LEN: u32 = 8; - const FIELD_TYPE: ifd::Type = ifd::Type::RATIONAL; + const FIELD_TYPE: Type = Type::RATIONAL; fn count(&self) -> u32 { 1 @@ -306,7 +299,7 @@ impl TiffValue for Rational { impl TiffValue for SRational { const BYTE_LEN: u32 = 8; - const FIELD_TYPE: ifd::Type = ifd::Type::SRATIONAL; + const FIELD_TYPE: Type = Type::SRATIONAL; fn count(&self) -> u32 { 1 @@ -321,7 +314,7 @@ impl TiffValue for SRational { impl TiffValue for str { const BYTE_LEN: u32 = 1; - const FIELD_TYPE: ifd::Type = ifd::Type::ASCII; + const FIELD_TYPE: Type = Type::ASCII; fn count(&self) -> u32 { self.len() as u32 + 1 @@ -340,7 +333,7 @@ impl TiffValue for str { impl<'a, T: TiffValue + ?Sized> TiffValue for &'a T { const BYTE_LEN: u32 = T::BYTE_LEN; - const FIELD_TYPE: ifd::Type = T::FIELD_TYPE; + const FIELD_TYPE: Type = T::FIELD_TYPE; fn count(&self) -> u32 { (*self).count() diff --git a/src/error.rs b/src/error.rs index dbdde69..27ef8c3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,8 +3,8 @@ use std::fmt; use std::io; use std::string; -use decoder::ifd::{Tag, Value}; -use decoder::{CompressionMethod, PhotometricInterpretation, PlanarConfiguration}; +use decoder::ifd::{Value}; +use tags::{CompressionMethod, PhotometricInterpretation, PlanarConfiguration, Tag}; use miniz_oxide::inflate::TINFLStatus; use ColorType; diff --git a/src/lib.rs b/src/lib.rs index 03ab3e2..7dec5ba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ extern crate miniz_oxide; pub mod decoder; pub mod encoder; mod error; +pub mod tags; pub use self::error::{InflateError, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError}; diff --git a/src/tags.rs b/src/tags.rs new file mode 100644 index 0000000..3c074cd --- /dev/null +++ b/src/tags.rs @@ -0,0 +1,188 @@ +mod seals { + pub trait TagConversion: Sized { + fn __from_inner_type(T) -> Result; + + fn __to_inner_type(&self) -> T; + } +} + +pub trait U16Tag: Sized { + fn from_u16(val: u16) -> Option; + + fn to_u16(&self) -> u16; +} + +impl> U16Tag for T { + fn from_u16(val: u16) -> Option { + Self::__from_inner_type(val).ok() + } + + fn to_u16(&self) -> u16 { + Self::__to_inner_type(self) + } +} + +macro_rules! tags { + { + // Permit arbitrary meta items, which include documentation. + $( #[$enum_attr:meta] )* + $vis:vis enum $name:ident($ty:ty) $(unknown($unknown_doc:literal))* { + // Each of the `Name = Val,` permitting documentation. + $($(#[$ident_attr:meta])* $tag:ident = $val:expr,)* + } + } => { + $( #[$enum_attr] )* + #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] + pub enum $name { + $($(#[$ident_attr])* $tag,)* + // FIXME: switch to non_exhaustive once stabilized and compiler requirement new enough + #[doc(hidden)] + __NonExhaustive, + $( + #[doc = $unknown_doc] + Unknown($ty), + )* + } + + impl ::tags::seals::TagConversion<$ty> for $name { + #[inline(always)] + fn __from_inner_type(n: $ty) -> Result { + match n { + $( $val => Ok($name::$tag), )* + n => Err(n), + } + } + + #[inline(always)] + fn __to_inner_type(&self) -> $ty { + match *self { + $( $name::$tag => $val, )* + $( $name::Unknown(n) => { $unknown_doc; n }, )* + $name::__NonExhaustive => unreachable!(), + } + } + } + } +} + +// Note: These tags appear in the order they are mentioned in the TIFF reference +tags! { +/// TIFF tags +pub enum Tag(u16) unknown("A private or extension tag") { + // Baseline tags: + Artist = 315, + // 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, + DateTime = 306, + 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, + ImageDescription = 270, + ImageLength = 257, + ImageWidth = 256, + Make = 271, + MaxSampleValue = 281, // TODO add support + MinSampleValue = 280, // TODO add support + Model = 272, + 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, +} +} + +impl Tag { + pub fn from_u16_exhaustive(val: u16) -> Self { + Self::from_u16(val).unwrap_or_else(|| Tag::Unknown(val)) + } +} + +tags! { +/// The type of an IFD entry (a 2 byte field). +pub enum Type(u16) { + BYTE = 1, + ASCII = 2, + SHORT = 3, + LONG = 4, + RATIONAL = 5, + SBYTE = 6, + SSHORT = 8, + SLONG = 9, + SRATIONAL = 10, + /// BigTIFF 64-bit unsigned integer + LONG8 = 16, +} +} + + +tags! { +pub enum CompressionMethod(u16) { + None = 1, + Huffman = 2, + Fax3 = 3, + Fax4 = 4, + LZW = 5, + JPEG = 6, + Deflate = 8, + OldDeflate = 0x80B2, + PackBits = 0x8005, +} +} + +tags! { +pub enum PhotometricInterpretation(u16) { + WhiteIsZero = 0, + BlackIsZero = 1, + RGB = 2, + RGBPalette = 3, + TransparencyMask = 4, + CMYK = 5, + YCbCr = 6, + CIELab = 8, +} +} + +tags! { +pub enum PlanarConfiguration(u16) { + Chunky = 1, + Planar = 2, +} +} + +tags! { +pub enum Predictor(u16) { + None = 1, + Horizontal = 2, +} +} + +tags!{ +/// Type to represent resolution units +pub enum ResolutionUnit(u16) { + None = 1, + Inch = 2, + Centimeter = 3, +} +} \ No newline at end of file diff --git a/tests/decode_images.rs b/tests/decode_images.rs index 7437cb1..7945d5b 100644 --- a/tests/decode_images.rs +++ b/tests/decode_images.rs @@ -106,7 +106,7 @@ fn test_string_tags() { let path = PathBuf::from(TEST_IMAGE_DIR).join(filename); let img_file = File::open(path).expect("Cannot find test image!"); let mut decoder = Decoder::new(img_file).expect("Cannot create decoder"); - let software = decoder.get_tag(ifd::Tag::Software).unwrap(); + let software = decoder.get_tag(tiff::tags::Tag::Software).unwrap(); match software { ifd::Value::Ascii(s) => assert_eq!( &s, diff --git a/tests/encode_images.rs b/tests/encode_images.rs index 988d386..32b1e88 100644 --- a/tests/encode_images.rs +++ b/tests/encode_images.rs @@ -1,9 +1,9 @@ extern crate tiff; use tiff::decoder::{Decoder, DecodingResult}; -use tiff::decoder::ifd::Tag; use tiff::encoder::{colortype, TiffEncoder, SRational}; use tiff::ColorType; +use tiff::tags::Tag; use std::fs::File; use std::io::{Cursor, Seek, SeekFrom};