xref: /StarryEngine/starry_server/src/base/image.rs (revision bee61dca287acb4b9fd6d747ba3f687aebacab90)
1 use std::{
2     cell::Cell,
3     cmp,
4     fs::File,
5     io::{Seek, SeekFrom, Write},
6     mem, ptr,
7 };
8 
9 use image::GenericImageView;
10 use starry_client::base::{
11     color::Color,
12     renderer::{RenderMode, Renderer},
13 };
14 
15 use crate::core::{SCREEN_HEIGHT, SCREEN_WIDTH};
16 
17 use super::rect::Rect;
18 
19 /// Roi区域中的行数据
20 pub struct ImageRoiRows<'a> {
21     /// Roi矩形区域(相对位置)
22     rect: Rect,
23     /// 矩形宽度
24     w: i32,
25     /// 帧缓冲数据
26     data: &'a [Color],
27     /// 当前行号
28     i: i32,
29 }
30 
31 // 实现迭代器
32 impl<'a> Iterator for ImageRoiRows<'a> {
33     type Item = &'a [Color];
34     fn next(&mut self) -> Option<Self::Item> {
35         if self.i < self.rect.height() {
36             let start = (self.rect.top() + self.i) * self.w + self.rect.left();
37             let end = start + self.rect.width();
38             self.i += 1;
39             Some(&self.data[start as usize..end as usize])
40         } else {
41             None
42         }
43     }
44 }
45 
46 /// Roi区域中的行数据
47 pub struct ImageRoiRowsMut<'a> {
48     /// Roi矩形区域(相对位置)
49     rect: Rect,
50     /// 矩形宽度
51     w: i32,
52     /// 帧缓冲数据
53     data: &'a mut [Color],
54     /// 当前行号
55     i: i32,
56 }
57 
58 // 实现迭代器
59 impl<'a> Iterator for ImageRoiRowsMut<'a> {
60     type Item = &'a mut [Color];
61     fn next(&mut self) -> Option<Self::Item> {
62         if self.i < self.rect.height() {
63             let mut data = mem::take(&mut self.data);
64 
65             // 剔除掉矩形以上的部分
66             if self.i == 0 {
67                 data = data
68                     .split_at_mut(self.rect.top() as usize * self.w as usize)
69                     .1
70             };
71 
72             // 分离当前行和剩下的部分
73             let (row, tail) = data.split_at_mut(self.w as usize);
74             self.data = tail;
75             let start = self.rect.left() as usize;
76             let end = self.rect.left() as usize + self.rect.width() as usize;
77             self.i += 1;
78             Some(&mut row[start..end])
79         } else {
80             None
81         }
82     }
83 }
84 
85 /// 图像中的ROI区域
86 pub struct ImageRoi<'a> {
87     /// ROI矩形区域(相对位置)
88     rect: Rect,
89     /// 矩形区域宽度
90     w: i32,
91     /// 帧缓冲数据
92     data: &'a mut [Color],
93 }
94 
95 // 实现到迭代器的转换
96 impl<'a> IntoIterator for ImageRoi<'a> {
97     type Item = &'a [Color];
98     type IntoIter = ImageRoiRows<'a>;
99 
100     fn into_iter(self) -> Self::IntoIter {
101         let Self { rect, w, data } = self;
102         // 两次切片操作
103         let data =
104             &mut data[rect.top() as usize * w as usize..][..rect.height() as usize * w as usize];
105         ImageRoiRows {
106             rect,
107             w,
108             data,
109             i: 0,
110         }
111     }
112 }
113 
114 impl<'a> ImageRoi<'a> {
115     /// 获得Roi相应的行数据
116     pub fn rows(&'a self) -> ImageRoiRows<'a> {
117         ImageRoiRows {
118             rect: self.rect,
119             w: self.w,
120             data: self.data,
121             i: 0,
122         }
123     }
124 
125     /// 获得Roi相应的行数据
126     pub fn rows_mut(&'a mut self) -> ImageRoiRowsMut<'a> {
127         ImageRoiRowsMut {
128             rect: self.rect,
129             w: self.w,
130             data: self.data,
131             i: 0,
132         }
133     }
134 
135     /// Roi区域颜色混合
136     pub fn blend(&'a mut self, other: &ImageRoi) {
137         for (self_row, other_row) in self.rows_mut().zip(other.rows()) {
138             for (old, new) in self_row.iter_mut().zip(other_row.iter()) {
139                 let alpha = (new.data >> 24) & 0xFF;
140                 if alpha >= 255 {
141                     old.data = new.data;
142                 } else if alpha > 0 {
143                     let n_r = (((new.data >> 16) & 0xFF) * alpha) >> 8;
144                     let n_g = (((new.data >> 8) & 0xFF) * alpha) >> 8;
145                     let n_b = ((new.data & 0xFF) * alpha) >> 8;
146 
147                     let n_alpha = 255 - alpha;
148 
149                     let o_r = (((old.data >> 16) & 0xFF) * n_alpha) >> 8;
150                     let o_g = (((old.data >> 8) & 0xFF) * n_alpha) >> 8;
151                     let o_b = ((old.data & 0xFF) * n_alpha) >> 8;
152 
153                     old.data = ((o_r << 16) | (o_g << 8) | o_b) + ((n_r << 16) | (n_g << 8) | n_b);
154                 }
155             }
156         }
157     }
158 
159     /// Roi区域颜色覆盖
160     pub fn cover(&'a mut self, other: &ImageRoi) {
161         for (self_row, other_row) in self.rows_mut().zip(other.rows()) {
162             let len = cmp::min(self_row.len(), other_row.len());
163             unsafe {
164                 ptr::copy(other_row.as_ptr(), self_row.as_mut_ptr(), len);
165             }
166         }
167     }
168 }
169 
170 /// 包含帧缓冲区的图像
171 pub struct ImageRef<'a> {
172     w: i32,
173     h: i32,
174     data: &'a mut [Color],
175     mode: Cell<RenderMode>,
176 }
177 
178 impl<'a> ImageRef<'a> {
179     /// 根据帧缓冲数据创建新图像
180     pub fn from_data(width: i32, height: i32, data: &'a mut [Color]) -> Self {
181         ImageRef {
182             w: width,
183             h: height,
184             data,
185             mode: Cell::new(RenderMode::Blend),
186         }
187     }
188 
189     /// 获得图像宽度
190     pub fn width(&self) -> i32 {
191         self.w
192     }
193 
194     /// 获得图像高度
195     pub fn height(&self) -> i32 {
196         self.h
197     }
198 
199     /// 根据矩形区域返回相应的Roi
200     pub fn roi(&mut self, rect: &Rect) -> ImageRoi {
201         ImageRoi {
202             rect: *rect,
203             w: self.w,
204             data: &mut self.data,
205         }
206     }
207 }
208 
209 impl<'a> Renderer for ImageRef<'a> {
210     fn width(&self) -> u32 {
211         self.w as u32
212     }
213 
214     fn height(&self) -> u32 {
215         self.h as u32
216     }
217 
218     fn data(&self) -> &[Color] {
219         self.data
220     }
221 
222     fn data_mut(&mut self) -> &mut [Color] {
223         self.data
224     }
225 
226     fn sync(&mut self) -> bool {
227         true
228     }
229 
230     fn mode(&self) -> &Cell<RenderMode> {
231         &self.mode
232     }
233 }
234 
235 /// 包含帧缓冲区的图像
236 #[derive(Clone)]
237 pub struct Image {
238     /// 宽度
239     w: i32,
240     /// 高度
241     h: i32,
242     /// 像素数据
243     data: Box<[Color]>,
244     /// 渲染模式
245     mode: Cell<RenderMode>,
246 }
247 
248 impl Image {
249     /// 创建默认图像
250     pub fn new(width: i32, height: i32) -> Self {
251         Image::from_color(width, height, Color::rgb(0, 0, 0))
252     }
253 
254     /// 创建单一颜色的图像
255     pub fn from_color(width: i32, height: i32, color: Color) -> Self {
256         Image::from_data(
257             width,
258             height,
259             vec![color; (width * height) as usize].into_boxed_slice(),
260         )
261     }
262 
263     /// 根据帧缓冲数据创建新图像
264     pub fn from_data(width: i32, height: i32, data: Box<[Color]>) -> Self {
265         Image {
266             w: width,
267             h: height,
268             data,
269             mode: Cell::new(RenderMode::Blend),
270         }
271     }
272 
273     pub fn from_path_scale(path: &[u8]) -> Option<Self> {
274         if let Ok(mut img) = image::load_from_memory(path) {
275             // let img = img.resize(20, 20, image::imageops::FilterType::Gaussian);
276 
277             let (mut img_width, mut img_heigh) = img.dimensions();
278             if img_width > SCREEN_WIDTH as u32 || img_heigh > SCREEN_HEIGHT as u32 {
279                 img = img.resize(
280                     SCREEN_WIDTH as u32,
281                     SCREEN_HEIGHT as u32,
282                     image::imageops::FilterType::Gaussian,
283                 );
284                 (img_width, img_heigh) = img.dimensions();
285             }
286 
287             let mut image = Image::new(img_width as i32, img_heigh as i32);
288             for y in 0..img_heigh {
289                 for x in 0..img_width as u32 {
290                     let pixel = img.get_pixel(x, y);
291                     let offset = y * img_width + x;
292                     // println!("Cursor pixel print x:{:?} y:{:?} rgba:{:?} {:?} {:?} {:?}", x, y, pixel[0], pixel[1], pixel[2], pixel[3]);
293                     image.data[offset as usize] =
294                         Color::rgba(pixel[0], pixel[1], pixel[2], pixel[3]);
295                 }
296             }
297 
298             // println!(
299             //     "[Info] Image created from path successfully,  width: {:?} height: {:?}",
300             //     img_width, img_heigh
301             // );
302 
303             return Some(image);
304         } else {
305             println!("[Error] Image created from path failed");
306             return None;
307         }
308     }
309 
310     /// 返回图像宽度
311     pub fn width(&self) -> i32 {
312         self.w
313     }
314 
315     /// 返回图像高度
316     pub fn height(&self) -> i32 {
317         self.h
318     }
319 
320     /// 返回图像宽度和高度
321     pub fn dimensions(&self) -> (i32, i32) {
322         (self.w, self.h)
323     }
324 
325     /// # 函数功能
326     /// 根据矩形区域返回相应的Roi
327     ///
328     /// ## 参数值
329     /// - rect: 矩形区域(相对位置)
330     ///
331     /// ## 返回值
332     /// Roi对象
333     pub fn roi(&mut self, rect: &Rect) -> ImageRoi {
334         ImageRoi {
335             rect: *rect,
336             w: self.w,
337             data: &mut self.data,
338         }
339     }
340 
341     /// 展示在桌面中央
342     pub fn show_on_desktop(&self) {
343         let xoffset = (SCREEN_WIDTH as i32 - self.width()) / 2;
344         let yoffset = (SCREEN_HEIGHT as i32 - self.height()) / 2;
345         let mut fb = File::open("/dev/fb0").expect("[Error] Unable to open framebuffer");
346         for y in 0..self.height() {
347             for x in 0..self.width() {
348                 let index: i32 = y * self.width() + x;
349                 let offset = ((y + yoffset) * SCREEN_WIDTH as i32 + x + xoffset) * 4;
350                 let color = &self.data[index as usize];
351                 println!(
352                     "Image show print x:{:?} y:{:?} rgba:{:?} {:?} {:?} {:?}",
353                     x,
354                     y,
355                     color.r(),
356                     color.g(),
357                     color.b(),
358                     color.a()
359                 );
360                 fb.seek(SeekFrom::Start(offset as u64)).expect("error");
361                 fb.write(&self.data[index as usize].to_bgra_bytes())
362                     .expect("error");
363             }
364         }
365     }
366 }
367 
368 impl Renderer for Image {
369     fn width(&self) -> u32 {
370         self.w as u32
371     }
372 
373     fn height(&self) -> u32 {
374         self.h as u32
375     }
376 
377     fn data(&self) -> &[Color] {
378         &self.data
379     }
380 
381     fn data_mut(&mut self) -> &mut [Color] {
382         &mut self.data
383     }
384 
385     fn mode(&self) -> &Cell<RenderMode> {
386         &self.mode
387     }
388 
389     fn sync(&mut self) -> bool {
390         true
391     }
392 }
393