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