Skip to main content

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}