plotters_unstable/element/
image.rs1#[cfg(all(not(target_arch = "wasm32"), feature = "image"))]
2use image::{DynamicImage, GenericImageView};
3
4use super::{Drawable, PointCollection};
5use plotters_backend::{BackendCoord, DrawingBackend, DrawingErrorKind};
6
7use plotters_bitmap::bitmap_pixel::{PixelFormat, RGBPixel};
8
9#[cfg(all(not(target_arch = "wasm32"), feature = "image"))]
10use plotters_bitmap::bitmap_pixel::BGRXPixel;
11
12use plotters_bitmap::BitMapBackend;
13
14use std::borrow::Borrow;
15use std::marker::PhantomData;
16
17enum Buffer<'a> {
18 Owned(Vec<u8>),
19 Borrowed(&'a [u8]),
20 BorrowedMut(&'a mut [u8]),
21}
22
23impl<'a> Borrow<[u8]> for Buffer<'a> {
24 fn borrow(&self) -> &[u8] {
25 self.as_ref()
26 }
27}
28
29impl AsRef<[u8]> for Buffer<'_> {
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
39impl<'a> Buffer<'a> {
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
56pub struct BitMapElement<'a, Coord, P: PixelFormat = RGBPixel> {
58 image: Buffer<'a>,
59 size: (u32, u32),
60 pos: Coord,
61 phantom: PhantomData<P>,
62}
63
64impl<'a, Coord, P: PixelFormat> BitMapElement<'a, Coord, P> {
65 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 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 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 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 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 pub fn move_to(&mut self, pos: Coord) {
157 self.pos = pos;
158 }
159
160 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"))]
168impl<'a, Coord> From<(Coord, DynamicImage)> for BitMapElement<'a, Coord, RGBPixel> {
169 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"))]
182impl<'a, Coord> From<(Coord, DynamicImage)> for BitMapElement<'a, Coord, BGRXPixel> {
183 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
195impl<'a, 'b, Coord> PointCollection<'a, Coord> for &'a BitMapElement<'b, Coord> {
196 type Point = &'a Coord;
197 type IntoIter = std::iter::Once<&'a Coord>;
198 fn point_iter(self) -> Self::IntoIter {
199 std::iter::once(&self.pos)
200 }
201}
202
203impl<'a, Coord, DB: DrawingBackend> Drawable<DB> for BitMapElement<'a, Coord> {
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 return backend.blit_bitmap((x, y), self.size, self.image.as_ref());
213 }
214 Ok(())
215 }
216}