1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
use crate::coord::Coord;
use crate::drawable::Dimensions;
use crate::drawable::Drawable;
use crate::pixelcolor::PixelColor;
use crate::transform::Transform;
use crate::unsignedcoord::{ToSigned, UnsignedCoord};
use core::marker::PhantomData;
/// Trait implemented by all concrete image types
pub trait ImageType {}
/// An image constructed from a slice
#[derive(Debug)]
pub struct Image<'a, C, T>
where
C: PixelColor,
T: ImageType,
{
/// Image width in pixels
pub(crate) width: u32,
/// Image height in pixels
pub(crate) height: u32,
/// Image data, packed as dictated by image type `T` (`Image1BPP` uses 8 bits per pixel, etc)
pub(crate) imagedata: &'a [u8],
/// Image offset in pixels from screen origin (0,0)
pub offset: Coord,
pixel_type: PhantomData<C>,
image_type: PhantomData<T>,
}
impl<'a, C, T> Image<'a, C, T>
where
C: PixelColor,
T: ImageType,
{
/// Create a new image with given pixel data, width and height
pub fn new(imagedata: &'a [u8], width: u32, height: u32) -> Self {
Self {
width,
height,
imagedata,
offset: Coord::new(0, 0),
pixel_type: PhantomData,
image_type: PhantomData,
}
}
}
impl<'a, C, T> Dimensions for Image<'a, C, T>
where
C: PixelColor,
T: ImageType,
{
fn top_left(&self) -> Coord {
self.offset
}
fn bottom_right(&self) -> Coord {
self.top_left() + self.size().to_signed()
}
fn size(&self) -> UnsignedCoord {
let height = self.height;
let width = self.width;
UnsignedCoord::new(width, height)
}
}
impl<'a, C, T> Drawable for Image<'a, C, T>
where
C: PixelColor,
T: ImageType,
{
}
impl<'a, C, T> Transform for Image<'a, C, T>
where
C: PixelColor,
T: ImageType,
{
/// Translate the image from its current position to a new position by (x, y) pixels, returning
/// a new `Image`. For a mutating transform, see `translate_mut`.
///
/// ```
/// # use embedded_graphics::image::{ Image, Image1BPP };
/// # use embedded_graphics::transform::Transform;
/// # use embedded_graphics::coord::Coord;
/// #
/// // 8px x 1px test image
/// let image: Image1BPP<u8> = Image1BPP::new(&[ 0xff ], 8, 1);
/// let moved = image.translate(Coord::new(25, 30));
///
/// assert_eq!(image.offset, Coord::new(0, 0));
/// assert_eq!(moved.offset, Coord::new(25, 30));
/// ```
fn translate(&self, by: Coord) -> Self {
Self {
offset: self.offset + by,
..*self.clone()
}
}
/// Translate the image from its current position to a new position by (x, y) pixels.
///
/// ```
/// # use embedded_graphics::image::{ Image, Image1BPP };
/// # use embedded_graphics::transform::Transform;
/// # use embedded_graphics::coord::Coord;
/// #
/// let mut image: Image1BPP<u8> = Image1BPP::new(&[ 0xff ], 8, 1);
/// image.translate_mut(Coord::new(25, 30));
///
/// assert_eq!(image.offset, Coord::new(25, 30));
/// ```
fn translate_mut(&mut self, by: Coord) -> &mut Self {
self.offset += by;
self
}
}
/// Iterator over every pixel in the source image
#[derive(Debug)]
pub struct ImageIterator<'a, C: 'a, T>
where
C: PixelColor,
T: ImageType,
{
pub(crate) x: u32,
pub(crate) y: u32,
pub(crate) im: &'a Image<'a, C, T>,
}
impl<'a, C, T> ImageIterator<'a, C, T>
where
C: PixelColor,
T: ImageType,
{
/// Create a new image iterator
pub fn new(image: &'a Image<'a, C, T>) -> Self {
ImageIterator {
im: image,
x: 0,
y: 0,
}
}
}
/// Image trait
pub trait ImageFile<'a>: Dimensions + Sized {
/// Create a new image with given input file
///
/// The input file is expected to be of a particular format (BMP, TGA, etc) and contain file
/// metadata like width/height and pixel data. Because parsing may fail, this returns a
/// `Result<Self, ()>`.
fn new(filedata: &'a [u8]) -> Result<Self, ()>;
/// Get the width in pixels of an image
fn width(&self) -> u32;
/// Get the height in pixels of an image
fn height(&self) -> u32;
}