@@ -2,7 +2,7 @@ use std::convert::TryInto;
2
2
use std:: ffi:: c_void;
3
3
use std:: marker:: PhantomData ;
4
4
use std:: ops:: Deref ;
5
- use std:: { fmt, ptr, slice} ;
5
+ use std:: { fmt, mem , ptr, slice} ;
6
6
7
7
pub use mat_:: * ;
8
8
@@ -97,23 +97,29 @@ fn match_is_continuous(mat: &(impl MatTraitConst + ?Sized)) -> Result<()> {
97
97
}
98
98
}
99
99
100
- fn match_length ( sizes : & [ i32 ] , len : usize ) -> Result < ( ) > {
100
+ fn match_length ( sizes : & [ i32 ] , slice_len : usize , size_mul : usize ) -> Result < ( ) > {
101
101
if sizes. is_empty ( ) {
102
102
return Err ( Error :: new ( core:: StsUnmatchedSizes , "Dimensions must not be empty" ) ) ;
103
103
}
104
- let mut volume : u64 = 1 ;
104
+ let mut expected_len : u64 = 1 ;
105
105
for ( i, size) in sizes. iter ( ) . enumerate ( ) {
106
106
let size =
107
107
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) ;
109
109
}
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 {
112
116
let msg = match sizes {
113
117
[ 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:?}" )
115
122
}
116
- _ => format ! ( "The length of the slice: {data_len} must match the passed dimensions: {sizes:?} exactly" ) ,
117
123
} ;
118
124
return Err ( Error :: new ( core:: StsUnmatchedSizes , msg) ) ;
119
125
}
@@ -165,6 +171,42 @@ impl Mat {
165
171
Self :: new_rows_cols_with_data ( 1 , i32:: try_from ( s. len ( ) ) ?, s)
166
172
}
167
173
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
+
168
210
/// Create a new `Mat` from a mutable single-dimensional slice
169
211
#[ inline]
170
212
pub fn from_slice_mut < T : DataType > ( s : & mut [ T ] ) -> Result < BoxedRefMut < Self > > {
@@ -211,17 +253,36 @@ impl Mat {
211
253
/// Create a new `Mat` that references a single-dimensional slice with custom shape
212
254
#[ inline]
213
255
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 ) ?;
215
257
let m = unsafe {
216
258
Self :: new_rows_cols_with_data_unsafe_def ( rows, cols, T :: opencv_type ( ) , data. as_ptr ( ) . cast :: < c_void > ( ) . cast_mut ( ) )
217
259
} ?;
218
260
Ok ( <BoxedRef < Mat > >:: from ( m) )
219
261
}
220
262
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
222
274
#[ inline]
223
275
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 > ( ) ) ?;
225
286
let m =
226
287
unsafe { Self :: new_rows_cols_with_data_unsafe_def ( rows, cols, T :: opencv_type ( ) , data. as_mut_ptr ( ) . cast :: < c_void > ( ) ) } ?;
227
288
Ok ( <BoxedRefMut < Mat > >:: from ( m) )
@@ -230,31 +291,31 @@ impl Mat {
230
291
/// Create a new `Mat` that references a single-dimensional slice with custom shape
231
292
#[ inline]
232
293
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 ) ?;
234
295
let m = unsafe { Self :: new_size_with_data_unsafe_def ( size, T :: opencv_type ( ) , data. as_ptr ( ) . cast :: < c_void > ( ) . cast_mut ( ) ) } ?;
235
296
Ok ( <BoxedRef < Mat > >:: from ( m) )
236
297
}
237
298
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
239
300
#[ inline]
240
301
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 ) ?;
242
303
let m = unsafe { Self :: new_size_with_data_unsafe_def ( size, T :: opencv_type ( ) , data. as_mut_ptr ( ) . cast :: < c_void > ( ) ) } ?;
243
304
Ok ( <BoxedRefMut < Mat > >:: from ( m) )
244
305
}
245
306
246
307
/// Create a new `Mat` that references a single-dimensional slice with custom shape
247
308
#[ inline]
248
309
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 ) ?;
250
311
let m = unsafe { Self :: new_nd_with_data_unsafe_def ( sizes, T :: opencv_type ( ) , data. as_ptr ( ) . cast :: < c_void > ( ) . cast_mut ( ) ) } ?;
251
312
Ok ( <BoxedRef < Mat > >:: from ( m) )
252
313
}
253
314
254
315
/// Create a new `Mat` that references a single-dimensional slice with custom shape
255
316
#[ inline]
256
317
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 ) ?;
258
319
let m = unsafe { Self :: new_nd_with_data_unsafe_def ( sizes, T :: opencv_type ( ) , data. as_mut_ptr ( ) . cast :: < c_void > ( ) ) } ?;
259
320
Ok ( <BoxedRefMut < Mat > >:: from ( m) )
260
321
}
0 commit comments