hayro_syntax/filter/
mod.rs1mod 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;
21
22#[derive(Debug, Copy, Clone, PartialEq, Eq)]
24pub enum Filter {
25 AsciiHexDecode,
27 Ascii85Decode,
29 LzwDecode,
31 FlateDecode,
33 RunLengthDecode,
35 CcittFaxDecode,
37 Jbig2Decode,
39 DctDecode,
41 JpxDecode,
43 Crypt,
45}
46
47impl Filter {
48 fn debug_name(&self) -> &'static str {
49 match self {
50 Self::AsciiHexDecode => "ascii_hex",
51 Self::Ascii85Decode => "ascii_85",
52 Self::LzwDecode => "lzw",
53 Self::FlateDecode => "flate",
54 Self::RunLengthDecode => "run-length",
55 Self::CcittFaxDecode => "ccit_fax",
56 Self::Jbig2Decode => "jbig2",
57 Self::DctDecode => "dct",
58 Self::JpxDecode => "jpx",
59 Self::Crypt => "crypt",
60 }
61 }
62
63 pub(crate) fn from_name(name: Name<'_>) -> Option<Self> {
64 match name.deref() {
65 ASCII_HEX_DECODE | ASCII_HEX_DECODE_ABBREVIATION => Some(Self::AsciiHexDecode),
66 ASCII85_DECODE | ASCII85_DECODE_ABBREVIATION => Some(Self::Ascii85Decode),
67 LZW_DECODE | LZW_DECODE_ABBREVIATION => Some(Self::LzwDecode),
68 FLATE_DECODE | FLATE_DECODE_ABBREVIATION => Some(Self::FlateDecode),
69 RUN_LENGTH_DECODE | RUN_LENGTH_DECODE_ABBREVIATION => Some(Self::RunLengthDecode),
70 CCITTFAX_DECODE | CCITTFAX_DECODE_ABBREVIATION => Some(Self::CcittFaxDecode),
71 JBIG2_DECODE => Some(Self::Jbig2Decode),
72 DCT_DECODE | DCT_DECODE_ABBREVIATION => Some(Self::DctDecode),
73 JPX_DECODE => Some(Self::JpxDecode),
74 CRYPT => Some(Self::Crypt),
75 _ => {
76 warn!("unknown filter: {}", name.as_str());
77
78 None
79 }
80 }
81 }
82
83 pub(crate) fn apply(
84 &self,
85 data: &[u8],
86 params: &Dict<'_>,
87 #[cfg_attr(not(feature = "images"), allow(unused))] image_params: &ImageDecodeParams,
88 ) -> Result<FilterResult<'static>, DecodeFailure> {
89 let res = match self {
90 Self::AsciiHexDecode => ascii_hex::decode(data)
91 .map(FilterResult::from_data)
92 .ok_or(DecodeFailure::StreamDecode),
93 Self::Ascii85Decode => ascii_85::decode(data)
94 .map(FilterResult::from_data)
95 .ok_or(DecodeFailure::StreamDecode),
96 Self::RunLengthDecode => run_length::decode(data)
97 .map(FilterResult::from_data)
98 .ok_or(DecodeFailure::StreamDecode),
99 Self::LzwDecode => lzw_flate::lzw::decode(data, params)
100 .map(FilterResult::from_data)
101 .ok_or(DecodeFailure::StreamDecode),
102 Self::FlateDecode => lzw_flate::flate::decode(data, params)
103 .map(FilterResult::from_data)
104 .ok_or(DecodeFailure::StreamDecode),
105 #[cfg(feature = "images")]
106 Self::DctDecode => {
107 dct::decode(data, params, image_params).ok_or(DecodeFailure::ImageDecode)
108 }
109 #[cfg(feature = "images")]
110 Self::CcittFaxDecode => {
111 ccitt::decode(data, params, image_params).ok_or(DecodeFailure::ImageDecode)
112 }
113 #[cfg(feature = "images")]
114 Self::Jbig2Decode => {
115 jbig2::decode(data, params, image_params).ok_or(DecodeFailure::ImageDecode)
116 }
117 #[cfg(feature = "images")]
118 Self::JpxDecode => jpx::decode(data, image_params).ok_or(DecodeFailure::ImageDecode),
119 #[cfg(not(feature = "images"))]
120 Self::DctDecode | Self::CcittFaxDecode | Self::Jbig2Decode | Self::JpxDecode => {
121 warn!("image decoding is not supported (enable the `images` feature)");
122 Err(DecodeFailure::ImageDecode)
123 }
124 _ => Err(DecodeFailure::StreamDecode),
125 };
126
127 if res.is_err() {
128 warn!("failed to apply filter {}", self.debug_name());
129 }
130
131 res
132 }
133}