mod ascii_85;
pub(crate) mod ascii_hex;
#[cfg(feature = "images")]
mod ccitt;
#[cfg(feature = "images")]
mod dct;
#[cfg(feature = "images")]
mod jbig2;
#[cfg(feature = "images")]
mod jpx;
mod lzw_flate;
mod run_length;
use crate::object::Dict;
use crate::object::Name;
use crate::object::dict::keys::*;
use crate::object::stream::{DecodeFailure, FilterResult, ImageDecodeParams};
use core::ops::Deref;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Filter {
AsciiHexDecode,
Ascii85Decode,
LzwDecode,
FlateDecode,
RunLengthDecode,
CcittFaxDecode,
Jbig2Decode,
DctDecode,
JpxDecode,
Crypt,
}
impl Filter {
fn debug_name(&self) -> &'static str {
match self {
Self::AsciiHexDecode => "ascii_hex",
Self::Ascii85Decode => "ascii_85",
Self::LzwDecode => "lzw",
Self::FlateDecode => "flate",
Self::RunLengthDecode => "run-length",
Self::CcittFaxDecode => "ccit_fax",
Self::Jbig2Decode => "jbig2",
Self::DctDecode => "dct",
Self::JpxDecode => "jpx",
Self::Crypt => "crypt",
}
}
pub(crate) fn from_name(name: Name<'_>) -> Option<Self> {
match name.deref() {
ASCII_HEX_DECODE | ASCII_HEX_DECODE_ABBREVIATION => Some(Self::AsciiHexDecode),
ASCII85_DECODE | ASCII85_DECODE_ABBREVIATION => Some(Self::Ascii85Decode),
LZW_DECODE | LZW_DECODE_ABBREVIATION => Some(Self::LzwDecode),
FLATE_DECODE | FLATE_DECODE_ABBREVIATION => Some(Self::FlateDecode),
RUN_LENGTH_DECODE | RUN_LENGTH_DECODE_ABBREVIATION => Some(Self::RunLengthDecode),
CCITTFAX_DECODE | CCITTFAX_DECODE_ABBREVIATION => Some(Self::CcittFaxDecode),
JBIG2_DECODE => Some(Self::Jbig2Decode),
DCT_DECODE | DCT_DECODE_ABBREVIATION => Some(Self::DctDecode),
JPX_DECODE => Some(Self::JpxDecode),
CRYPT => Some(Self::Crypt),
_ => {
warn!("unknown filter: {}", name.as_str());
None
}
}
}
pub(crate) fn apply(
&self,
data: &[u8],
params: &Dict<'_>,
#[cfg_attr(not(feature = "images"), allow(unused))] image_params: &ImageDecodeParams,
) -> Result<FilterResult<'static>, DecodeFailure> {
let res = match self {
Self::AsciiHexDecode => ascii_hex::decode(data)
.map(FilterResult::from_data)
.ok_or(DecodeFailure::StreamDecode),
Self::Ascii85Decode => ascii_85::decode(data)
.map(FilterResult::from_data)
.ok_or(DecodeFailure::StreamDecode),
Self::RunLengthDecode => run_length::decode(data)
.map(FilterResult::from_data)
.ok_or(DecodeFailure::StreamDecode),
Self::LzwDecode => lzw_flate::lzw::decode(data, params)
.map(FilterResult::from_data)
.ok_or(DecodeFailure::StreamDecode),
Self::FlateDecode => lzw_flate::flate::decode(data, params)
.map(FilterResult::from_data)
.ok_or(DecodeFailure::StreamDecode),
#[cfg(feature = "images")]
Self::DctDecode => {
dct::decode(data, params, image_params).ok_or(DecodeFailure::ImageDecode)
}
#[cfg(feature = "images")]
Self::CcittFaxDecode => {
ccitt::decode(data, params, image_params).ok_or(DecodeFailure::ImageDecode)
}
#[cfg(feature = "images")]
Self::Jbig2Decode => {
jbig2::decode(data, params, image_params).ok_or(DecodeFailure::ImageDecode)
}
#[cfg(feature = "images")]
Self::JpxDecode => jpx::decode(data, image_params).ok_or(DecodeFailure::ImageDecode),
#[cfg(not(feature = "images"))]
Self::DctDecode | Self::CcittFaxDecode | Self::Jbig2Decode | Self::JpxDecode => {
warn!("image decoding is not supported (enable the `images` feature)");
Err(DecodeFailure::ImageDecode)
}
_ => Err(DecodeFailure::StreamDecode),
};
if res.is_err() {
warn!("failed to apply filter {}", self.debug_name());
}
res
}
}