1 macro_rules! tags { 2 { 3 // Permit arbitrary meta items, which include documentation. 4 $( #[$enum_attr:meta] )* 5 $vis:vis enum $name:ident($ty:tt) $(unknown($unknown_doc:literal))* { 6 // Each of the `Name = Val,` permitting documentation. 7 $($(#[$ident_attr:meta])* $tag:ident = $val:expr,)* 8 } 9 } => { 10 $( #[$enum_attr] )* 11 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] 12 pub enum $name { 13 $($(#[$ident_attr])* $tag,)* 14 // FIXME: switch to non_exhaustive once stabilized and compiler requirement new enough 15 #[doc(hidden)] 16 __NonExhaustive, 17 $( 18 #[doc = $unknown_doc] 19 Unknown($ty), 20 )* 21 } 22 23 impl $name { 24 #[inline(always)] 25 fn __from_inner_type(n: $ty) -> Result<Self, $ty> { 26 match n { 27 $( $val => Ok($name::$tag), )* 28 n => Err(n), 29 } 30 } 31 32 #[inline(always)] 33 fn __to_inner_type(&self) -> $ty { 34 match *self { 35 $( $name::$tag => $val, )* 36 $( $name::Unknown(n) => { $unknown_doc; n }, )* 37 $name::__NonExhaustive => unreachable!(), 38 } 39 } 40 } 41 42 tags!($name, $ty); 43 }; 44 // For u16 tags, provide direct inherent primitive conversion methods. 45 ($name:tt, u16) => { 46 impl $name { 47 #[inline(always)] 48 pub fn from_u16(val: u16) -> Option<Self> { 49 Self::__from_inner_type(val).ok() 50 } 51 52 #[inline(always)] 53 pub fn to_u16(&self) -> u16 { 54 Self::__to_inner_type(self) 55 } 56 } 57 }; 58 // For other tag types, do nothing for now. With concat_idents one could 59 // provide inherent conversion methods for all types. 60 ($name:tt, $ty:tt) => {}; 61 } 62 63 // Note: These tags appear in the order they are mentioned in the TIFF reference 64 tags! { 65 /// TIFF tags 66 pub enum Tag(u16) unknown("A private or extension tag") { 67 // Baseline tags: 68 Artist = 315, 69 // grayscale images PhotometricInterpretation 1 or 3 70 BitsPerSample = 258, 71 CellLength = 265, // TODO add support 72 CellWidth = 264, // TODO add support 73 // palette-color images (PhotometricInterpretation 3) 74 ColorMap = 320, // TODO add support 75 Compression = 259, // TODO add support for 2 and 32773 76 Copyright = 33_432, 77 DateTime = 306, 78 ExtraSamples = 338, // TODO add support 79 FillOrder = 266, // TODO add support 80 FreeByteCounts = 289, // TODO add support 81 FreeOffsets = 288, // TODO add support 82 GrayResponseCurve = 291, // TODO add support 83 GrayResponseUnit = 290, // TODO add support 84 HostComputer = 316, 85 ImageDescription = 270, 86 ImageLength = 257, 87 ImageWidth = 256, 88 Make = 271, 89 MaxSampleValue = 281, // TODO add support 90 MinSampleValue = 280, // TODO add support 91 Model = 272, 92 NewSubfileType = 254, // TODO add support 93 Orientation = 274, // TODO add support 94 PhotometricInterpretation = 262, 95 PlanarConfiguration = 284, 96 ResolutionUnit = 296, // TODO add support 97 RowsPerStrip = 278, 98 SamplesPerPixel = 277, 99 Software = 305, 100 StripByteCounts = 279, 101 StripOffsets = 273, 102 SubfileType = 255, // TODO add support 103 Threshholding = 263, // TODO add support 104 XResolution = 282, 105 YResolution = 283, 106 // Advanced tags 107 Predictor = 317, 108 } 109 } 110 111 impl Tag { from_u16_exhaustive(val: u16) -> Self112 pub fn from_u16_exhaustive(val: u16) -> Self { 113 Self::from_u16(val).unwrap_or_else(|| Tag::Unknown(val)) 114 } 115 } 116 117 tags! { 118 /// The type of an IFD entry (a 2 byte field). 119 pub enum Type(u16) { 120 BYTE = 1, 121 ASCII = 2, 122 SHORT = 3, 123 LONG = 4, 124 RATIONAL = 5, 125 SBYTE = 6, 126 SSHORT = 8, 127 SLONG = 9, 128 SRATIONAL = 10, 129 /// BigTIFF 64-bit unsigned integer 130 LONG8 = 16, 131 } 132 } 133 134 135 tags! { 136 pub enum CompressionMethod(u16) { 137 None = 1, 138 Huffman = 2, 139 Fax3 = 3, 140 Fax4 = 4, 141 LZW = 5, 142 JPEG = 6, 143 Deflate = 8, 144 OldDeflate = 0x80B2, 145 PackBits = 0x8005, 146 } 147 } 148 149 tags! { 150 pub enum PhotometricInterpretation(u16) { 151 WhiteIsZero = 0, 152 BlackIsZero = 1, 153 RGB = 2, 154 RGBPalette = 3, 155 TransparencyMask = 4, 156 CMYK = 5, 157 YCbCr = 6, 158 CIELab = 8, 159 } 160 } 161 162 tags! { 163 pub enum PlanarConfiguration(u16) { 164 Chunky = 1, 165 Planar = 2, 166 } 167 } 168 169 tags! { 170 pub enum Predictor(u16) { 171 None = 1, 172 Horizontal = 2, 173 } 174 } 175 176 tags!{ 177 /// Type to represent resolution units 178 pub enum ResolutionUnit(u16) { 179 None = 1, 180 Inch = 2, 181 Centimeter = 3, 182 } 183 }