hayro_syntax/filter/
mod.rs

1//! Results from decoding filtered data streams.
2
3mod ascii_85;
4pub(crate) mod ascii_hex;
5mod ccitt;
6mod dct;
7mod jbig2;
8mod jpx;
9mod lzw_flate;
10mod run_length;
11
12use crate::object::Dict;
13use crate::object::Name;
14use crate::object::dict::keys::*;
15use crate::object::stream::{DecodeFailure, FilterResult, ImageDecodeParams};
16use log::warn;
17use std::ops::Deref;
18
19/// A data filter.
20#[derive(Debug, Copy, Clone, PartialEq, Eq)]
21pub enum Filter {
22    /// ASCII hexadecimal encoding.
23    AsciiHexDecode,
24    /// ASCII base-85 encoding.
25    Ascii85Decode,
26    /// Lempel-Ziv-Welch (LZW) compression.
27    LzwDecode,
28    /// DEFLATE compression (zlib/gzip).
29    FlateDecode,
30    /// Run-length encoding compression.
31    RunLengthDecode,
32    /// CCITT Group 3 or Group 4 fax compression.
33    CcittFaxDecode,
34    /// JBIG2 compression for bi-level images.
35    Jbig2Decode,
36    /// JPEG (DCT) compression.
37    DctDecode,
38    /// JPEG 2000 compression.
39    JpxDecode,
40    /// Encryption filter.
41    Crypt,
42}
43
44impl Filter {
45    fn debug_name(&self) -> &'static str {
46        match self {
47            Self::AsciiHexDecode => "ascii_hex",
48            Self::Ascii85Decode => "ascii_85",
49            Self::LzwDecode => "lzw",
50            Self::FlateDecode => "flate",
51            Self::RunLengthDecode => "run-length",
52            Self::CcittFaxDecode => "ccit_fax",
53            Self::Jbig2Decode => "jbig2",
54            Self::DctDecode => "dct",
55            Self::JpxDecode => "jpx",
56            Self::Crypt => "crypt",
57        }
58    }
59
60    pub(crate) fn from_name(name: Name<'_>) -> Option<Self> {
61        match name.deref() {
62            ASCII_HEX_DECODE | ASCII_HEX_DECODE_ABBREVIATION => Some(Self::AsciiHexDecode),
63            ASCII85_DECODE | ASCII85_DECODE_ABBREVIATION => Some(Self::Ascii85Decode),
64            LZW_DECODE | LZW_DECODE_ABBREVIATION => Some(Self::LzwDecode),
65            FLATE_DECODE | FLATE_DECODE_ABBREVIATION => Some(Self::FlateDecode),
66            RUN_LENGTH_DECODE | RUN_LENGTH_DECODE_ABBREVIATION => Some(Self::RunLengthDecode),
67            CCITTFAX_DECODE | CCITTFAX_DECODE_ABBREVIATION => Some(Self::CcittFaxDecode),
68            JBIG2_DECODE => Some(Self::Jbig2Decode),
69            DCT_DECODE | DCT_DECODE_ABBREVIATION => Some(Self::DctDecode),
70            JPX_DECODE => Some(Self::JpxDecode),
71            CRYPT => Some(Self::Crypt),
72            _ => {
73                warn!("unknown filter: {}", name.as_str());
74
75                None
76            }
77        }
78    }
79
80    pub(crate) fn apply(
81        &self,
82        data: &[u8],
83        params: Dict<'_>,
84        image_params: &ImageDecodeParams,
85    ) -> Result<FilterResult, DecodeFailure> {
86        let res = match self {
87            Self::AsciiHexDecode => ascii_hex::decode(data)
88                .map(FilterResult::from_data)
89                .ok_or(DecodeFailure::StreamDecode),
90            Self::Ascii85Decode => ascii_85::decode(data)
91                .map(FilterResult::from_data)
92                .ok_or(DecodeFailure::StreamDecode),
93            Self::RunLengthDecode => run_length::decode(data)
94                .map(FilterResult::from_data)
95                .ok_or(DecodeFailure::StreamDecode),
96            Self::LzwDecode => lzw_flate::lzw::decode(data, params)
97                .map(FilterResult::from_data)
98                .ok_or(DecodeFailure::StreamDecode),
99            Self::DctDecode => {
100                dct::decode(data, params, image_params).ok_or(DecodeFailure::ImageDecode)
101            }
102            Self::FlateDecode => lzw_flate::flate::decode(data, params)
103                .map(FilterResult::from_data)
104                .ok_or(DecodeFailure::StreamDecode),
105            Self::CcittFaxDecode => {
106                ccitt::decode(data, params, image_params).ok_or(DecodeFailure::ImageDecode)
107            }
108            Self::Jbig2Decode => Ok(FilterResult::from_data(
109                jbig2::decode(data, params).ok_or(DecodeFailure::ImageDecode)?,
110            )),
111            Self::JpxDecode => jpx::decode(data, image_params).ok_or(DecodeFailure::ImageDecode),
112            _ => Err(DecodeFailure::StreamDecode),
113        };
114
115        if res.is_err() {
116            warn!("failed to apply filter {}", self.debug_name());
117        }
118
119        res
120    }
121}