1 #[cfg(all(not(target_arch = "wasm32"), feature = "image"))] 2 use image::{DynamicImage, GenericImageView}; 3 4 use super::{Drawable, PointCollection}; 5 use plotters_backend::{BackendCoord, DrawingBackend, DrawingErrorKind}; 6 7 use plotters_bitmap::bitmap_pixel::{PixelFormat, RGBPixel}; 8 9 #[cfg(all(not(target_arch = "wasm32"), feature = "image"))] 10 use plotters_bitmap::bitmap_pixel::BGRXPixel; 11 12 use plotters_bitmap::BitMapBackend; 13 14 use std::borrow::Borrow; 15 use std::marker::PhantomData; 16 17 enum Buffer<'a> { 18 Owned(Vec<u8>), 19 Borrowed(&'a [u8]), 20 BorrowedMut(&'a mut [u8]), 21 } 22 23 impl<'a> Borrow<[u8]> for Buffer<'a> { borrow(&self) -> &[u8]24 fn borrow(&self) -> &[u8] { 25 self.as_ref() 26 } 27 } 28 29 impl AsRef<[u8]> for Buffer<'_> { as_ref(&self) -> &[u8]30 fn as_ref(&self) -> &[u8] { 31 match self { 32 Buffer::Owned(owned) => owned.as_ref(), 33 Buffer::Borrowed(target) => target, 34 Buffer::BorrowedMut(target) => target, 35 } 36 } 37 } 38 39 impl<'a> Buffer<'a> { to_mut(&mut self) -> &mut [u8]40 fn to_mut(&mut self) -> &mut [u8] { 41 let owned = match self { 42 Buffer::Owned(owned) => return &mut owned[..], 43 Buffer::BorrowedMut(target) => return target, 44 Buffer::Borrowed(target) => { 45 let mut value = vec![]; 46 value.extend_from_slice(target); 47 value 48 } 49 }; 50 51 *self = Buffer::Owned(owned); 52 self.to_mut() 53 } 54 } 55 56 /// The element that contains a bitmap on it 57 pub struct BitMapElement<'a, Coord, P: PixelFormat = RGBPixel> { 58 image: Buffer<'a>, 59 size: (u32, u32), 60 pos: Coord, 61 phantom: PhantomData<P>, 62 } 63 64 impl<'a, Coord, P: PixelFormat> BitMapElement<'a, Coord, P> { 65 /// Create a new empty bitmap element. This can be use as 66 /// the draw and blit pattern. 67 /// 68 /// - `pos`: The left upper coordinate for the element 69 /// - `size`: The size of the bitmap new(pos: Coord, size: (u32, u32)) -> Self70 pub fn new(pos: Coord, size: (u32, u32)) -> Self { 71 Self { 72 image: Buffer::Owned(vec![0; (size.0 * size.1) as usize * P::PIXEL_SIZE]), 73 size, 74 pos, 75 phantom: PhantomData, 76 } 77 } 78 79 /// Create a new bitmap element with an pre-allocated owned buffer, this function will 80 /// take the ownership of the buffer. 81 /// 82 /// - `pos`: The left upper coordinate of the elelent 83 /// - `size`: The size of the bitmap 84 /// - `buf`: The buffer to use 85 /// - **returns**: The newly created image element, if the buffer isn't fit the image 86 /// dimension, this will returns an `None`. with_owned_buffer(pos: Coord, size: (u32, u32), buf: Vec<u8>) -> Option<Self>87 pub fn with_owned_buffer(pos: Coord, size: (u32, u32), buf: Vec<u8>) -> Option<Self> { 88 if buf.len() < (size.0 * size.1) as usize * P::PIXEL_SIZE { 89 return None; 90 } 91 92 Some(Self { 93 image: Buffer::Owned(buf), 94 size, 95 pos, 96 phantom: PhantomData, 97 }) 98 } 99 100 /// Create a new bitmap element with a mut borrow to an existing buffer 101 /// 102 /// - `pos`: The left upper coordinate of the elelent 103 /// - `size`: The size of the bitmap 104 /// - `buf`: The buffer to use 105 /// - **returns**: The newly created image element, if the buffer isn't fit the image 106 /// dimension, this will returns an `None`. with_mut(pos: Coord, size: (u32, u32), buf: &'a mut [u8]) -> Option<Self>107 pub fn with_mut(pos: Coord, size: (u32, u32), buf: &'a mut [u8]) -> Option<Self> { 108 if buf.len() < (size.0 * size.1) as usize * P::PIXEL_SIZE { 109 return None; 110 } 111 112 Some(Self { 113 image: Buffer::BorrowedMut(buf), 114 size, 115 pos, 116 phantom: PhantomData, 117 }) 118 } 119 120 /// Create a new bitmap element with a shared borrowed buffer. This means if we want to modifiy 121 /// the content of the image, the buffer is automatically copied 122 /// 123 /// - `pos`: The left upper coordinate of the elelent 124 /// - `size`: The size of the bitmap 125 /// - `buf`: The buffer to use 126 /// - **returns**: The newly created image element, if the buffer isn't fit the image 127 /// dimension, this will returns an `None`. with_ref(pos: Coord, size: (u32, u32), buf: &'a [u8]) -> Option<Self>128 pub fn with_ref(pos: Coord, size: (u32, u32), buf: &'a [u8]) -> Option<Self> { 129 if buf.len() < (size.0 * size.1) as usize * P::PIXEL_SIZE { 130 return None; 131 } 132 133 Some(Self { 134 image: Buffer::Borrowed(buf), 135 size, 136 pos, 137 phantom: PhantomData, 138 }) 139 } 140 141 /// Copy the existing bitmap element to another location 142 /// 143 /// - `pos`: The new location to copy copy_to<Coord2>(&self, pos: Coord2) -> BitMapElement<Coord2, P>144 pub fn copy_to<Coord2>(&self, pos: Coord2) -> BitMapElement<Coord2, P> { 145 BitMapElement { 146 image: Buffer::Borrowed(self.image.borrow()), 147 size: self.size, 148 pos, 149 phantom: PhantomData, 150 } 151 } 152 153 /// Move the existing bitmap element to a new position 154 /// 155 /// - `pos`: The new position move_to(&mut self, pos: Coord)156 pub fn move_to(&mut self, pos: Coord) { 157 self.pos = pos; 158 } 159 160 /// Make the bitmap element as a bitmap backend, so that we can use 161 /// plotters drawing functionality on the bitmap element as_bitmap_backend(&mut self) -> BitMapBackend<P>162 pub fn as_bitmap_backend(&mut self) -> BitMapBackend<P> { 163 BitMapBackend::with_buffer_and_format(self.image.to_mut(), self.size).unwrap() 164 } 165 } 166 167 #[cfg(all(not(target_arch = "wasm32"), feature = "image"))] 168 impl<'a, Coord> From<(Coord, DynamicImage)> for BitMapElement<'a, Coord, RGBPixel> { from((pos, image): (Coord, DynamicImage)) -> Self169 fn from((pos, image): (Coord, DynamicImage)) -> Self { 170 let (w, h) = image.dimensions(); 171 let rgb_image = image.to_rgb().into_raw(); 172 Self { 173 pos, 174 image: Buffer::Owned(rgb_image), 175 size: (w, h), 176 phantom: PhantomData, 177 } 178 } 179 } 180 181 #[cfg(all(not(target_arch = "wasm32"), feature = "image"))] 182 impl<'a, Coord> From<(Coord, DynamicImage)> for BitMapElement<'a, Coord, BGRXPixel> { from((pos, image): (Coord, DynamicImage)) -> Self183 fn from((pos, image): (Coord, DynamicImage)) -> Self { 184 let (w, h) = image.dimensions(); 185 let rgb_image = image.to_bgra().into_raw(); 186 Self { 187 pos, 188 image: Buffer::Owned(rgb_image), 189 size: (w, h), 190 phantom: PhantomData, 191 } 192 } 193 } 194 195 impl<'a, 'b, Coord> PointCollection<'a, Coord> for &'a BitMapElement<'b, Coord> { 196 type Point = &'a Coord; 197 type IntoIter = std::iter::Once<&'a Coord>; point_iter(self) -> Self::IntoIter198 fn point_iter(self) -> Self::IntoIter { 199 std::iter::once(&self.pos) 200 } 201 } 202 203 impl<'a, Coord, DB: DrawingBackend> Drawable<DB> for BitMapElement<'a, Coord> { draw<I: Iterator<Item = BackendCoord>>( &self, mut points: I, backend: &mut DB, _: (u32, u32), ) -> Result<(), DrawingErrorKind<DB::ErrorType>>204 fn draw<I: Iterator<Item = BackendCoord>>( 205 &self, 206 mut points: I, 207 backend: &mut DB, 208 _: (u32, u32), 209 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> { 210 if let Some((x, y)) = points.next() { 211 // TODO: convert the pixel format when needed 212 return backend.blit_bitmap((x, y), self.size, self.image.as_ref()); 213 } 214 Ok(()) 215 } 216 } 217