@@ -2,7 +2,7 @@ use std::convert::TryInto;
22use std:: ffi:: c_void;
33use std:: marker:: PhantomData ;
44use std:: ops:: Deref ;
5- use std:: { fmt, ptr, slice} ;
5+ use std:: { fmt, mem , ptr, slice} ;
66
77pub use mat_:: * ;
88
@@ -97,23 +97,29 @@ fn match_is_continuous(mat: &(impl MatTraitConst + ?Sized)) -> Result<()> {
9797 }
9898}
9999
100- fn match_length ( sizes : & [ i32 ] , len : usize ) -> Result < ( ) > {
100+ fn match_length ( sizes : & [ i32 ] , slice_len : usize , size_mul : usize ) -> Result < ( ) > {
101101 if sizes. is_empty ( ) {
102102 return Err ( Error :: new ( core:: StsUnmatchedSizes , "Dimensions must not be empty" ) ) ;
103103 }
104- let mut volume : u64 = 1 ;
104+ let mut expected_len : u64 = 1 ;
105105 for ( i, size) in sizes. iter ( ) . enumerate ( ) {
106106 let size =
107107 u64:: try_from ( * size) . map_err ( |_| Error :: new ( core:: StsOutOfRange , format ! ( "Dimension {i} must not be negative" ) ) ) ?;
108- volume = volume . saturating_mul ( size) ;
108+ expected_len = expected_len . saturating_mul ( size) ;
109109 }
110- let data_len = u64:: try_from ( len) . map_err ( |_| Error :: new ( core:: StsOutOfRange , "Length must fit in u64" ) ) ?;
111- if volume != data_len {
110+ if size_mul > 1 {
111+ // cast is safe because of the `> 1` check above
112+ expected_len = expected_len. saturating_mul ( size_mul as u64 ) ;
113+ }
114+ let slice_len = u64:: try_from ( slice_len) . map_err ( |_| Error :: new ( core:: StsOutOfRange , "Length must fit in u64" ) ) ?;
115+ if expected_len != slice_len {
112116 let msg = match sizes {
113117 [ rows, cols] => {
114- format ! ( "The length of the slice: {data_len} must match the passed row: {rows} and column: {cols} counts exactly" )
118+ format ! ( "The length of the slice: {slice_len} must be: {expected_len} to match the passed row: {rows} and column: {cols} counts" )
119+ }
120+ _ => {
121+ format ! ( "The length of the slice: {slice_len} must be: {expected_len} to match the passed dimensions: {sizes:?}" )
115122 }
116- _ => format ! ( "The length of the slice: {data_len} must match the passed dimensions: {sizes:?} exactly" ) ,
117123 } ;
118124 return Err ( Error :: new ( core:: StsUnmatchedSizes , msg) ) ;
119125 }
@@ -165,6 +171,42 @@ impl Mat {
165171 Self :: new_rows_cols_with_data ( 1 , i32:: try_from ( s. len ( ) ) ?, s)
166172 }
167173
174+ /// Create a new `Mat` from a single-dimensional byte slice
175+ #[ inline]
176+ pub fn from_bytes < T : DataType > ( s : & [ u8 ] ) -> Result < BoxedRef < Self > > {
177+ let rem = s. len ( ) % mem:: size_of :: < T > ( ) ;
178+ if rem != 0 {
179+ return Err ( Error :: new (
180+ core:: StsBadArg ,
181+ format ! (
182+ "Unexpected number of bytes: {} the indicated type, expected multiple of {}" ,
183+ s. len( ) ,
184+ T :: opencv_channels( )
185+ ) ,
186+ ) ) ;
187+ }
188+ let len = s. len ( ) / mem:: size_of :: < T > ( ) ;
189+ Self :: new_rows_cols_with_bytes :: < T > ( 1 , i32:: try_from ( len) ?, s)
190+ }
191+
192+ /// Create a new `Mat` from a mutable single-dimensional byte slice
193+ #[ inline]
194+ pub fn from_bytes_mut < T : DataType > ( s : & mut [ u8 ] ) -> Result < BoxedRefMut < Self > > {
195+ let rem = s. len ( ) % mem:: size_of :: < T > ( ) ;
196+ if rem != 0 {
197+ return Err ( Error :: new (
198+ core:: StsBadArg ,
199+ format ! (
200+ "Unexpected number of bytes: {} the indicated type, expected multiple of {}" ,
201+ s. len( ) ,
202+ T :: opencv_channels( )
203+ ) ,
204+ ) ) ;
205+ }
206+ let len = s. len ( ) / mem:: size_of :: < T > ( ) ;
207+ Self :: new_rows_cols_with_bytes_mut :: < T > ( 1 , i32:: try_from ( len) ?, s)
208+ }
209+
168210 /// Create a new `Mat` from a mutable single-dimensional slice
169211 #[ inline]
170212 pub fn from_slice_mut < T : DataType > ( s : & mut [ T ] ) -> Result < BoxedRefMut < Self > > {
@@ -211,17 +253,36 @@ impl Mat {
211253 /// Create a new `Mat` that references a single-dimensional slice with custom shape
212254 #[ inline]
213255 pub fn new_rows_cols_with_data < T : DataType > ( rows : i32 , cols : i32 , data : & [ T ] ) -> Result < BoxedRef < Self > > {
214- match_length ( & [ rows, cols] , data. len ( ) ) ?;
256+ match_length ( & [ rows, cols] , data. len ( ) , 1 ) ?;
215257 let m = unsafe {
216258 Self :: new_rows_cols_with_data_unsafe_def ( rows, cols, T :: opencv_type ( ) , data. as_ptr ( ) . cast :: < c_void > ( ) . cast_mut ( ) )
217259 } ?;
218260 Ok ( <BoxedRef < Mat > >:: from ( m) )
219261 }
220262
221- /// Create a new `Mat` that references a single-dimensional slice with custom shape
263+ /// Create a new `Mat` that references a single-dimensional byte slice with custom shape
264+ #[ inline]
265+ pub fn new_rows_cols_with_bytes < T : DataType > ( rows : i32 , cols : i32 , data : & [ u8 ] ) -> Result < BoxedRef < Self > > {
266+ match_length ( & [ rows, cols] , data. len ( ) , mem:: size_of :: < T > ( ) ) ?;
267+ let m = unsafe {
268+ Self :: new_rows_cols_with_data_unsafe_def ( rows, cols, T :: opencv_type ( ) , data. as_ptr ( ) . cast :: < c_void > ( ) . cast_mut ( ) )
269+ } ?;
270+ Ok ( <BoxedRef < Mat > >:: from ( m) )
271+ }
272+
273+ /// Create a new mutable `Mat` that references a single-dimensional slice with custom shape
222274 #[ inline]
223275 pub fn new_rows_cols_with_data_mut < T : DataType > ( rows : i32 , cols : i32 , data : & mut [ T ] ) -> Result < BoxedRefMut < Self > > {
224- match_length ( & [ rows, cols] , data. len ( ) ) ?;
276+ match_length ( & [ rows, cols] , data. len ( ) , 1 ) ?;
277+ let m =
278+ unsafe { Self :: new_rows_cols_with_data_unsafe_def ( rows, cols, T :: opencv_type ( ) , data. as_mut_ptr ( ) . cast :: < c_void > ( ) ) } ?;
279+ Ok ( <BoxedRefMut < Mat > >:: from ( m) )
280+ }
281+
282+ /// Create a new mutable `Mat` that references a single-dimensional byte slice with custom shape
283+ #[ inline]
284+ pub fn new_rows_cols_with_bytes_mut < T : DataType > ( rows : i32 , cols : i32 , data : & mut [ u8 ] ) -> Result < BoxedRefMut < Self > > {
285+ match_length ( & [ rows, cols] , data. len ( ) , mem:: size_of :: < T > ( ) ) ?;
225286 let m =
226287 unsafe { Self :: new_rows_cols_with_data_unsafe_def ( rows, cols, T :: opencv_type ( ) , data. as_mut_ptr ( ) . cast :: < c_void > ( ) ) } ?;
227288 Ok ( <BoxedRefMut < Mat > >:: from ( m) )
@@ -230,31 +291,31 @@ impl Mat {
230291 /// Create a new `Mat` that references a single-dimensional slice with custom shape
231292 #[ inline]
232293 pub fn new_size_with_data < T : DataType > ( size : Size , data : & [ T ] ) -> Result < BoxedRef < Self > > {
233- match_length ( & [ size. width , size. height ] , data. len ( ) ) ?;
294+ match_length ( & [ size. width , size. height ] , data. len ( ) , 1 ) ?;
234295 let m = unsafe { Self :: new_size_with_data_unsafe_def ( size, T :: opencv_type ( ) , data. as_ptr ( ) . cast :: < c_void > ( ) . cast_mut ( ) ) } ?;
235296 Ok ( <BoxedRef < Mat > >:: from ( m) )
236297 }
237298
238- /// Create a new `Mat` that references a single-dimensional slice with custom shape
299+ /// Create a new mutable `Mat` that references a single-dimensional slice with custom shape
239300 #[ inline]
240301 pub fn new_size_with_data_mut < T : DataType > ( size : Size , data : & mut [ T ] ) -> Result < BoxedRefMut < Self > > {
241- match_length ( & [ size. width , size. height ] , data. len ( ) ) ?;
302+ match_length ( & [ size. width , size. height ] , data. len ( ) , 1 ) ?;
242303 let m = unsafe { Self :: new_size_with_data_unsafe_def ( size, T :: opencv_type ( ) , data. as_mut_ptr ( ) . cast :: < c_void > ( ) ) } ?;
243304 Ok ( <BoxedRefMut < Mat > >:: from ( m) )
244305 }
245306
246307 /// Create a new `Mat` that references a single-dimensional slice with custom shape
247308 #[ inline]
248309 pub fn new_nd_with_data < ' data , T : DataType > ( sizes : & [ i32 ] , data : & ' data [ T ] ) -> Result < BoxedRef < ' data , Self > > {
249- match_length ( sizes, data. len ( ) ) ?;
310+ match_length ( sizes, data. len ( ) , 1 ) ?;
250311 let m = unsafe { Self :: new_nd_with_data_unsafe_def ( sizes, T :: opencv_type ( ) , data. as_ptr ( ) . cast :: < c_void > ( ) . cast_mut ( ) ) } ?;
251312 Ok ( <BoxedRef < Mat > >:: from ( m) )
252313 }
253314
254315 /// Create a new `Mat` that references a single-dimensional slice with custom shape
255316 #[ inline]
256317 pub fn new_nd_with_data_mut < ' data , T : DataType > ( sizes : & [ i32 ] , data : & ' data mut [ T ] ) -> Result < BoxedRefMut < ' data , Self > > {
257- match_length ( sizes, data. len ( ) ) ?;
318+ match_length ( sizes, data. len ( ) , 1 ) ?;
258319 let m = unsafe { Self :: new_nd_with_data_unsafe_def ( sizes, T :: opencv_type ( ) , data. as_mut_ptr ( ) . cast :: < c_void > ( ) ) } ?;
259320 Ok ( <BoxedRefMut < Mat > >:: from ( m) )
260321 }
0 commit comments