use image::{DynamicImage, GenericImageView, ImageBuffer, Rgb};
use super::{Drawable, PointCollection};
use crate::drawing::backend::{BackendCoord, DrawingBackend, DrawingErrorKind};
use crate::drawing::BitMapBackend;
use std::borrow::{Borrow, Cow};
pub struct BitMapElement<'a, Coord> {
image: Cow<'a, Vec<u8>>,
size: (u32, u32),
pos: Coord,
}
impl<'a, Coord> BitMapElement<'a, Coord> {
pub fn new(pos: Coord, size: (u32, u32)) -> Self {
Self {
image: Cow::Owned(vec![0; (size.0 * size.1 * 3) as usize]),
size,
pos,
}
}
pub fn copy_to<Coord2>(&self, pos: Coord2) -> BitMapElement<Coord2> {
BitMapElement {
image: Cow::Borrowed(self.image.borrow()),
size: self.size,
pos,
}
}
pub fn move_to(&mut self, pos: Coord) {
self.pos = pos;
}
#[cfg(feature = "bitmap")]
pub fn as_bitmap_backend(&mut self) -> BitMapBackend {
BitMapBackend::with_buffer(self.image.to_mut(), self.size)
}
}
impl<'a, Coord> From<(Coord, DynamicImage)> for BitMapElement<'a, Coord> {
fn from((pos, image): (Coord, DynamicImage)) -> Self {
let (w, h) = image.dimensions();
let rgb_image = image.to_rgb().into_raw();
Self {
pos,
image: Cow::Owned(rgb_image),
size: (w, h),
}
}
}
impl<'a, 'b, Coord> PointCollection<'a, Coord> for &'a BitMapElement<'b, Coord> {
type Borrow = &'a Coord;
type IntoIter = std::iter::Once<&'a Coord>;
fn point_iter(self) -> Self::IntoIter {
std::iter::once(&self.pos)
}
}
impl<'a, Coord, DB: DrawingBackend> Drawable<DB> for BitMapElement<'a, Coord> {
fn draw<I: Iterator<Item = BackendCoord>>(
&self,
mut points: I,
backend: &mut DB,
_: (u32, u32),
) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
if let Some((x, y)) = points.next() {
return backend.blit_bitmap(
(x, y),
&(ImageBuffer::<Rgb<u8>, &[u8]>::from_raw(
self.size.0,
self.size.1,
&self.image[..],
)
.unwrap()),
);
}
Ok(())
}
}