pnm decoding and encoding
Diffstat (limited to 'src/lib.rs')
| -rw-r--r-- | src/lib.rs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..f3cdf62 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,90 @@ +//! crate for decoding/encoding the portable anymap format. +#![allow(incomplete_features)] +#![feature( + test, + generic_const_exprs, + ptr_sub_ptr, + array_chunks, + let_chains, + iter_array_chunks +)] +#![warn( + clippy::missing_const_for_fn, + clippy::suboptimal_flops, + clippy::dbg_macro, + clippy::use_self +)] + +use fimg::{uninit, DynImage, Image}; +pub mod decode; +pub(crate) mod encode; +pub mod pam; +pub mod pbm; +pub mod pgm; +pub mod ppm; +pub use pam::PAM; + +/// Decode any [`pgm`], [`ppm`], [`pbm`], [`pam`] image. +pub fn decode(x: &impl AsRef<[u8]>) -> decode::Result<DynImage<Vec<u8>>> { + let mut x = x.as_ref(); + let magic = decode::magic(&mut x).ok_or(decode::Error::MissingMagic)?; + match magic { + pbm::raw::MAGIC => { + let header = decode::decode_header(&mut x, pbm::raw::MAGIC)?; + Ok(DynImage::Y(pbm::raw::decode_body_into_u8( + x, + uninit::Image::new(header.width, header.height), + )?)) + } + pbm::plain::MAGIC => { + let header = decode::decode_header(&mut x, pbm::plain::MAGIC)?; + Ok(DynImage::Y(pbm::plain::decode_body_into_u8( + x, + uninit::Image::new(header.width, header.height), + )?)) + } + pgm::raw::MAGIC => Ok(DynImage::Y(pgm::raw::decode_wo_magic(x)?)), + pgm::plain::MAGIC => Ok(DynImage::Y(pgm::plain::decode_wo_magic(x)?)), + ppm::raw::MAGIC => Ok(DynImage::Rgb(ppm::raw::decode_wo_magic(x)?)), + ppm::plain::MAGIC => Ok(DynImage::Rgb(ppm::plain::decode_wo_magic(x)?)), + pam::MAGIC => pam::decode_wo_magic(x), + _ => Err(decode::Error::BadMagic(magic)), + } +} + +/// Encodes an image to one of the [`pgm`] or [`ppm`] portable anymap formats. +/// +/// Please note that this will not produce a [`pam`], use [`PAM`] for that. +pub trait Encode { + /// Encodes an image to one of the [`pgm`] or [`ppm`] portable anymap formats. + fn encode(self) -> Vec<u8>; + /// ASCII EDITION. + fn encode_plain(self) -> String; +} + +macro_rules! x { + ($mod:ident) => { + impl<T: AsRef<[u8]>> Encode for Image<T, { $mod::CHANNELS }> { + fn encode(self) -> Vec<u8> { + $mod::raw::encode(self) + } + fn encode_plain(self) -> String { + $mod::plain::encode(self) + } + } + }; + (t $mod:ident, $n:literal) => { + impl<T: AsRef<[u8]>> Encode for Image<T, $n> { + fn encode(self) -> Vec<u8> { + $mod::raw::encode(<Image<Box<[u8]>, { $mod::CHANNELS }>>::from(self.as_ref())) + } + fn encode_plain(self) -> String { + $mod::plain::encode(<Image<Box<[u8]>, { $mod::CHANNELS }>>::from(self.as_ref())) + } + } + }; +} +x![pgm]; +x![t pgm, 2]; +x![ppm]; +x![t ppm, 4]; |