opencv_core/
mat.rs

1//! Mat - The fundamental OpenCV data structure for images and matrices
2
3use crate::{Error, Result, Size, Point, Rect, Scalar};
4use std::fmt;
5use std::marker::PhantomData;
6
7/// OpenCV Mat data types
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[repr(i32)]
10#[allow(non_camel_case_types)]
11pub enum MatType {
12    /// 8-bit unsigned integer
13    CV_8U = 0,
14    /// 8-bit signed integer
15    CV_8S = 1,
16    /// 16-bit unsigned integer
17    CV_16U = 2,
18    /// 16-bit signed integer
19    CV_16S = 3,
20    /// 32-bit signed integer
21    CV_32S = 4,
22    /// 32-bit floating-point
23    CV_32F = 5,
24    /// 64-bit floating-point
25    CV_64F = 6,
26    /// 16-bit floating-point
27    CV_16F = 7,
28}
29
30impl MatType {
31    /// Get the element size in bytes
32    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    /// Check if the type is floating point
42    pub fn is_float(&self) -> bool {
43        matches!(self, MatType::CV_32F | MatType::CV_64F | MatType::CV_16F)
44    }
45
46    /// Check if the type is signed
47    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
52/// Mat structure - the fundamental data container
53pub 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    /// Create a new empty Mat
66    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    /// Create a Mat with specified dimensions and type
77    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    /// Create a Mat with specified dimensions, type, and default value
82    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    /// Create a Mat from existing data
94    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        // Copy data (simplified - assumes matching types)
110        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    /// Get the number of rows
128    pub fn rows(&self) -> i32 {
129        self.rows
130    }
131
132    /// Get the number of columns
133    pub fn cols(&self) -> i32 {
134        self.cols
135    }
136
137    /// Get the size of the matrix
138    pub fn size(&self) -> Size {
139        Size::new(self.cols, self.rows)
140    }
141
142    /// Get the matrix type
143    pub fn mat_type(&self) -> MatType {
144        self.mat_type
145    }
146
147    /// Get the number of channels
148    pub fn channels(&self) -> i32 {
149        self.channels
150    }
151
152    /// Check if the matrix is empty
153    pub fn is_empty(&self) -> bool {
154        self.data.is_empty() || self.rows == 0 || self.cols == 0
155    }
156
157    /// Get a region of interest (ROI)
158    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        // For now, create a new Mat with the ROI data (simplified)
166        Ok(Mat {
167            data: Vec::new(), // Would copy ROI data here
168            rows: rect.height,
169            cols: rect.width,
170            mat_type: self.mat_type,
171            channels: self.channels,
172        })
173    }
174
175    /// Clone the matrix
176    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    /// Copy data to another matrix
187    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    /// Convert matrix type
197    pub fn convert_to(&self, dst: &mut Mat, rtype: MatType, _alpha: f64, _beta: f64) -> Result<()> {
198        // Simplified conversion - just change type for now
199        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    /// Get raw data pointer
208    pub fn data_ptr(&self) -> *const u8 {
209        self.data.as_ptr()
210    }
211
212    /// Get mutable raw data pointer
213    pub fn data_ptr_mut(&mut self) -> *mut u8 {
214        self.data.as_mut_ptr()
215    }
216
217    /// Get element size in bytes
218    pub fn elem_size(&self) -> usize {
219        self.mat_type.elem_size() * self.channels as usize
220    }
221
222    /// Get total number of elements
223    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
246/// Trait for Mat-like objects
247pub trait MatTrait {
248    /// Get number of rows
249    fn rows(&self) -> i32;
250    /// Get number of columns
251    fn cols(&self) -> i32;
252    /// Get size
253    fn size(&self) -> Size;
254    /// Get matrix type
255    fn mat_type(&self) -> MatType;
256    /// Get number of channels
257    fn channels(&self) -> i32;
258    /// Check if empty
259    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}