1use crate::{Error, Result, Size, Point, Rect, Scalar};
4use std::fmt;
5use std::marker::PhantomData;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[repr(i32)]
10#[allow(non_camel_case_types)]
11pub enum MatType {
12 CV_8U = 0,
14 CV_8S = 1,
16 CV_16U = 2,
18 CV_16S = 3,
20 CV_32S = 4,
22 CV_32F = 5,
24 CV_64F = 6,
26 CV_16F = 7,
28}
29
30impl MatType {
31 pub fn elem_size(&self) -> usize {
33 match self {
34 MatType::CV_8U | MatType::CV_8S => 1,
35 MatType::CV_16U | MatType::CV_16S | MatType::CV_16F => 2,
36 MatType::CV_32S | MatType::CV_32F => 4,
37 MatType::CV_64F => 8,
38 }
39 }
40
41 pub fn is_float(&self) -> bool {
43 matches!(self, MatType::CV_32F | MatType::CV_64F | MatType::CV_16F)
44 }
45
46 pub fn is_signed(&self) -> bool {
48 matches!(self, MatType::CV_8S | MatType::CV_16S | MatType::CV_32S | MatType::CV_32F | MatType::CV_64F | MatType::CV_16F)
49 }
50}
51
52pub struct Mat {
54 data: Vec<u8>,
55 rows: i32,
56 cols: i32,
57 mat_type: MatType,
58 channels: i32,
59}
60
61unsafe impl Send for Mat {}
62unsafe impl Sync for Mat {}
63
64impl Mat {
65 pub fn new() -> Result<Self> {
67 Ok(Mat {
68 data: Vec::new(),
69 rows: 0,
70 cols: 0,
71 mat_type: MatType::CV_8U,
72 channels: 1,
73 })
74 }
75
76 pub fn new_size(size: Size, mat_type: MatType) -> Result<Self> {
78 Self::new_size_with_default(size, mat_type, Scalar::default())
79 }
80
81 pub fn new_size_with_default(size: Size, mat_type: MatType, _default_value: Scalar) -> Result<Self> {
83 let total_size = (size.width * size.height) as usize * mat_type.elem_size();
84 Ok(Mat {
85 data: vec![0u8; total_size],
86 rows: size.height,
87 cols: size.width,
88 mat_type,
89 channels: 1,
90 })
91 }
92
93 pub fn from_slice<T>(data: &[T], rows: i32, cols: i32, mat_type: MatType) -> Result<Self> {
95 let elem_size = mat_type.elem_size();
96 let expected_size = (rows * cols) as usize;
97
98 if data.len() != expected_size {
99 return Err(Error::InvalidArgument(format!(
100 "Data size mismatch: expected {}, got {}",
101 expected_size,
102 data.len()
103 )));
104 }
105
106 let byte_size = expected_size * elem_size;
107 let mut mat_data = vec![0u8; byte_size];
108
109 unsafe {
111 std::ptr::copy_nonoverlapping(
112 data.as_ptr() as *const u8,
113 mat_data.as_mut_ptr(),
114 byte_size,
115 );
116 }
117
118 Ok(Mat {
119 data: mat_data,
120 rows,
121 cols,
122 mat_type,
123 channels: 1,
124 })
125 }
126
127 pub fn rows(&self) -> i32 {
129 self.rows
130 }
131
132 pub fn cols(&self) -> i32 {
134 self.cols
135 }
136
137 pub fn size(&self) -> Size {
139 Size::new(self.cols, self.rows)
140 }
141
142 pub fn mat_type(&self) -> MatType {
144 self.mat_type
145 }
146
147 pub fn channels(&self) -> i32 {
149 self.channels
150 }
151
152 pub fn is_empty(&self) -> bool {
154 self.data.is_empty() || self.rows == 0 || self.cols == 0
155 }
156
157 pub fn roi(&self, rect: Rect) -> Result<Mat> {
159 if rect.x < 0 || rect.y < 0 ||
160 rect.x + rect.width > self.cols ||
161 rect.y + rect.height > self.rows {
162 return Err(Error::InvalidArgument("ROI out of bounds".into()));
163 }
164
165 Ok(Mat {
167 data: Vec::new(), rows: rect.height,
169 cols: rect.width,
170 mat_type: self.mat_type,
171 channels: self.channels,
172 })
173 }
174
175 pub fn clone(&self) -> Result<Mat> {
177 Ok(Mat {
178 data: self.data.clone(),
179 rows: self.rows,
180 cols: self.cols,
181 mat_type: self.mat_type,
182 channels: self.channels,
183 })
184 }
185
186 pub fn copy_to(&self, dst: &mut Mat) -> Result<()> {
188 dst.data = self.data.clone();
189 dst.rows = self.rows;
190 dst.cols = self.cols;
191 dst.mat_type = self.mat_type;
192 dst.channels = self.channels;
193 Ok(())
194 }
195
196 pub fn convert_to(&self, dst: &mut Mat, rtype: MatType, _alpha: f64, _beta: f64) -> Result<()> {
198 dst.data = self.data.clone();
200 dst.rows = self.rows;
201 dst.cols = self.cols;
202 dst.mat_type = rtype;
203 dst.channels = self.channels;
204 Ok(())
205 }
206
207 pub fn data_ptr(&self) -> *const u8 {
209 self.data.as_ptr()
210 }
211
212 pub fn data_ptr_mut(&mut self) -> *mut u8 {
214 self.data.as_mut_ptr()
215 }
216
217 pub fn elem_size(&self) -> usize {
219 self.mat_type.elem_size() * self.channels as usize
220 }
221
222 pub fn total(&self) -> usize {
224 (self.rows * self.cols) as usize
225 }
226}
227
228impl Default for Mat {
229 fn default() -> Self {
230 Self::new().expect("Failed to create default Mat")
231 }
232}
233
234impl fmt::Debug for Mat {
235 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
236 f.debug_struct("Mat")
237 .field("rows", &self.rows)
238 .field("cols", &self.cols)
239 .field("type", &self.mat_type)
240 .field("channels", &self.channels)
241 .field("empty", &self.is_empty())
242 .finish()
243 }
244}
245
246pub trait MatTrait {
248 fn rows(&self) -> i32;
250 fn cols(&self) -> i32;
252 fn size(&self) -> Size;
254 fn mat_type(&self) -> MatType;
256 fn channels(&self) -> i32;
258 fn is_empty(&self) -> bool;
260}
261
262impl MatTrait for Mat {
263 fn rows(&self) -> i32 {
264 self.rows()
265 }
266
267 fn cols(&self) -> i32 {
268 self.cols()
269 }
270
271 fn size(&self) -> Size {
272 self.size()
273 }
274
275 fn mat_type(&self) -> MatType {
276 self.mat_type()
277 }
278
279 fn channels(&self) -> i32 {
280 self.channels()
281 }
282
283 fn is_empty(&self) -> bool {
284 self.is_empty()
285 }
286}
287
288#[cfg(test)]
289mod tests {
290 use super::*;
291
292 #[test]
293 fn test_mat_creation() {
294 let mat = Mat::new().unwrap();
295 assert!(mat.is_empty());
296 }
297
298 #[test]
299 fn test_mat_with_size() {
300 let size = Size::new(640, 480);
301 let mat = Mat::new_size(size, MatType::CV_8U).unwrap();
302 assert_eq!(mat.rows(), 480);
303 assert_eq!(mat.cols(), 640);
304 assert_eq!(mat.mat_type(), MatType::CV_8U);
305 }
306
307 #[test]
308 fn test_mat_type_properties() {
309 assert_eq!(MatType::CV_8U.elem_size(), 1);
310 assert_eq!(MatType::CV_32F.elem_size(), 4);
311 assert!(MatType::CV_32F.is_float());
312 assert!(!MatType::CV_8U.is_float());
313 assert!(MatType::CV_8S.is_signed());
314 assert!(!MatType::CV_8U.is_signed());
315 }
316}