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