opencv_rs_core/
mat_view.rs1use crate::{ImageOpsError, PixelFormat};
4
5pub trait MatView {
7 fn width(&self) -> u32;
9 fn height(&self) -> u32;
11 fn channels(&self) -> u32;
13 fn pixel_format(&self) -> PixelFormat;
15 fn data(&self) -> &[u8];
17}
18
19#[derive(Debug, Clone)]
21pub struct OwnedMatView {
22 width: u32,
23 height: u32,
24 pixel_format: PixelFormat,
25 data: Vec<u8>,
26}
27
28impl OwnedMatView {
29 pub fn new(
32 width: u32,
33 height: u32,
34 pixel_format: PixelFormat,
35 data: Vec<u8>,
36 ) -> Result<Self, ImageOpsError> {
37 let expected = (width as usize) * (height as usize) * (pixel_format.channels() as usize);
38 if data.len() != expected {
39 return Err(ImageOpsError::InvalidParameter(
40 "OwnedMatView: data length does not match width*height*channels",
41 ));
42 }
43 Ok(Self {
44 width,
45 height,
46 pixel_format,
47 data,
48 })
49 }
50
51 pub fn zeros(width: u32, height: u32, pixel_format: PixelFormat) -> Self {
53 let len = (width as usize) * (height as usize) * (pixel_format.channels() as usize);
54 Self {
55 width,
56 height,
57 pixel_format,
58 data: vec![0u8; len],
59 }
60 }
61
62 pub fn into_data(self) -> Vec<u8> {
64 self.data
65 }
66
67 pub fn data_mut(&mut self) -> &mut [u8] {
69 &mut self.data
70 }
71}
72
73impl MatView for OwnedMatView {
74 fn width(&self) -> u32 {
75 self.width
76 }
77 fn height(&self) -> u32 {
78 self.height
79 }
80 fn channels(&self) -> u32 {
81 self.pixel_format.channels()
82 }
83 fn pixel_format(&self) -> PixelFormat {
84 self.pixel_format
85 }
86 fn data(&self) -> &[u8] {
87 &self.data
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn new_accepts_matching_length() {
97 let v = OwnedMatView::new(2, 3, PixelFormat::Mono8, vec![0u8; 6]).unwrap();
98 assert_eq!(v.width(), 2);
99 assert_eq!(v.height(), 3);
100 assert_eq!(v.channels(), 1);
101 assert_eq!(v.pixel_format(), PixelFormat::Mono8);
102 assert_eq!(v.data().len(), 6);
103 }
104
105 #[test]
106 fn new_rejects_mismatched_length() {
107 let err = OwnedMatView::new(2, 3, PixelFormat::Bgr8, vec![0u8; 6]).unwrap_err();
108 assert!(matches!(err, ImageOpsError::InvalidParameter(_)));
109 }
110
111 #[test]
112 fn zeros_allocates_zeroed_buffer() {
113 let v = OwnedMatView::zeros(4, 2, PixelFormat::Bgr8);
114 assert_eq!(v.data().len(), 4 * 2 * 3);
115 assert_eq!(v.channels(), 3);
116 assert_eq!(v.pixel_format(), PixelFormat::Bgr8);
117 assert!(v.data().iter().all(|&b| b == 0));
118 }
119
120 #[test]
121 fn into_data_returns_buffer() {
122 let v = OwnedMatView::new(1, 1, PixelFormat::Mono8, vec![7u8]).unwrap();
123 assert_eq!(v.into_data(), vec![7u8]);
124 }
125
126 #[test]
127 fn data_mut_allows_mutation() {
128 let mut v = OwnedMatView::zeros(1, 1, PixelFormat::Mono8);
129 v.data_mut()[0] = 42;
130 assert_eq!(v.data()[0], 42);
131 }
132}