pnm decoding and encoding
-rw-r--r--README.md13
-rw-r--r--src/decode.rs2
-rw-r--r--src/lib.rs64
-rw-r--r--src/pam.rs26
-rw-r--r--src/ppm.rs8
-rw-r--r--tdata/fimg-rainbowA.ppm (renamed from tdata/fimgA.ppm)0
-rw-r--r--tdata/fimg-rainbowR.ppm (renamed from tdata/fimgR.ppm)bin913 -> 913 bytes
7 files changed, 96 insertions, 17 deletions
diff --git a/README.md b/README.md
index 6d4d7a5..64a7906 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,14 @@
# PNM
-provides encoders and decoders for the portable anymap formats. \ No newline at end of file
+provides encoders and decoders for the portable anymap formats.
+
+> **Warning** 16 bit images are not supported.
+
+### pnm format depth support table
+
+||[PBM](https://docs.rs/pnm/latest/pnm/pbm/index.html)|[PGM](https://docs.rs/pnm/latest/pnm/pgm/index.html)|[PPM](https://docs.rs/pnm/latest/pnm/ppm/index.html)|[PAM](https://docs.rs/pnm/latest/pnm/pam/index.html)
+|----|--|--|--|--|
+|Y |✅|✅|❎|✅|
+|YA |❎|❎|❎|✅|
+|RGB |❎|❎|✅|✅|
+|RGBA|❎|❎|❎|✅|
diff --git a/src/decode.rs b/src/decode.rs
index 183d2ec..4ca678c 100644
--- a/src/decode.rs
+++ b/src/decode.rs
@@ -86,6 +86,7 @@ macro_rules! dec_fn {
pub(crate) use dec_fn;
/// Header for the older PNM formats. Not applicable to PAM.
+#[derive(Debug, Clone, Copy)]
pub struct Header {
/// Magic number.
pub magic: u8,
@@ -135,6 +136,7 @@ impl std::fmt::Display for Error {
}
}
}
+impl std::error::Error for Error {}
/// Decodes the magic number.
pub fn magic(x: &mut &[u8]) -> Option<u8> {
diff --git a/src/lib.rs b/src/lib.rs
index f3cdf62..6cdd4c7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,13 +1,26 @@
//! crate for decoding/encoding the portable anymap format.
+//!
+//! ### a quick guide to the various functions for everyday use
+//!
+//! - [`decode()`]: your go-to for all PNM image decoding.
+//! If you have a specific format you need to support, use its module directly.
+//! Note that this function reads both plain and raw formats.
+//! - [`encode()`]: this function is a little tricky.
+//! It supports the "older" PNM formats, and, due to their age they do not support the alpha channels existence.
+//! If possible, use [`pam::encode`] instead.
+//! - [`encode_plain`]: The `PAM` format doesnt actually support read-age-by-humans, so this is still useful at times.
+//! Outputs data in decimal digits.
+//!
+//! ### functions in action
+//!
+//! ```
+//! let data = include_bytes!("../tdata/fimg-rainbowR.ppm");
+//! let out = pnm::decode(data).unwrap();
+//!
+//! assert_eq!(pnm::encode(out), data);
+//! ```
#![allow(incomplete_features)]
-#![feature(
- test,
- generic_const_exprs,
- ptr_sub_ptr,
- array_chunks,
- let_chains,
- iter_array_chunks
-)]
+#![feature(ptr_sub_ptr, let_chains, iter_array_chunks)]
#![warn(
clippy::missing_const_for_fn,
clippy::suboptimal_flops,
@@ -55,10 +68,21 @@ pub fn decode(x: &impl AsRef<[u8]>) -> decode::Result<DynImage<Vec<u8>>> {
/// 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 fn encode(x: impl Encode) -> Vec<u8> {
+ x.encode()
+}
+
+/// 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.
+/// ASCII EDITION!
+pub fn encode_plain(x: impl Encode) -> String {
+ x.encode_plain()
+}
+
+#[doc(hidden)]
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;
}
@@ -88,3 +112,23 @@ x![pgm];
x![t pgm, 2];
x![ppm];
x![t ppm, 4];
+
+macro_rules! e {
+ ($dyn:expr, |$image: pat_param| $do:expr) => {
+ match $dyn {
+ DynImage::Y($image) => $do,
+ DynImage::Ya($image) => $do,
+ DynImage::Rgb($image) => $do,
+ DynImage::Rgba($image) => $do,
+ }
+ };
+}
+use e;
+impl<T: AsRef<[u8]>> Encode for DynImage<T> {
+ fn encode(self) -> Vec<u8> {
+ e!(self, |x| encode(x))
+ }
+ fn encode_plain(self) -> String {
+ e!(self, |x| encode_plain(x))
+ }
+}
diff --git a/src/pam.rs b/src/pam.rs
index f55b4b8..d8c1314 100644
--- a/src/pam.rs
+++ b/src/pam.rs
@@ -10,8 +10,20 @@ use fimg::{DynImage, Image};
pub const MAGIC: u8 = 7;
-/// Encode an <code>[Image]<[u8], N></code> to [PAM](https://en.wikipedia.org/wiki/Netpbm#PAM_graphics_format) Raw (binary) Image.
-/// And decode.
+/// Encode this <code>[Image]<[u8], N></code> to a [PAM](https://en.wikipedia.org/wiki/Netpbm#PAM_graphics_format) Raw (binary) Image.
+///
+/// ```
+/// # use pnm::pam;
+/// # use fimg::Image;
+/// let out = pam::encode(
+/// Image::<_, 1>::build(20, 15).buf(&include_bytes!("../tdata/fimg-gray.imgbuf")[..])
+/// );
+/// ```
+pub fn encode(x: impl PAM) -> Vec<u8> {
+ x.encode()
+}
+
+#[doc(hidden)]
pub trait PAM {
/// Encode this image to pam.
fn encode(self) -> Vec<u8>;
@@ -100,6 +112,16 @@ impl<T: AsRef<[u8]>> PAM for Image<T, 4> {
}
}
+impl<T: AsRef<[u8]>> PAM for DynImage<T> {
+ fn encode(self) -> Vec<u8> {
+ super::e!(self, |x| encode(x))
+ }
+
+ unsafe fn encode_into(x: Self, out: *mut u8) -> usize {
+ super::e!(x, |x| PAM::encode_into(x, out))
+ }
+}
+
#[inline]
unsafe fn encode_into<const N: usize>(
(buf, (w, h)): (&[u8], (u32, u32)),
diff --git a/src/ppm.rs b/src/ppm.rs
index 5c62062..f57a3d9 100644
--- a/src/ppm.rs
+++ b/src/ppm.rs
@@ -91,14 +91,14 @@ pub mod plain {
fn test_encode() {
assert_eq!(
encode(Image::build(20, 15).buf(tdata())),
- include_str!("../tdata/fimgA.ppm")
+ include_str!("../tdata/fimg-rainbowA.ppm")
);
}
#[test]
fn test_decode() {
assert_eq!(
- &**decode(include_bytes!("../tdata/fimgA.ppm"))
+ &**decode(include_bytes!("../tdata/fimg-rainbowA.ppm"))
.unwrap()
.buffer(),
tdata()
@@ -163,7 +163,7 @@ pub mod raw {
#[test]
fn test_decode() {
assert_eq!(
- &**decode(include_bytes!("../tdata/fimgR.ppm"))
+ &**decode(include_bytes!("../tdata/fimg-rainbowR.ppm"))
.unwrap()
.buffer(),
tdata()
@@ -174,7 +174,7 @@ pub mod raw {
fn test_encode() {
assert_eq!(
encode(Image::build(20, 15).buf(tdata())),
- include_bytes!("../tdata/fimgR.ppm")
+ include_bytes!("../tdata/fimg-rainbowR.ppm")
);
}
}
diff --git a/tdata/fimgA.ppm b/tdata/fimg-rainbowA.ppm
index fe0ae58..fe0ae58 100644
--- a/tdata/fimgA.ppm
+++ b/tdata/fimg-rainbowA.ppm
diff --git a/tdata/fimgR.ppm b/tdata/fimg-rainbowR.ppm
index 2bf5d88..2bf5d88 100644
--- a/tdata/fimgR.ppm
+++ b/tdata/fimg-rainbowR.ppm
Binary files differ