gamut_tiff/compression/mod.rs
1//! TIFF compression schemes, selected by the `Compression` tag (259).
2//!
3//! Baseline TIFF readers must handle the uncompressed, Modified Huffman, and PackBits schemes;
4//! the remainder are extensions (TIFF 6.0 Part 2). Each scheme is decoded/encoded per strip or
5//! tile; the per-scheme codecs land in later phases.
6
7pub mod ccitt;
8pub mod lzw;
9pub mod packbits;
10pub mod predictor;
11
12/// A compression scheme applied to a strip or tile of image data.
13///
14/// The discriminants are documented with their on-disk `Compression` tag values.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
16pub enum Compression {
17 /// `1` — no compression; samples are packed into bytes as tightly as possible.
18 #[default]
19 None,
20 /// `2` — CCITT Group 3 1-Dimensional Modified Huffman run-length encoding (TIFF 6.0 §10).
21 CcittRle,
22 /// `3` — CCITT T.4 (Group 3) bilevel fax encoding (TIFF 6.0 §11).
23 CcittGroup3Fax,
24 /// `4` — CCITT T.6 (Group 4) bilevel fax encoding (TIFF 6.0 §11).
25 CcittGroup4Fax,
26 /// `5` — LZW (TIFF 6.0 §13).
27 Lzw,
28 /// `6` — the deprecated old-style JPEG process (TIFF 6.0 §22).
29 OldJpeg,
30 /// `7` — JPEG (the redefined "new-style" process; TIFF Technical Note 2).
31 Jpeg,
32 /// `8` — Deflate/zlib (Adobe). Post-6.0 extension; out of the current campaign's scope.
33 Deflate,
34 /// `32773` — PackBits, a simple byte-oriented run-length scheme (TIFF 6.0 §9).
35 PackBits,
36}
37
38impl Compression {
39 /// Returns the scheme for an on-disk `Compression` tag value, or `None` if unrecognised.
40 #[must_use]
41 pub fn from_code(code: u32) -> Option<Self> {
42 Some(match code {
43 1 => Compression::None,
44 2 => Compression::CcittRle,
45 3 => Compression::CcittGroup3Fax,
46 4 => Compression::CcittGroup4Fax,
47 5 => Compression::Lzw,
48 6 => Compression::OldJpeg,
49 7 => Compression::Jpeg,
50 8 | 32946 => Compression::Deflate,
51 32773 => Compression::PackBits,
52 _ => return None,
53 })
54 }
55
56 /// Returns the on-disk `Compression` tag value.
57 #[must_use]
58 pub fn code(self) -> u16 {
59 match self {
60 Compression::None => 1,
61 Compression::CcittRle => 2,
62 Compression::CcittGroup3Fax => 3,
63 Compression::CcittGroup4Fax => 4,
64 Compression::Lzw => 5,
65 Compression::OldJpeg => 6,
66 Compression::Jpeg => 7,
67 Compression::Deflate => 8,
68 Compression::PackBits => 32773,
69 }
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn compression_codes_round_trip() {
79 for c in [
80 Compression::None,
81 Compression::CcittRle,
82 Compression::CcittGroup3Fax,
83 Compression::CcittGroup4Fax,
84 Compression::Lzw,
85 Compression::OldJpeg,
86 Compression::Jpeg,
87 Compression::Deflate,
88 Compression::PackBits,
89 ] {
90 assert_eq!(Compression::from_code(u32::from(c.code())), Some(c));
91 }
92 assert_eq!(Compression::from_code(32946), Some(Compression::Deflate));
93 assert_eq!(Compression::from_code(99), None);
94 }
95}