mod mix;
mod raw;
mod set;
mod sub;
use embedded_graphics::Drawable;
use embedded_graphics::draw_target::{DrawTarget, DrawTargetExt};
use embedded_graphics::geometry::{Dimensions, Point};
use embedded_graphics::image::ImageDrawable;
use embedded_graphics::iterator::raw::RawDataSlice;
use embedded_graphics::pixelcolor::PixelColor;
use embedded_graphics::pixelcolor::raw::BigEndian;
use embedded_graphics::primitives::Rectangle;
use embedded_graphics::transform::Transform;
pub use mix::with_colormap::{WithColormap, WithColormapImage, WithColormapImageMix};
pub use mix::{ImageMix, Mixed};
pub use raw::ImageRaw;
pub use set::ImageSet;
pub use sub::{ImageDrawableExt, SubImage};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Image<T: ImageDrawable> {
image_drawable: T,
offset: Point,
}
pub trait Colors<T> {
fn colors(&self) -> impl IntoIterator<Item = T>;
}
impl<'a, C> Image<ImageRaw<'a, C>>
where
C: PixelColor + From<C::Raw>,
RawDataSlice<'a, C::Raw, BigEndian>: IntoIterator<Item = C::Raw>,
{
pub const NULL: Self = Self {
image_drawable: ImageRaw::new(&[], 0),
offset: Point::zero(),
};
}
impl<T: ImageDrawable> Image<T> {
pub const fn new(image_drawable: T, offset: Point) -> Self {
Self {
image_drawable,
offset,
}
}
pub fn clipped(&self, area: &Rectangle) -> Image<SubImage<'_, T>> {
let x = self.offset.x.saturating_neg();
let y = self.offset.y.saturating_neg();
let offset = Point::new(x, y);
let area = area.translate(offset);
let area = self.image_drawable.bounding_box().intersection(&area);
let image_drawable = self.image_drawable.sub_image(&area);
Image::new(image_drawable, area.translate(self.offset).top_left)
}
}
impl<T: ImageDrawable + Clone> Image<T> {
pub fn add_offset(&self, x: i32, y: i32) -> Self {
let x = self.offset.x.saturating_add(x);
let y = self.offset.y.saturating_add(y);
let offset = Point::new(x, y);
Self::new(self.image_drawable.clone(), offset)
}
pub fn mul_offset(&self, x: i32, y: i32) -> Self {
let x = self.offset.x.saturating_mul(x);
let y = self.offset.y.saturating_mul(y);
let offset = Point::new(x, y);
Self::new(self.image_drawable.clone(), offset)
}
}
impl<T: ImageDrawable + Colors<T::Color>> Colors<T::Color> for Image<T> {
fn colors(&self) -> impl IntoIterator<Item = T::Color> {
self.image_drawable.colors()
}
}
impl<T: ImageDrawable> Dimensions for Image<T> {
fn bounding_box(&self) -> Rectangle {
self.image_drawable.bounding_box().translate(self.offset)
}
}
impl<T: ImageDrawable> Drawable for Image<T> {
type Color = T::Color;
type Output = ();
fn draw<D>(&self, target: &mut D) -> Result<Self::Output, D::Error>
where
D: DrawTarget<Color = Self::Color>,
{
let mut target = target.translated(self.offset);
self.image_drawable.draw(&mut target)
}
}