1pub const TAG_NEW_SUBFILE_TYPE: u16 = 254;
3pub const TAG_SUBFILE_TYPE: u16 = 255;
4pub const TAG_IMAGE_WIDTH: u16 = 256;
5pub const TAG_IMAGE_LENGTH: u16 = 257;
6pub const TAG_BITS_PER_SAMPLE: u16 = 258;
7pub const TAG_COMPRESSION: u16 = 259;
8pub const TAG_PHOTOMETRIC_INTERPRETATION: u16 = 262;
9pub const TAG_STRIP_OFFSETS: u16 = 273;
10pub const TAG_SAMPLES_PER_PIXEL: u16 = 277;
11pub const TAG_ROWS_PER_STRIP: u16 = 278;
12pub const TAG_STRIP_BYTE_COUNTS: u16 = 279;
13pub const TAG_PLANAR_CONFIGURATION: u16 = 284;
14pub const TAG_PREDICTOR: u16 = 317;
15pub const TAG_TILE_WIDTH: u16 = 322;
16pub const TAG_TILE_LENGTH: u16 = 323;
17pub const TAG_TILE_OFFSETS: u16 = 324;
18pub const TAG_TILE_BYTE_COUNTS: u16 = 325;
19pub const TAG_SAMPLE_FORMAT: u16 = 339;
20pub const TAG_JPEG_TABLES: u16 = 347;
21pub const TAG_LERC_PARAMETERS: u16 = 50674;
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
25pub enum Compression {
26 None,
27 Lzw,
28 OldJpeg,
29 Jpeg,
30 Deflate,
31 PackBits,
32 DeflateOld,
33 Lerc,
34 Zstd,
35}
36
37impl Compression {
38 pub fn from_code(code: u16) -> Option<Self> {
39 match code {
40 1 => Some(Self::None),
41 5 => Some(Self::Lzw),
42 6 => Some(Self::OldJpeg),
43 7 => Some(Self::Jpeg),
44 8 => Some(Self::Deflate),
45 32773 => Some(Self::PackBits),
46 32946 => Some(Self::DeflateOld),
47 34887 => Some(Self::Lerc),
48 50000 => Some(Self::Zstd),
49 _ => None,
50 }
51 }
52
53 pub fn to_code(self) -> u16 {
54 match self {
55 Self::None => 1,
56 Self::Lzw => 5,
57 Self::OldJpeg => 6,
58 Self::Jpeg => 7,
59 Self::Deflate => 8,
60 Self::PackBits => 32773,
61 Self::DeflateOld => 32946,
62 Self::Lerc => 34887,
63 Self::Zstd => 50000,
64 }
65 }
66
67 pub fn name(self) -> &'static str {
68 match self {
69 Self::None => "None",
70 Self::Lzw => "LZW",
71 Self::OldJpeg => "OldJpeg",
72 Self::Jpeg => "JPEG",
73 Self::Deflate => "Deflate",
74 Self::PackBits => "PackBits",
75 Self::DeflateOld => "DeflateOld",
76 Self::Lerc => "LERC",
77 Self::Zstd => "ZSTD",
78 }
79 }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
84pub enum Predictor {
85 None,
86 Horizontal,
87 FloatingPoint,
88}
89
90impl Predictor {
91 pub fn from_code(code: u16) -> Option<Self> {
92 match code {
93 1 => Some(Self::None),
94 2 => Some(Self::Horizontal),
95 3 => Some(Self::FloatingPoint),
96 _ => None,
97 }
98 }
99
100 pub fn to_code(self) -> u16 {
101 match self {
102 Self::None => 1,
103 Self::Horizontal => 2,
104 Self::FloatingPoint => 3,
105 }
106 }
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
111pub enum SampleFormat {
112 Uint,
113 Int,
114 Float,
115}
116
117impl SampleFormat {
118 pub fn from_code(code: u16) -> Option<Self> {
119 match code {
120 1 => Some(Self::Uint),
121 2 => Some(Self::Int),
122 3 => Some(Self::Float),
123 _ => None,
124 }
125 }
126
127 pub fn to_code(self) -> u16 {
128 match self {
129 Self::Uint => 1,
130 Self::Int => 2,
131 Self::Float => 3,
132 }
133 }
134}
135
136#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
138pub enum PhotometricInterpretation {
139 MinIsWhite,
140 MinIsBlack,
141 Rgb,
142 Palette,
143 Mask,
144}
145
146impl PhotometricInterpretation {
147 pub fn from_code(code: u16) -> Option<Self> {
148 match code {
149 0 => Some(Self::MinIsWhite),
150 1 => Some(Self::MinIsBlack),
151 2 => Some(Self::Rgb),
152 3 => Some(Self::Palette),
153 4 => Some(Self::Mask),
154 _ => None,
155 }
156 }
157
158 pub fn to_code(self) -> u16 {
159 match self {
160 Self::MinIsWhite => 0,
161 Self::MinIsBlack => 1,
162 Self::Rgb => 2,
163 Self::Palette => 3,
164 Self::Mask => 4,
165 }
166 }
167}
168
169#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
171pub enum PlanarConfiguration {
172 Chunky,
173 Planar,
174}
175
176impl PlanarConfiguration {
177 pub fn from_code(code: u16) -> Option<Self> {
178 match code {
179 1 => Some(Self::Chunky),
180 2 => Some(Self::Planar),
181 _ => None,
182 }
183 }
184
185 pub fn to_code(self) -> u16 {
186 match self {
187 Self::Chunky => 1,
188 Self::Planar => 2,
189 }
190 }
191}
192
193#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
199pub enum LercAdditionalCompression {
200 None,
201 Deflate,
202 Zstd,
203}
204
205impl LercAdditionalCompression {
206 pub fn from_code(code: u32) -> Option<Self> {
207 match code {
208 0 => Some(Self::None),
209 1 => Some(Self::Deflate),
210 2 => Some(Self::Zstd),
211 _ => None,
212 }
213 }
214
215 pub fn to_code(self) -> u32 {
216 match self {
217 Self::None => 0,
218 Self::Deflate => 1,
219 Self::Zstd => 2,
220 }
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227
228 #[test]
229 fn compression_roundtrips_lerc() {
230 assert_eq!(Compression::from_code(34887), Some(Compression::Lerc));
231 assert_eq!(Compression::Lerc.to_code(), 34887);
232 assert_eq!(Compression::Lerc.name(), "LERC");
233 }
234
235 #[test]
236 fn lerc_parameters_tag_matches_registered_value() {
237 assert_eq!(TAG_LERC_PARAMETERS, 50674);
238 }
239
240 #[test]
241 fn lerc_additional_compression_roundtrips() {
242 for (code, expected) in [
243 (0, LercAdditionalCompression::None),
244 (1, LercAdditionalCompression::Deflate),
245 (2, LercAdditionalCompression::Zstd),
246 ] {
247 assert_eq!(LercAdditionalCompression::from_code(code), Some(expected));
248 assert_eq!(expected.to_code(), code);
249 }
250 assert_eq!(LercAdditionalCompression::from_code(99), None);
251 }
252}