#[cfg(feature = "fmt-farbfeld")]
pub mod farbfeld;
#[cfg(feature = "fmt-jpeg")]
pub mod jpeg;
#[cfg(feature = "fmt-png")]
pub mod png;
#[cfg(feature = "fmt-webp")]
pub mod webp;
use std::fmt;
use std::str::FromStr;
use crate::color::convert::ConvertInto;
use crate::color::Color;
use crate::specialized::{self, No};
#[macro_export]
macro_rules! impl_format {
(name: $name:ty, id: $id:expr, magic: $magic:expr $(,)?) => {
impl $crate::image::Format for $name {
fn id(&self) -> &'static str {
$id
}
fn magic(&self) -> &'static [u8] {
$magic
}
}
};
}
pub trait Format {
fn id(&self) -> &'static str;
fn magic(&self) -> &'static [u8];
fn is_valid_magic(&self, magic: &[u8]) -> bool {
if magic.len() < self.magic().len() {
return false;
}
self.magic()
.iter()
.copied()
.zip(magic.iter().copied())
.all(|(m, n)| m == n || m == b'?')
}
}
pub trait Dimensions {
fn width(&self) -> usize;
fn height(&self) -> usize;
fn dimensions(&self) -> (usize, usize) {
let w = self.width();
let h = self.height();
(w, h)
}
}
pub trait Image<Specialized = No> {
type Pixel: Color;
fn color_get(&self, x: usize, y: usize) -> Self::Pixel;
}
pub trait ImageMut<Specialized = No> {
type Pixel: Color;
fn color_set<C, ColorSpecialized>(&mut self, x: usize, y: usize, color: C)
where
C: ConvertInto<Self::Pixel, ColorSpecialized> + Color;
fn color_set_generic<C>(&mut self, x: usize, y: usize, color: C)
where
C: ConvertInto<Self::Pixel, specialized::No> + Color,
{
self.color_set::<_, specialized::No>(x, y, color)
}
fn pixel_set(&mut self, x: usize, y: usize, color: Self::Pixel) {
self.color_set::<_, specialized::For<Self::Pixel>>(x, y, color)
}
}
#[derive(Debug, Copy, Clone)]
pub enum BuiltInFormat {
#[cfg(feature = "fmt-farbfeld")]
Farbfeld,
#[cfg(feature = "fmt-jpeg")]
Jpeg,
#[cfg(feature = "fmt-png")]
Png,
#[cfg(feature = "fmt-webp")]
Webp,
}
impl FromStr for BuiltInFormat {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
match s {
#[cfg(feature = "fmt-farbfeld")]
"farbfeld" => Ok(Self::Farbfeld),
#[cfg(feature = "fmt-jpeg")]
"jpeg" => Ok(Self::Jpeg),
#[cfg(feature = "fmt-png")]
"png" => Ok(Self::Png),
#[cfg(feature = "fmt-webp")]
"webp" => Ok(Self::Webp),
_ => Err(()),
}
}
}
impl fmt::Display for BuiltInFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
#[cfg(feature = "fmt-farbfeld")]
Self::Farbfeld => write!(f, "farbfeld"),
#[cfg(feature = "fmt-jpeg")]
Self::Jpeg => write!(f, "jpeg"),
#[cfg(feature = "fmt-png")]
Self::Png => write!(f, "png"),
#[cfg(feature = "fmt-webp")]
Self::Webp => write!(f, "webp"),
#[allow(unreachable_patterns)]
_ => Ok(()),
}
}
}
impl BuiltInFormat {
pub fn get(self) -> &'static dyn Format {
match self {
#[cfg(feature = "fmt-farbfeld")]
BuiltInFormat::Farbfeld => &farbfeld::Farbfeld,
#[cfg(feature = "fmt-jpeg")]
BuiltInFormat::Jpeg => &jpeg::Jpeg,
#[cfg(feature = "fmt-png")]
BuiltInFormat::Png => &png::Png,
#[cfg(feature = "fmt-webp")]
BuiltInFormat::Webp => &webp::Webp,
}
}
}
pub fn built_in_formats() -> &'static [(BuiltInFormat, &'static dyn Format)] {
&[
#[cfg(feature = "fmt-farbfeld")]
{
(BuiltInFormat::Farbfeld, &farbfeld::Farbfeld)
},
#[cfg(feature = "fmt-jpeg")]
{
(BuiltInFormat::Jpeg, &jpeg::Jpeg)
},
#[cfg(feature = "fmt-png")]
{
(BuiltInFormat::Png, &png::Png)
},
#[cfg(feature = "fmt-webp")]
{
(BuiltInFormat::Webp, &webp::Webp)
},
]
}
pub fn built_in_formats_iter() -> impl Iterator<Item = (BuiltInFormat, &'static dyn Format)> {
built_in_formats().iter().copied()
}