mod image_drawable_ext;
mod image_raw;
mod sub_image;
pub use embedded_graphics_core::image::{GetPixel, ImageDrawable};
pub use image_drawable_ext::ImageDrawableExt;
pub use image_raw::{ImageRaw, ImageRawBE, ImageRawLE};
pub use sub_image::SubImage;
use crate::{
draw_target::{DrawTarget, DrawTargetExt},
geometry::{Dimensions, OriginDimensions, Point},
primitives::Rectangle,
transform::Transform,
Drawable,
};
use core::fmt::Debug;
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
pub struct Image<'a, T> {
image_drawable: &'a T,
offset: Point,
}
impl<'a, T> Image<'a, T>
where
T: ImageDrawable,
{
pub const fn new(image_drawable: &'a T, position: Point) -> Self {
Self {
image_drawable,
offset: position,
}
}
pub fn with_center(image_drawable: &'a T, center: Point) -> Self {
let offset = Rectangle::with_center(center, image_drawable.size()).top_left;
Self {
image_drawable,
offset,
}
}
}
impl<T> Transform for Image<'_, T> {
fn translate(&self, by: Point) -> Self {
Self {
image_drawable: self.image_drawable,
offset: self.offset + by,
}
}
fn translate_mut(&mut self, by: Point) -> &mut Self {
self.offset += by;
self
}
}
impl<'a, T> Drawable for Image<'a, T>
where
T: ImageDrawable,
{
type Color = T::Color;
type Output = ();
fn draw<D>(&self, display: &mut D) -> Result<Self::Output, D::Error>
where
D: DrawTarget<Color = Self::Color>,
{
self.image_drawable
.draw(&mut display.translated(self.offset))
}
}
impl<'a, T> Dimensions for Image<'a, T>
where
T: OriginDimensions,
{
fn bounding_box(&self) -> Rectangle {
self.image_drawable.bounding_box().translate(self.offset)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{geometry::Size, mock_display::MockDisplay, pixelcolor::BinaryColor};
#[test]
fn negative_top_left() {
let image: ImageRaw<BinaryColor> = ImageRaw::new(&[0xff, 0x00, 0xff, 0x00], 4);
let image = Image::new(&image, Point::zero()).translate(Point::new(-1, -1));
assert_eq!(
image.bounding_box(),
Rectangle::new(Point::new(-1, -1), Size::new(4, 4))
);
}
#[test]
fn dimensions() {
let image: ImageRaw<BinaryColor> = ImageRaw::new(&[0xff, 0x00, 0xFF, 0x00], 4);
let image = Image::new(&image, Point::zero()).translate(Point::new(100, 200));
assert_eq!(
image.bounding_box(),
Rectangle::new(Point::new(100, 200), Size::new(4, 4))
);
}
#[test]
fn position() {
let image_raw: ImageRaw<BinaryColor> = ImageRaw::new(&[0xAA, 0x55, 0xAA, 0x55], 4);
let mut display = MockDisplay::new();
Image::new(&image_raw, Point::new(1, 2))
.draw(&mut display)
.unwrap();
display.assert_pattern(&[
" ", " ", " #.#.", " .#.#", " #.#.", " .#.#", ]);
}
#[test]
fn with_center() {
let image_raw: ImageRaw<BinaryColor> = ImageRaw::new(&[0xAA, 0x55, 0xAA, 0x55], 4);
let mut display = MockDisplay::new();
Image::with_center(&image_raw, Point::new(1, 2))
.draw(&mut display)
.unwrap();
display.assert_pattern(&[
" ", "#.#.", ".#.#", "#.#.", ".#.#", ]);
}
}