chess_corners_core/
imageview.rs1#[derive(Copy, Clone, Debug)]
3pub struct ImageView<'a> {
4 pub data: &'a [u8],
5 pub width: usize,
6 pub height: usize,
7 pub(crate) origin: [i32; 2],
12}
13
14impl<'a> ImageView<'a> {
15 pub fn from_u8_slice(width: usize, height: usize, data: &'a [u8]) -> Option<Self> {
16 if width.checked_mul(height)? != data.len() {
17 return None;
18 }
19 Some(Self {
20 data,
21 width,
22 height,
23 origin: [0, 0],
24 })
25 }
26
27 pub fn with_origin(
28 width: usize,
29 height: usize,
30 data: &'a [u8],
31 origin: [i32; 2],
32 ) -> Option<Self> {
33 Self::from_u8_slice(width, height, data).map(|mut view| {
34 view.origin = origin;
35 view
36 })
37 }
38
39 #[inline]
43 pub fn origin(&self) -> [i32; 2] {
44 self.origin
45 }
46
47 #[inline]
48 pub fn supports_patch(&self, cx: i32, cy: i32, radius: i32) -> bool {
49 if self.width == 0 || self.height == 0 {
50 return false;
51 }
52
53 let gx = cx + self.origin[0];
54 let gy = cy + self.origin[1];
55 let min_x = 0;
56 let min_y = 0;
57 let max_x = self.width as i32 - 1;
58 let max_y = self.height as i32 - 1;
59 gx - radius >= min_x && gy - radius >= min_y && gx + radius <= max_x && gy + radius <= max_y
60 }
61
62 #[inline]
63 pub fn sample(&self, gx: i32, gy: i32) -> f32 {
64 if self.width == 0 || self.height == 0 {
65 return 0.0;
66 }
67 let gx = gx + self.origin[0];
68 let gy = gy + self.origin[1];
69 let lx = gx.clamp(0, self.width.saturating_sub(1) as i32) as usize;
70 let ly = gy.clamp(0, self.height.saturating_sub(1) as i32) as usize;
71 self.data[ly * self.width + lx] as f32
72 }
73
74 #[inline]
78 pub fn sample_bilinear(&self, gx: f32, gy: f32) -> f32 {
79 if self.width == 0 || self.height == 0 {
80 return 0.0;
81 }
82
83 let fx = gx + self.origin[0] as f32;
84 let fy = gy + self.origin[1] as f32;
85
86 let max_x = self.width.saturating_sub(1) as i32;
87 let max_y = self.height.saturating_sub(1) as i32;
88
89 let x0 = (fx.floor() as i32).clamp(0, max_x);
90 let y0 = (fy.floor() as i32).clamp(0, max_y);
91 let x1 = (x0 + 1).clamp(0, max_x);
92 let y1 = (y0 + 1).clamp(0, max_y);
93
94 let tx = (fx - x0 as f32).clamp(0.0, 1.0);
97 let ty = (fy - y0 as f32).clamp(0.0, 1.0);
98
99 let w = self.width;
100 let i00 = self.data[y0 as usize * w + x0 as usize] as f32;
101 let i10 = self.data[y0 as usize * w + x1 as usize] as f32;
102 let i01 = self.data[y1 as usize * w + x0 as usize] as f32;
103 let i11 = self.data[y1 as usize * w + x1 as usize] as f32;
104
105 let a = i00 + (i10 - i00) * tx;
106 let b = i01 + (i11 - i01) * tx;
107 a + (b - a) * ty
108 }
109}