use std::ops::{Deref, DerefMut};
use image::{ImageBuffer, ImageFormat, Luma, LumaA, Pixel, Rgb, Rgba};
#[derive(Debug, Hash, PartialEq, Eq)]
pub struct Image<P: Pixel, U: image::GenericImage<Pixel = P>> {
underlying: U,
}
impl<P: Pixel, U: image::GenericImage<Pixel = P>> Image<P, U> {
pub fn capacity(&self) -> usize {
return self.underlying.pixels().count() * <P as Pixel>::CHANNEL_COUNT as usize;
}
}
impl<P: Pixel> Image<P, ImageBuffer<P, Vec<P::Subpixel>>> {
pub fn new(width: u32, height: u32) -> Self {
Self {
underlying: ImageBuffer::new(width, height),
}
}
}
impl<P: Pixel, U: image::GenericImage<Pixel = P>> Deref for Image<P, U> {
type Target = U;
fn deref(&self) -> &Self::Target {
&self.underlying
}
}
impl<P: Pixel, U: image::GenericImage<Pixel = P>> DerefMut for Image<P, U> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.underlying
}
}
impl<P, Container> From<ImageBuffer<P, Container>> for Image<P, ImageBuffer<P, Container>>
where
P: Pixel,
Container: DerefMut<Target = [P::Subpixel]>,
{
fn from(image: ImageBuffer<P, Container>) -> Self {
Self { underlying: image }
}
}
pub trait FromWithFormat<Container>
where
Container: Deref<Target = [u8]>,
{
fn from_with_format(container: Container, format: ImageFormat) -> Self;
}
macro_rules! impl_from_with_format {
($px_type:ident, $channel_type:ty, $to_fn:ident) => {
#[doc = concat!(
r#"Implementation of [`FromWithFormat`](FromWithFormat) for an [`Image`](Image) with a pixel type of [`"#,
stringify!($px_type),
"`](image::",
stringify!($px_type),
"), holding a subpixel type of [`",
stringify!($channel_type),
r#"`]("#
, stringify!($channel_type),
r#") and an underlying [`ImageBuffer`](image::ImageBuffer) buffer that holds `Vec<"#,
stringify!($channel_type),
r#">`'s.
"#)]
impl<Container> FromWithFormat<Container>
for Image<
$px_type<$channel_type>,
ImageBuffer<$px_type<$channel_type>, Vec<$channel_type>>,
>
where
Container: Deref<Target = [u8]>,
{
fn from_with_format(container: Container, format: ImageFormat) -> Self {
let dyn_image = image::load_from_memory_with_format(&container, format).unwrap();
let img = dyn_image.$to_fn();
Self::from(img)
}
}
};
}
impl_from_with_format!(Rgb, u8, into_rgb8);
impl_from_with_format!(Rgb, u16, into_rgb16);
impl_from_with_format!(Rgb, f32, into_rgb32f);
impl_from_with_format!(Rgba, u8, into_rgba8);
impl_from_with_format!(Rgba, u16, into_rgba16);
impl_from_with_format!(Rgba, f32, into_rgba32f);
impl_from_with_format!(Luma, u8, into_luma8);
impl_from_with_format!(Luma, u16, into_luma16);
impl_from_with_format!(LumaA, u8, into_luma_alpha8);
impl_from_with_format!(LumaA, u16, into_luma_alpha16);