1mod ascii_85;
4pub(crate) mod ascii_hex;
5#[cfg(feature = "images")]
6mod ccitt;
7#[cfg(feature = "images")]
8mod dct;
9#[cfg(feature = "images")]
10mod jbig2;
11#[cfg(feature = "images")]
12mod jpx;
13mod lzw_flate;
14mod run_length;
15
16use crate::object::Dict;
17use crate::object::Name;
18use crate::object::dict::keys::*;
19use crate::object::stream::{DecodeFailure, FilterResult, ImageDecodeParams};
20use core::ops::Deref;
21use log::warn;
22
23#[derive(Debug, Copy, Clone, PartialEq, Eq)]
25pub enum Filter {
26 AsciiHexDecode,
28 Ascii85Decode,
30 LzwDecode,
32 FlateDecode,
34 RunLengthDecode,
36 CcittFaxDecode,
38 Jbig2Decode,
40 DctDecode,
42 JpxDecode,
44 Crypt,
46}
47
48impl Filter {
49 fn debug_name(&self) -> &'static str {
50 match self {
51 Self::AsciiHexDecode => "ascii_hex",
52 Self::Ascii85Decode => "ascii_85",
53 Self::LzwDecode => "lzw",
54 Self::FlateDecode => "flate",
55 Self::RunLengthDecode => "run-length",
56 Self::CcittFaxDecode => "ccit_fax",
57 Self::Jbig2Decode => "jbig2",
58 Self::DctDecode => "dct",
59 Self::JpxDecode => "jpx",
60 Self::Crypt => "crypt",
61 }
62 }
63
64 pub(crate) fn from_name(name: Name) -> Option<Self> {
65 match name.deref() {
66 ASCII_HEX_DECODE | ASCII_HEX_DECODE_ABBREVIATION => Some(Self::AsciiHexDecode),
67 ASCII85_DECODE | ASCII85_DECODE_ABBREVIATION => Some(Self::Ascii85Decode),
68 LZW_DECODE | LZW_DECODE_ABBREVIATION => Some(Self::LzwDecode),
69 FLATE_DECODE | FLATE_DECODE_ABBREVIATION => Some(Self::FlateDecode),
70 RUN_LENGTH_DECODE | RUN_LENGTH_DECODE_ABBREVIATION => Some(Self::RunLengthDecode),
71 CCITTFAX_DECODE | CCITTFAX_DECODE_ABBREVIATION => Some(Self::CcittFaxDecode),
72 JBIG2_DECODE => Some(Self::Jbig2Decode),
73 DCT_DECODE | DCT_DECODE_ABBREVIATION => Some(Self::DctDecode),
74 JPX_DECODE => Some(Self::JpxDecode),
75 CRYPT => Some(Self::Crypt),
76 _ => {
77 warn!("unknown filter: {}", name.as_str());
78
79 None
80 }
81 }
82 }
83
84 pub(crate) fn apply(
85 &self,
86 data: &[u8],
87 params: Dict<'_>,
88 #[cfg_attr(not(feature = "images"), allow(unused))] image_params: &ImageDecodeParams,
89 ) -> Result<FilterResult, DecodeFailure> {
90 let res = match self {
91 Self::AsciiHexDecode => ascii_hex::decode(data)
92 .map(FilterResult::from_data)
93 .ok_or(DecodeFailure::StreamDecode),
94 Self::Ascii85Decode => ascii_85::decode(data)
95 .map(FilterResult::from_data)
96 .ok_or(DecodeFailure::StreamDecode),
97 Self::RunLengthDecode => run_length::decode(data)
98 .map(FilterResult::from_data)
99 .ok_or(DecodeFailure::StreamDecode),
100 Self::LzwDecode => lzw_flate::lzw::decode(data, params)
101 .map(FilterResult::from_data)
102 .ok_or(DecodeFailure::StreamDecode),
103 Self::FlateDecode => lzw_flate::flate::decode(data, params)
104 .map(FilterResult::from_data)
105 .ok_or(DecodeFailure::StreamDecode),
106 #[cfg(feature = "images")]
107 Self::DctDecode => {
108 dct::decode(data, params, image_params).ok_or(DecodeFailure::ImageDecode)
109 }
110 #[cfg(feature = "images")]
111 Self::CcittFaxDecode => {
112 ccitt::decode(data, params, image_params).ok_or(DecodeFailure::ImageDecode)
113 }
114 #[cfg(feature = "images")]
115 Self::Jbig2Decode => Ok(FilterResult::from_data(
116 jbig2::decode(data, params).ok_or(DecodeFailure::ImageDecode)?,
117 )),
118 #[cfg(feature = "images")]
119 Self::JpxDecode => jpx::decode(data, image_params).ok_or(DecodeFailure::ImageDecode),
120 #[cfg(not(feature = "images"))]
121 Self::DctDecode | Self::CcittFaxDecode | Self::Jbig2Decode | Self::JpxDecode => {
122 warn!("image decoding is not supported (enable the `images` feature)");
123 Err(DecodeFailure::ImageDecode)
124 }
125 _ => Err(DecodeFailure::StreamDecode),
126 };
127
128 if res.is_err() {
129 warn!("failed to apply filter {}", self.debug_name());
130 }
131
132 res
133 }
134}