1use std::convert::TryInto;
2use std::ffi::c_void;
3use std::marker::PhantomData;
4use std::ops::{Deref, DerefMut};
5use std::{fmt, mem, ptr, slice};
6
7pub use mat_::*;
8
9use crate::boxed_ref::{BoxedRef, BoxedRefMut};
10use crate::core::{MatConstIterator, MatExpr, MatSize, MatStep, Point, Rect, Scalar, Size, UMat};
11use crate::manual::core::DataType;
12use crate::prelude::*;
13use crate::{core, input_output_array, input_output_array_vector, Error, Result};
14
15mod mat_;
16
17#[inline(always)]
18unsafe fn convert_ptr<'r, T>(r: *const u8) -> &'r T {
20 unsafe { &*(r.cast::<T>()) }
21}
22
23#[inline(always)]
24unsafe fn convert_ptr_mut<'r, T>(r: *mut u8) -> &'r mut T {
26 unsafe { &mut *(r.cast::<T>()) }
27}
28
29trait MatMatcher {
30 fn match_indices(&self, idx: &[i32]) -> Result<()>;
31 fn match_total(&self, idx: i32) -> Result<()>;
32 fn match_max_dims(&self, max_dims: i32) -> Result<()>;
33 fn match_is_continuous(&self) -> Result<()>;
34}
35
36impl<T: MatTraitConst + ?Sized> MatMatcher for T {
37 fn match_indices(&self, idx: &[i32]) -> Result<()> {
38 let mat_size = self.mat_size();
39 let size = &*mat_size;
40 if size.len() != idx.len() {
41 return Err(Error::new(
42 core::StsUnmatchedSizes,
43 format!(
44 "Amount of Mat dimensions: {} doesn't match the amount of requested indices: {}",
45 size.len(),
46 idx.len()
47 ),
48 ));
49 }
50 if let Some((out_idx, (out_idx_val, out_size))) = idx
51 .iter()
52 .zip(size)
53 .enumerate()
54 .find(|(_, (idx_val, &size))| !(0..size).contains(idx_val))
55 {
56 Err(Error::new(
57 core::StsOutOfRange,
58 format!("Index: {out_idx_val} along dimension: {out_idx} out of bounds 0..{out_size}"),
59 ))
60 } else {
61 Ok(())
62 }
63 }
64
65 #[inline]
66 fn match_total(&self, idx: i32) -> Result<()> {
67 let size = self.total();
68 if 0 <= idx && (idx as usize) < size {
70 Ok(())
71 } else {
72 Err(Error::new(
73 core::StsOutOfRange,
74 format!("Index: {idx} out of bounds: 0..{size}"),
75 ))
76 }
77 }
78
79 #[inline]
80 fn match_max_dims(&self, max_dims: i32) -> Result<()> {
81 let dims = self.dims();
82 if (0..=max_dims).contains(&dims) {
84 Ok(())
85 } else {
86 Err(Error::new(
87 core::StsOutOfRange,
88 format!("Mat contains too many dimensions: {dims}, maximum for this operation: {max_dims}"),
89 ))
90 }
91 }
92
93 #[inline]
94 fn match_is_continuous(&self) -> Result<()> {
95 if self.is_continuous() {
96 Ok(())
97 } else {
98 Err(Error::new(
99 core::StsUnmatchedSizes,
100 "Mat is not continuous, operation is not applicable",
101 ))
102 }
103 }
104}
105
106#[inline]
107fn match_format<T: DataType>(mat_type: i32) -> Result<()> {
108 let out_type = T::opencv_type();
109 if mat_type == out_type {
110 Ok(())
111 } else {
112 let mat_type = core::type_to_string(mat_type)?;
113 let out_type = core::type_to_string(out_type)?;
114 Err(Error::new(
115 core::StsUnmatchedFormats,
116 format!("Mat type is: {mat_type}, but requested type is: {out_type}"),
117 ))
118 }
119}
120
121fn match_length(sizes: &[i32], slice_len: usize, size_mul: usize) -> Result<()> {
122 let mut expected_len: u64 = 1;
123 for (i, size) in sizes.iter().enumerate() {
124 let size =
125 u64::try_from(*size).map_err(|_| Error::new(core::StsOutOfRange, format!("Dimension {i} must not be negative")))?;
126 expected_len = expected_len.saturating_mul(size);
127 }
128 if size_mul > 1 {
129 expected_len = expected_len.saturating_mul(
130 u64::try_from(size_mul).map_err(|_| Error::new(core::StsOutOfRange, "Size multiplier must fit in u64"))?,
131 );
132 }
133 let slice_len = u64::try_from(slice_len).map_err(|_| Error::new(core::StsOutOfRange, "Length must fit in u64"))?;
134 if expected_len != slice_len {
135 let msg = match sizes {
136 [rows, cols] => {
137 format!("The length of the slice: {slice_len} must be: {expected_len} to match the passed row: {rows} and column: {cols} counts")
138 }
139 _ => {
140 format!("The length of the slice: {slice_len} must be: {expected_len} to match the passed dimensions: {sizes:?}")
141 }
142 };
143 return Err(Error::new(core::StsUnmatchedSizes, msg));
144 }
145 Ok(())
146}
147
148#[inline(always)]
150unsafe fn data_at_idx<T: DataType>(mat: &(impl MatTraitConst + ?Sized), i0: usize) -> *const T {
151 let size = mat.mat_size();
152 let size = &*size;
153 let data = mat.data();
154 if size.len() <= 1 || mat.is_continuous() || size[0] == 1 {
155 unsafe { data.cast::<T>().add(i0) }
156 } else if size[1] == 1 {
157 unsafe { data.add(mat.mat_step()[0] * i0) }.cast::<T>()
158 } else {
159 let cols = usize::try_from(size[1]).unwrap_or(1);
160 let i = i0 / cols;
161 let j = i0 - i * cols;
162 unsafe { data.add(mat.mat_step()[0] * i).cast::<T>().add(j) }
163 }
164}
165
166#[inline]
167fn row_count_i32(row_count: usize) -> Result<i32> {
168 i32::try_from(row_count).map_err(|_| Error::new(core::StsBadArg, format!("Row count: {row_count} is too high")))
169}
170
171#[inline]
172fn col_count_i32(col_count: usize) -> Result<i32> {
173 i32::try_from(col_count).map_err(|_| Error::new(core::StsBadArg, format!("Column count: {col_count} is too high")))
174}
175
176impl Mat {
177 pub fn from_exact_iter<T: DataType>(s: impl ExactSizeIterator<Item = T>) -> Result<Self> {
179 let mut out = unsafe { Self::new_rows_cols(1, col_count_i32(s.len())?, T::opencv_type()) }?;
180 for (i, x) in s.enumerate() {
181 let i = i as i32;
183 unsafe { ptr::write(out.at_unchecked_mut::<T>(i), x) };
184 }
185 Ok(out)
186 }
187
188 #[inline]
190 pub fn from_slice<T: DataType>(s: &[T]) -> Result<BoxedRef<'_, Self>> {
191 Self::new_rows_cols_with_data(1, i32::try_from(s.len())?, s)
192 }
193
194 #[inline]
196 pub fn from_bytes<T: DataType>(s: &[u8]) -> Result<BoxedRef<'_, Self>> {
197 let rem = s.len() % mem::size_of::<T>();
198 if rem != 0 {
199 return Err(Error::new(
200 core::StsBadArg,
201 format!(
202 "Unexpected number of bytes: {}, expected multiple of: {} based on the indicated type",
203 s.len(),
204 mem::size_of::<T>()
205 ),
206 ));
207 }
208 let len = s.len() / mem::size_of::<T>();
209 Self::new_rows_cols_with_bytes::<T>(1, i32::try_from(len)?, s)
210 }
211
212 #[inline]
214 pub fn from_bytes_mut<T: DataType>(s: &mut [u8]) -> Result<BoxedRefMut<'_, Self>> {
215 let rem = s.len() % mem::size_of::<T>();
216 if rem != 0 {
217 return Err(Error::new(
218 core::StsBadArg,
219 format!(
220 "Unexpected number of bytes: {}, expected multiple of: {} based on the indicated type",
221 s.len(),
222 mem::size_of::<T>()
223 ),
224 ));
225 }
226 let len = s.len() / mem::size_of::<T>();
227 Self::new_rows_cols_with_bytes_mut::<T>(1, i32::try_from(len)?, s)
228 }
229
230 #[inline]
232 pub fn from_slice_mut<T: DataType>(s: &mut [T]) -> Result<BoxedRefMut<'_, Self>> {
233 Self::new_rows_cols_with_data_mut(1, i32::try_from(s.len())?, s)
234 }
235
236 pub fn from_slice_2d<T: DataType>(s: &[impl AsRef<[T]>]) -> Result<Self> {
240 let col_count = if let Some(first_row) = s.first() {
241 col_count_i32(first_row.as_ref().len())?
242 } else {
243 0
244 };
245 let row_count = if col_count > 0 {
246 row_count_i32(s.len())?
247 } else {
248 0
249 };
250 let mut out = Self::new_rows_cols_with_default(row_count, col_count, T::opencv_type(), Scalar::all(0.))?;
251 if row_count > 0 && col_count > 0 {
252 for (row_n, row) in s.iter().enumerate() {
253 let row_n = row_n as i32;
255 let trg = out.at_row_mut(row_n)?;
256 let src = row.as_ref();
257 if trg.len() != src.len() {
258 return Err(Error::new(
259 core::StsUnmatchedSizes,
260 format!(
261 "Unexpected number of items: {} in a row index: {row_n}, expected: {}",
262 src.len(),
263 trg.len(),
264 ),
265 ));
266 }
267 trg.copy_from_slice(src);
268 }
269 }
270 Ok(out)
271 }
272
273 #[inline]
275 pub fn new_rows_cols_with_data<T: DataType>(rows: i32, cols: i32, data: &[T]) -> Result<BoxedRef<'_, Self>> {
276 match_length(&[rows, cols], data.len(), 1)?;
277 let m = unsafe {
278 Self::new_rows_cols_with_data_unsafe_def(rows, cols, T::opencv_type(), data.as_ptr().cast::<c_void>().cast_mut())
279 }?;
280 Ok(<BoxedRef<Mat>>::from(m))
281 }
282
283 #[inline]
285 pub fn new_rows_cols_with_bytes<T: DataType>(rows: i32, cols: i32, data: &[u8]) -> Result<BoxedRef<'_, Self>> {
286 match_length(&[rows, cols], data.len(), mem::size_of::<T>())?;
287 let m = unsafe {
288 Self::new_rows_cols_with_data_unsafe_def(rows, cols, T::opencv_type(), data.as_ptr().cast::<c_void>().cast_mut())
289 }?;
290 Ok(<BoxedRef<Mat>>::from(m))
291 }
292
293 #[inline]
295 pub fn new_rows_cols_with_data_mut<T: DataType>(rows: i32, cols: i32, data: &mut [T]) -> Result<BoxedRefMut<'_, Self>> {
296 match_length(&[rows, cols], data.len(), 1)?;
297 let m =
298 unsafe { Self::new_rows_cols_with_data_unsafe_def(rows, cols, T::opencv_type(), data.as_mut_ptr().cast::<c_void>()) }?;
299 Ok(<BoxedRefMut<Mat>>::from(m))
300 }
301
302 #[inline]
304 pub fn new_rows_cols_with_bytes_mut<T: DataType>(rows: i32, cols: i32, data: &mut [u8]) -> Result<BoxedRefMut<'_, Self>> {
305 match_length(&[rows, cols], data.len(), mem::size_of::<T>())?;
306 let m =
307 unsafe { Self::new_rows_cols_with_data_unsafe_def(rows, cols, T::opencv_type(), data.as_mut_ptr().cast::<c_void>()) }?;
308 Ok(<BoxedRefMut<Mat>>::from(m))
309 }
310
311 #[inline]
313 pub fn new_size_with_data<T: DataType>(size: Size, data: &[T]) -> Result<BoxedRef<'_, Self>> {
314 match_length(&[size.width, size.height], data.len(), 1)?;
315 let m = unsafe { Self::new_size_with_data_unsafe_def(size, T::opencv_type(), data.as_ptr().cast::<c_void>().cast_mut()) }?;
316 Ok(<BoxedRef<Mat>>::from(m))
317 }
318
319 #[inline]
321 pub fn new_size_with_data_mut<T: DataType>(size: Size, data: &mut [T]) -> Result<BoxedRefMut<'_, Self>> {
322 match_length(&[size.width, size.height], data.len(), 1)?;
323 let m = unsafe { Self::new_size_with_data_unsafe_def(size, T::opencv_type(), data.as_mut_ptr().cast::<c_void>()) }?;
324 Ok(<BoxedRefMut<Mat>>::from(m))
325 }
326
327 #[inline]
329 pub fn new_nd_with_data<'data, T: DataType>(sizes: &[i32], data: &'data [T]) -> Result<BoxedRef<'data, Self>> {
330 match_length(sizes, data.len(), 1)?;
331 let m = unsafe { Self::new_nd_with_data_unsafe_def(sizes, T::opencv_type(), data.as_ptr().cast::<c_void>().cast_mut()) }?;
332 Ok(<BoxedRef<Mat>>::from(m))
333 }
334
335 #[inline]
337 pub fn new_nd_with_data_mut<'data, T: DataType>(sizes: &[i32], data: &'data mut [T]) -> Result<BoxedRefMut<'data, Self>> {
338 match_length(sizes, data.len(), 1)?;
339 let m = unsafe { Self::new_nd_with_data_unsafe_def(sizes, T::opencv_type(), data.as_mut_ptr().cast::<c_void>()) }?;
340 Ok(<BoxedRefMut<Mat>>::from(m))
341 }
342
343 pub fn roi_2_mut<MAT: MatTrait>(m: &mut MAT, roi1: Rect, roi2: Rect) -> Result<(BoxedRefMut<'_, Mat>, BoxedRefMut<'_, Mat>)> {
345 if (roi1 & roi2).empty() {
346 let m2 = unsafe { (m as *mut MAT).as_mut().expect("Can't fail") };
348 let out1 = Mat::roi_mut(m, roi1)?;
349 let out2 = Mat::roi_mut(m2, roi2)?;
350 Ok((out1, out2))
351 } else {
352 Err(Error::new(core::StsBadArg, "ROIs must not intersect"))
353 }
354 }
355}
356
357pub struct MatIter<'m, T> {
358 iter: Option<MatConstIterator>,
359 _d: PhantomData<&'m T>,
360}
361
362impl<T: DataType> MatIter<'_, T> {
363 pub fn new(iter: MatConstIterator) -> Result<Self> {
364 match_format::<T>(iter.typ())?;
365 Ok(Self {
366 iter: Some(iter),
367 _d: PhantomData,
368 })
369 }
370}
371
372impl<T: DataType> Iterator for MatIter<'_, T> {
373 type Item = (Point, T);
374
375 fn next(&mut self) -> Option<Self::Item> {
376 self.iter.as_mut().and_then(|iter| {
377 if iter.has_elements() {
378 let cur = *unsafe { convert_ptr(iter.ptr()) };
380 let pos = iter.pos().ok()?;
381 iter.seek(1, true).ok()?;
382 Some((pos, cur))
383 } else {
384 None
385 }
386 })
387 }
388}
389
390pub struct MatIterMut<'m, T> {
391 iter: Option<MatConstIterator>,
392 _d: PhantomData<&'m mut T>,
393}
394
395impl<T: DataType> MatIterMut<'_, T> {
396 pub fn new(iter: MatConstIterator) -> Result<Self> {
397 match_format::<T>(iter.typ())?;
398 Ok(Self {
399 iter: Some(iter),
400 _d: PhantomData,
401 })
402 }
403}
404
405impl<'m, T: DataType> Iterator for MatIterMut<'m, T> {
406 type Item = (Point, &'m mut T);
407
408 fn next(&mut self) -> Option<Self::Item> {
409 self.iter.as_mut().and_then(|iter| {
410 if iter.has_elements() {
411 let cur = unsafe { convert_ptr_mut(iter.ptr().cast_mut()) };
413 let pos = iter.pos().ok()?;
414 iter.seek(1, true).ok()?;
415 Some((pos, cur))
416 } else {
417 None
418 }
419 })
420 }
421}
422
423pub(crate) mod mat_forward {
424 use super::*;
425
426 #[inline]
427 pub fn at<T: DataType>(mat: &(impl MatTraitConst + ?Sized), i0: i32) -> Result<&T> {
428 match_format::<T>(mat.typ())
429 .and_then(|_| mat.match_total(i0))
430 .and_then(|_| mat.match_max_dims(2))
431 .map(|_| unsafe { mat.at_unchecked(i0) })
432 }
433
434 #[inline]
435 pub fn at_def<T: DataType>(mat: &(impl MatTraitConst + ?Sized)) -> Result<&T> {
436 at(mat, 0)
437 }
438
439 #[inline]
440 pub fn at_mut<T: DataType>(mat: &mut (impl MatTrait + ?Sized), i0: i32) -> Result<&mut T> {
441 match_format::<T>(mat.typ()).and_then(|_| mat.match_total(i0))?;
442 Ok(unsafe { mat.at_unchecked_mut(i0) })
443 }
444
445 #[inline]
446 pub fn at_mut_def<T: DataType>(mat: &mut (impl MatTrait + ?Sized)) -> Result<&mut T> {
447 at_mut(mat, 0)
448 }
449
450 #[inline]
451 pub fn at_2d<T: DataType>(mat: &(impl MatTraitConst + ?Sized), row: i32, col: i32) -> Result<&T> {
452 match_format::<T>(mat.typ())
453 .and_then(|_| mat.match_indices(&[row, col]))
454 .and_then(|_| unsafe { mat.at_2d_unchecked(row, col) })
455 }
456
457 #[inline]
458 pub fn at_2d_mut<T: DataType>(mat: &mut (impl MatTrait + ?Sized), row: i32, col: i32) -> Result<&mut T> {
459 match_format::<T>(mat.typ()).and_then(|_| mat.match_indices(&[row, col]))?;
460 unsafe { mat.at_2d_unchecked_mut(row, col) }
461 }
462
463 #[inline]
464 pub fn at_pt<T: DataType>(mat: &(impl MatTraitConst + ?Sized), pt: Point) -> Result<&T> {
465 at_2d(mat, pt.y, pt.x)
466 }
467
468 #[inline]
469 pub fn at_pt_mut<T: DataType>(mat: &mut (impl MatTrait + ?Sized), pt: Point) -> Result<&mut T> {
470 at_2d_mut(mat, pt.y, pt.x)
471 }
472
473 #[inline]
474 pub fn at_3d<T: DataType>(mat: &(impl MatTraitConst + ?Sized), i0: i32, i1: i32, i2: i32) -> Result<&T> {
475 match_format::<T>(mat.typ())
476 .and_then(|_| mat.match_indices(&[i0, i1, i2]))
477 .and_then(|_| unsafe { mat.at_3d_unchecked(i0, i1, i2) })
478 }
479
480 #[inline]
481 pub fn at_3d_mut<T: DataType>(mat: &mut (impl MatTrait + ?Sized), i0: i32, i1: i32, i2: i32) -> Result<&mut T> {
482 match_format::<T>(mat.typ()).and_then(|_| mat.match_indices(&[i0, i1, i2]))?;
483 unsafe { mat.at_3d_unchecked_mut(i0, i1, i2) }
484 }
485
486 #[inline]
487 pub fn at_nd<'s, T: DataType>(mat: &'s (impl MatTraitConst + ?Sized), idx: &[i32]) -> Result<&'s T> {
488 match_format::<T>(mat.typ())
489 .and_then(|_| mat.match_indices(idx))
490 .and_then(|_| unsafe { mat.at_nd_unchecked(idx) })
491 }
492
493 #[inline]
494 pub fn at_nd_mut<'s, T: DataType>(mat: &'s mut (impl MatTrait + ?Sized), idx: &[i32]) -> Result<&'s mut T> {
495 match_format::<T>(mat.typ()).and_then(|_| mat.match_indices(idx))?;
496 unsafe { mat.at_nd_unchecked_mut(idx) }
497 }
498}
499
500pub trait MatTraitConstManual: MatTraitConst {
501 #[inline]
506 unsafe fn at_unchecked<T: DataType>(&self, i0: i32) -> &T {
507 unsafe { &*data_at_idx::<T>(self, i0 as usize) }
508 }
509
510 #[inline]
514 unsafe fn at_2d_unchecked<T: DataType>(&self, row: i32, col: i32) -> Result<&T> {
515 self.ptr_2d(row, col).map(|ptr| unsafe { convert_ptr(ptr) })
516 }
517
518 #[inline]
522 unsafe fn at_pt_unchecked<T: DataType>(&self, pt: Point) -> Result<&T> {
523 unsafe { self.at_2d_unchecked(pt.y, pt.x) }
524 }
525
526 #[inline]
530 unsafe fn at_3d_unchecked<T: DataType>(&self, i0: i32, i1: i32, i2: i32) -> Result<&T> {
531 self.ptr_3d(i0, i1, i2).map(|ptr| unsafe { convert_ptr(ptr) })
532 }
533
534 #[inline]
538 unsafe fn at_nd_unchecked<T: DataType>(&self, idx: &[i32]) -> Result<&T> {
539 self.ptr_nd(idx).map(|ptr| unsafe { convert_ptr(ptr) })
540 }
541
542 #[inline]
544 fn at_row<T: DataType>(&self, row: i32) -> Result<&[T]> {
545 match_format::<T>(self.typ())
546 .and_then(|_| self.match_indices(&[row, 0]))
547 .and_then(|_| unsafe { self.at_row_unchecked(row) })
548 }
549
550 #[inline]
554 unsafe fn at_row_unchecked<T: DataType>(&self, row: i32) -> Result<&[T]> {
555 let width = self.size()?.width as usize;
557 self.ptr(row).map(|row| {
558 if row.is_null() {
559 &[]
560 } else {
561 unsafe { slice::from_raw_parts(convert_ptr(row), width) }
562 }
563 })
564 }
565
566 #[inline]
567 fn is_allocated(&self) -> bool {
568 !self.data().is_null()
569 }
570
571 #[inline]
573 fn data_bytes(&self) -> Result<&[u8]> {
574 self.match_is_continuous().and_then(|_| {
575 let data = self.data();
576 Ok(if data.is_null() {
577 &[]
578 } else {
579 unsafe { slice::from_raw_parts(data, self.total() * self.elem_size()?) }
580 })
581 })
582 }
583
584 #[inline]
585 fn data_typed<T: DataType>(&self) -> Result<&[T]> {
586 match_format::<T>(self.typ())
587 .and_then(|_| self.match_is_continuous())
588 .and_then(|_| unsafe { self.data_typed_unchecked() })
589 }
590
591 #[inline]
594 unsafe fn data_typed_unchecked<T: DataType>(&self) -> Result<&[T]> {
595 let data = self.data();
596 Ok(if data.is_null() {
597 &[]
598 } else {
599 unsafe { slice::from_raw_parts(data.cast::<T>(), self.total()) }
600 })
601 }
602
603 fn to_vec_2d<T: DataType>(&self) -> Result<Vec<Vec<T>>> {
604 match_format::<T>(self.typ()).and_then(|_| {
605 let size = match *self.mat_size() {
606 [rows, cols] => Size::new(cols, rows),
607 ref mat_size => {
608 return Err(Error::new(
609 core::StsUnmatchedSizes,
610 format!(
611 "Mat must have 2 dimensions for this operation, but it has: {}",
612 mat_size.len()
613 ),
614 ))
615 }
616 };
617 let width = size.width as usize;
619 if self.is_continuous() {
620 let data = self.data_typed()?;
621 Ok((0..size.height)
622 .map(|row_n| {
623 let row_n = row_n as usize;
625 let mut row = Vec::with_capacity(width);
626 row.extend_from_slice(&data[row_n * width..(row_n + 1) * width]);
627 row
628 })
629 .collect())
630 } else {
631 Ok((0..size.height)
632 .map(|row_n| {
633 self.at_row(row_n).map(|src_row| {
634 let mut row = Vec::with_capacity(width);
635 row.extend_from_slice(src_row);
636 row
637 })
638 })
639 .collect::<Result<_>>()?)
640 }
641 })
642 }
643
644 #[inline]
646 fn iter<T: DataType>(&self) -> Result<MatIter<'_, T>>
647 where
648 Self: Sized,
649 {
650 MatConstIterator::over(self).map_or(
651 Ok(MatIter {
652 iter: None,
653 _d: PhantomData,
654 }),
655 MatIter::new,
656 )
657 }
658
659 #[inline]
660 fn try_into_typed<T: DataType>(self) -> Result<Mat_<T>>
661 where
662 Self: Sized,
663 Mat_<T>: TryFrom<Self, Error = Error>,
664 {
665 self.try_into()
666 }
667}
668
669pub trait MatTraitManual: MatTraitConstManual + MatTrait {
670 #[inline]
674 unsafe fn at_unchecked_mut<T: DataType>(&mut self, i0: i32) -> &mut T {
675 unsafe { &mut *data_at_idx::<T>(self, i0 as usize).cast_mut() }
676 }
677
678 #[inline]
682 unsafe fn at_2d_unchecked_mut<T: DataType>(&mut self, row: i32, col: i32) -> Result<&mut T> {
683 self.ptr_2d_mut(row, col).map(|ptr| unsafe { convert_ptr_mut(ptr) })
684 }
685
686 #[inline]
690 unsafe fn at_pt_unchecked_mut<T: DataType>(&mut self, pt: Point) -> Result<&mut T> {
691 unsafe { self.at_2d_unchecked_mut(pt.y, pt.x) }
692 }
693
694 #[inline]
698 unsafe fn at_3d_unchecked_mut<T: DataType>(&mut self, i0: i32, i1: i32, i2: i32) -> Result<&mut T> {
699 self.ptr_3d_mut(i0, i1, i2).map(|ptr| unsafe { convert_ptr_mut(ptr) })
700 }
701
702 #[inline]
706 unsafe fn at_nd_unchecked_mut<T: DataType>(&mut self, idx: &[i32]) -> Result<&mut T> {
707 self.ptr_nd_mut(idx).map(|ptr| unsafe { convert_ptr_mut(ptr) })
708 }
709
710 #[inline]
712 fn at_row_mut<T: DataType>(&mut self, row: i32) -> Result<&mut [T]> {
713 match_format::<T>(self.typ()).and_then(|_| self.match_indices(&[row, 0]))?;
714 unsafe { self.at_row_unchecked_mut(row) }
715 }
716
717 #[inline]
721 unsafe fn at_row_unchecked_mut<T: DataType>(&mut self, row: i32) -> Result<&mut [T]> {
722 let width = self.size()?.width as usize;
724 self.ptr_mut(row).map(|x| {
725 if x.is_null() {
726 &mut []
727 } else {
728 unsafe { slice::from_raw_parts_mut(convert_ptr_mut(x), width) }
729 }
730 })
731 }
732
733 #[inline]
735 fn data_bytes_mut(&mut self) -> Result<&mut [u8]> {
736 self.match_is_continuous().and_then(|_| {
737 let data = self.data_mut();
738 Ok(if data.is_null() {
739 &mut []
740 } else {
741 unsafe { slice::from_raw_parts_mut(self.data_mut(), self.total() * self.elem_size()?) }
742 })
743 })
744 }
745
746 #[inline]
747 fn data_typed_mut<T: DataType>(&mut self) -> Result<&mut [T]> {
748 match_format::<T>(self.typ()).and_then(|_| self.match_is_continuous())?;
749 unsafe { self.data_typed_unchecked_mut() }
750 }
751
752 #[inline]
755 unsafe fn data_typed_unchecked_mut<T: DataType>(&mut self) -> Result<&mut [T]> {
756 let total = self.total();
757 let data = self.data_mut();
758 Ok(if data.is_null() {
759 &mut []
760 } else {
761 unsafe { slice::from_raw_parts_mut(data.cast::<T>(), total) }
762 })
763 }
764
765 #[inline]
767 fn iter_mut<T: DataType>(&mut self) -> Result<MatIterMut<'_, T>>
768 where
769 Self: Sized,
770 {
771 MatConstIterator::over(self).map_or(
772 Ok(MatIterMut {
773 iter: None,
774 _d: PhantomData,
775 }),
776 MatIterMut::new,
777 )
778 }
779}
780
781impl<T: MatTraitConst + ?Sized> MatTraitConstManual for T {}
782
783impl<T: MatTrait + ?Sized> MatTraitManual for T {}
784
785input_output_array! { Mat, from_mat, from_mat_mut }
786input_output_array_vector! { Mat, from_mat_vec, from_mat_vec_mut }
787
788unsafe impl Sync for Mat {}
789
790impl fmt::Debug for Mat {
791 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
792 let typ = self.typ();
793 let depth = self.depth();
794 let typ = core::type_to_string(typ).map_err(|_| fmt::Error)?;
795 let depth = core::depth_to_string(depth).map_err(|_| fmt::Error)?;
796 let flags = self.flags();
797 let mut flags_str = String::new();
798 if flags & core::Mat_MAGIC_VAL != core::Mat_MAGIC_VAL {
799 flags_str.push_str("invalid magic value");
800 } else {
801 if flags & core::Mat_CONTINUOUS_FLAG != 0 {
802 flags_str.push_str("continuous");
803 }
804 if flags & core::Mat_SUBMATRIX_FLAG != 0 {
805 if !flags_str.is_empty() {
806 flags_str.push_str(", ");
807 }
808 flags_str.push_str("submatrix");
809 }
810 }
811 f.debug_struct("Mat")
812 .field("type", &typ)
813 .field("flags", &format!("0x{flags:X} ({flags_str})"))
814 .field("channels", &self.channels())
815 .field("depth", &depth)
816 .field("dims", &self.dims())
817 .field("rows", &self.rows())
818 .field("cols", &self.cols())
819 .field("mat_size", &self.mat_size())
820 .field("elem_size", &self.elem_size().map_err(|_| fmt::Error)?)
821 .field("elem_size1", &self.elem_size1())
822 .field("mat_step", &self.mat_step())
823 .field("total", &self.total())
824 .field("is_continuous", &self.is_continuous())
825 .field("is_submatrix", &self.is_submatrix())
826 .field("data", &MatDataDumper(self))
827 .finish()
828 }
829}
830
831struct MatDataDumper<'r>(&'r Mat);
832
833impl fmt::Debug for MatDataDumper<'_> {
834 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
835 const MAX_DUMP_SIZE: usize = 1000;
836
837 if self.0.total() <= MAX_DUMP_SIZE {
838 f.write_str(&self.0.get_data_dump().map_err(|_| fmt::Error)?)
839 } else {
840 f.write_fmt(format_args!("<element count is higher than threshold: {MAX_DUMP_SIZE}>"))
841 }
842 }
843}
844
845input_output_array! { UMat, from_umat, from_umat_mut }
846input_output_array_vector! { UMat, from_umat_vec, from_umat_vec_mut }
847
848impl Deref for MatSize<'_> {
849 type Target = [i32];
850
851 #[inline]
852 fn deref(&self) -> &Self::Target {
853 let p = self.p();
854 if p.is_null() {
855 &[]
856 } else {
857 let dims = usize::try_from(self.dims()).unwrap_or(0);
858 unsafe { slice::from_raw_parts(p, dims) }
859 }
860 }
861}
862
863impl fmt::Debug for MatSize<'_> {
864 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
865 writeln!(f, "{:#?}", self.deref())
866 }
867}
868
869impl Deref for MatStep {
870 #[cfg(not(ocvrs_opencv_branch_5))]
871 type Target = [usize; 2];
872 #[cfg(ocvrs_opencv_branch_5)]
873 type Target = [usize; 3];
874
875 fn deref(&self) -> &Self::Target {
876 self.buf()
877 }
878}
879
880impl DerefMut for MatStep {
881 fn deref_mut(&mut self) -> &mut Self::Target {
882 self.buf_mut()
883 }
884}
885
886pub trait MatConstIteratorTraitManual: MatConstIteratorTrait {
887 #[inline]
888 fn has_elements(&self) -> bool {
889 self.ptr() != self.slice_end()
890 }
891
892 #[inline]
893 fn current<T: DataType>(&self) -> Result<&T> {
894 match_format::<T>(self.typ())?;
895 if self.has_elements() {
896 Ok(unsafe { convert_ptr(self.ptr()) })
897 } else {
898 Err(Error::new(
899 core::StsOutOfRange,
900 "MatConstIterator doesn't have any more elements",
901 ))
902 }
903 }
904
905 #[inline]
906 fn current_mut<T: DataType>(&mut self) -> Result<&mut T> {
907 match_format::<T>(self.typ())?;
908 if self.has_elements() {
909 Ok(unsafe { convert_ptr_mut(self.ptr().cast_mut()) })
910 } else {
911 Err(Error::new(
912 core::StsOutOfRange,
913 "MatConstIterator doesn't have any more elements",
914 ))
915 }
916 }
917}
918
919impl<T: MatConstIteratorTrait> MatConstIteratorTraitManual for T {}
920
921input_output_array! { MatExpr, from_matexpr }