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.
This commit is contained in:
Andrew Champion committed 2019-12-21 15:57:24 +00:00
1 parent f9cace84da
commit f92be13f6c
9 files changed
+242 -238

No files matched your search

+1 -138
View File
@@ -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<T>: Sized {
fn __from_inner_type(T) -> Result<Self, T>;
fn __to_inner_type(&self) -> T;
}
}
pub trait U16Tag: Sized {
fn from_u16(val: u16) -> Option<Self>;
fn to_u16(&self) -> u16;
}
impl<T: seals::TagConversion<u16>> U16Tag for T {
fn from_u16(val: u16) -> Option<Self> {
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<Self, $ty> {
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)]
+25 -66
View File
@@ -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<R: Read + Seek> Decoder<R> {
/// 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<R: Read + Seek> Decoder<R> {
// Type 2 bytes
// Count 4 bytes
// Value 4 bytes either a pointer the value itself
fn read_entry(&mut self) -> TiffResult<Option<(ifd::Tag, ifd::Entry)>> {
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<Option<(Tag, ifd::Entry)>> {
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<R: Read + Seek> Decoder<R> {
/// Tries to retrieve a tag.
/// Return `Ok(None)` if the tag is not present.
pub fn find_tag(&mut self, tag: ifd::Tag) -> TiffResult<Option<ifd::Value>> {
pub fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<ifd::Value>> {
let entry = match self.ifd.as_ref().unwrap().get(&tag) {
None => return Ok(None),
Some(entry) => entry.clone(),
@@ -545,7 +504,7 @@ impl<R: Read + Seek> Decoder<R> {
}
/// Tries to retrieve a tag and convert it to the desired unsigned type.
pub fn find_tag_unsigned<T: TryFrom<u32>>(&mut self, tag: ifd::Tag) -> TiffResult<Option<T>> {
pub fn find_tag_unsigned<T: TryFrom<u32>>(&mut self, tag: Tag) -> TiffResult<Option<T>> {
self.find_tag(tag)?
.map(|v| v.into_u32()).transpose()?
.map(|value| T::try_from(value)
@@ -555,7 +514,7 @@ impl<R: Read + Seek> Decoder<R> {
/// 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<T: TryFrom<u32>>(&mut self, tag: ifd::Tag) -> TiffResult<Option<Vec<T>>> {
pub fn find_tag_unsigned_vec<T: TryFrom<u32>>(&mut self, tag: Tag) -> TiffResult<Option<Vec<T>>> {
self.find_tag(tag)?
.map(|v| v.into_u32_vec()).transpose()?
.map(|v| v.into_iter()
@@ -566,14 +525,14 @@ impl<R: Read + Seek> Decoder<R> {
/// 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<T: TryFrom<u32>>(&mut self, tag: ifd::Tag) -> TiffResult<T> {
pub fn get_tag_unsigned<T: TryFrom<u32>>(&mut self, tag: Tag) -> TiffResult<T> {
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<ifd::Value> {
pub fn get_tag(&mut self, tag: Tag) -> TiffResult<ifd::Value> {
match self.find_tag(tag)? {
Some(val) => Ok(val),
None => Err(TiffError::FormatError(
@@ -583,12 +542,12 @@ impl<R: Read + Seek> Decoder<R> {
}
/// Tries to retrieve a tag and convert it to the desired type.
pub fn get_tag_u32(&mut self, tag: ifd::Tag) -> TiffResult<u32> {
pub fn get_tag_u32(&mut self, tag: Tag) -> TiffResult<u32> {
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<Vec<u32>> {
pub fn get_tag_u32_vec(&mut self, tag: Tag) -> TiffResult<Vec<u32>> {
self.get_tag(tag)?.into_u32_vec()
}
@@ -714,7 +673,7 @@ impl<R: Read + Seek> Decoder<R> {
/// Number of strips in image
pub fn strip_count(&mut self) -> TiffResult<u32> {
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<R: Read + Seek> Decoder<R> {
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<R: Read + Seek> Decoder<R> {
))?;
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<R: Read + Seek> Decoder<R> {
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<R: Read + Seek> Decoder<R> {
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<R: Read + Seek> Decoder<R> {
pub fn read_image(&mut self) -> TiffResult<DecodingResult> {
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 =
+1 -1
View File
@@ -1,4 +1,4 @@
use decoder::PhotometricInterpretation;
use tags::PhotometricInterpretation;
/// Trait for different colortypes that can be encoded.
pub trait ColorType {
+22 -29
View File
@@ -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()
+2 -2
View File
@@ -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;
+1
View File
@@ -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};
+188
View File
@@ -0,0 +1,188 @@
mod seals {
pub trait TagConversion<T>: Sized {
fn __from_inner_type(T) -> Result<Self, T>;
fn __to_inner_type(&self) -> T;
}
}
pub trait U16Tag: Sized {
fn from_u16(val: u16) -> Option<Self>;
fn to_u16(&self) -> u16;
}
impl<T: seals::TagConversion<u16>> U16Tag for T {
fn from_u16(val: u16) -> Option<Self> {
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<Self, $ty> {
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,
}
}
+1 -1
View File
@@ -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,
+1 -1
View File
@@ -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};