enable MatConstIterator and SparseMat
MODIFY
build.rs
build.rs
@@ -435,7 +435,7 @@ fn gen_wrapper((opencv, pkg_name): (&pkg_config::Library, &str), opencv_header_d
{
let mut sys = File::create(module_dir.join("sys.rs"))?;
writeln!(&mut sys, "use std::os::raw::{{c_char, c_void}};")?;
- writeln!(&mut sys, "use libc::size_t;")?;
+ writeln!(&mut sys, "use libc::{{ptrdiff_t, size_t}};")?;
writeln!(&mut sys, "use crate::core;")?;
writeln!(&mut sys, "")?;
for entry in glob(&format!("{}/*.rv.rs", out_dir_as_str))? {

MODIFY
src/manual/core/mat.rs
src/manual/core/mat.rs
-use std::{fmt, ops::Deref, slice};
+use std::{
+ ffi::c_void,
+ fmt,
+ ops::Deref,
+ slice,
+};
-use libc::size_t;
+use libc::{c_uchar, size_t};
use crate::{
- core::{self, Mat, MatSize, MatStep, Scalar, UMat},
+ core::{self, Mat, MatConstIterator, MatSize, MatStep, Scalar, UMat},
Error,
Result,
sys,
@@ -87,6 +92,16 @@ data_type!(core::Rect2i, core::CV_32S, 4);
data_type!(core::Rect2f, core::CV_32F, 4);
data_type!(core::Rect2d, core::CV_64F, 4);
+#[inline(always)]
+fn convert_ptr<T>(r: &u8) -> &T {
+ unsafe { &*(r as *const _ as *const T) }
+}
+
+#[inline(always)]
+fn convert_ptr_mut<T>(r: &mut u8) -> &mut T {
+ unsafe { &mut *(r as *mut _ as *mut T) }
+}
+
impl Mat {
#[inline(always)]
fn match_format<T: DataType>(&self) -> Result<()> {
@@ -103,6 +118,7 @@ impl Mat {
}
}
+ #[inline(always)]
fn match_dims(&self, dims: usize) -> Result<()> {
let mat_dims = self.dims()? as usize;
if mat_dims == dims {
@@ -136,16 +152,6 @@ impl Mat {
}
}
- #[inline(always)]
- fn convert_ptr<T>(r: &u8) -> &T {
- unsafe { &*(r as *const _ as *const T) }
- }
-
- #[inline(always)]
- fn convert_ptr_mut<T>(r: &mut u8) -> &mut T {
- unsafe { &mut *(r as *mut _ as *mut T) }
- }
-
/// Create new `Mat` from the iterator of known size
pub fn from_exact_iter<T: DataType>(s: impl ExactSizeIterator<Item=T>) -> Result<Self> {
let mut out = unsafe { Self::new_rows_cols(s.len() as _, 1, T::typ()) }?;
@@ -176,7 +182,7 @@ impl Mat {
(i, i0 - i * mat_size[1])
};
self.ptr_2d(i, j)
- .map(Self::convert_ptr)
+ .map(convert_ptr)
}
#[inline(always)]
@@ -200,7 +206,7 @@ impl Mat {
(i, i0 - i * mat_size[1])
};
self.ptr_2d_mut(i, j)
- .map(Self::convert_ptr_mut)
+ .map(convert_ptr_mut)
}
#[inline(always)]
@@ -213,7 +219,7 @@ impl Mat {
/// Like `Mat::at_2d()` but performs no bounds or type checks
pub unsafe fn at_2d_unchecked<T: DataType>(&self, row: i32, col: i32) -> Result<&T> {
self.ptr_2d(row, col)
- .map(Self::convert_ptr)
+ .map(convert_ptr)
}
#[inline(always)]
@@ -226,7 +232,7 @@ impl Mat {
/// Like `Mat::at_2d_mut()` but performs no bounds or type checks
pub unsafe fn at_2d_mut_unchecked<T: DataType>(&mut self, row: i32, col: i32) -> Result<&mut T> {
self.ptr_2d_mut(row, col)
- .map(Self::convert_ptr_mut)
+ .map(convert_ptr_mut)
}
#[inline(always)]
@@ -238,7 +244,7 @@ impl Mat {
pub unsafe fn at_3d_unchecked<T: DataType>(&self, i0: i32, i1: i32, i2: i32) -> Result<&T> {
self.ptr_3d(i0, i1, i2)
- .map(Self::convert_ptr)
+ .map(convert_ptr)
}
#[inline(always)]
@@ -250,7 +256,7 @@ impl Mat {
pub unsafe fn at_3d_mut_unchecked<T: DataType>(&mut self, i0: i32, i1: i32, i2: i32) -> Result<&mut T> {
self.ptr_3d_mut(i0, i1, i2)
- .map(Self::convert_ptr_mut)
+ .map(convert_ptr_mut)
}
#[inline(always)]
@@ -262,7 +268,7 @@ impl Mat {
pub unsafe fn at_nd_unchecked<T: core::DataType>(&self, idx: &[i32]) -> Result<&T> {
self.ptr_nd(idx)
- .map(Self::convert_ptr)
+ .map(convert_ptr)
}
#[inline(always)]
@@ -274,7 +280,7 @@ impl Mat {
pub unsafe fn at_nd_mut_unchecked<T: core::DataType>(&mut self, idx: &[i32]) -> Result<&mut T> {
self.ptr_nd_mut(idx)
- .map(Self::convert_ptr_mut)
+ .map(convert_ptr_mut)
}
/// Return a complete read-only row
@@ -287,7 +293,7 @@ impl Mat {
/// Like `Mat::at_row()` but performs no bounds or type checks
pub unsafe fn at_row_unchecked<T: DataType>(&self, row: i32) -> Result<&[T]> {
let width = self.size()?.width as usize;
- self.ptr(row).map(Self::convert_ptr).map(|x| slice::from_raw_parts(x, width))
+ self.ptr(row).map(convert_ptr).map(|x| slice::from_raw_parts(x, width))
}
/// Return a complete writeable row
@@ -300,7 +306,7 @@ impl Mat {
/// Like `Mat::at_row_mut()` but performs no bounds or type checks
pub unsafe fn at_row_mut_unchecked<T: DataType>(&mut self, row: i32) -> Result<&mut [T]> {
let width = self.size()?.width as usize;
- self.ptr_mut(row).map(Self::convert_ptr_mut).map(|x| slice::from_raw_parts_mut(x, width))
+ self.ptr_mut(row).map(convert_ptr_mut).map(|x| slice::from_raw_parts_mut(x, width))
}
pub fn size(&self) -> Result<core::Size> {
@@ -379,7 +385,9 @@ impl Mat {
}
pub fn to_vec_2d<T: DataType>(&self) -> Result<Vec<Vec<T>>> {
- self.match_format::<T>().and_then(|_| self.match_dims(2)).and_then(|_| {
+ self.match_format::<T>()
+ .and_then(|_| self.match_dims(2))
+ .and_then(|_| {
let size = self.size()?;
let width = size.width as usize;
if self.is_continuous()? {
@@ -501,6 +509,45 @@ impl fmt::Debug for MatStep {
}
}
+impl MatConstIterator {
+ #[inline]
+ fn m(&self) -> Mat {
+ let me = self.as_raw_MatConstIterator();
+ Mat {
+ ptr: cpp!(unsafe [me as "const MatConstIterator*"] -> *mut c_void as "const void*" {
+ return reinterpret_cast<const void*>(new cv::Mat(*me->m));
+ })
+ }
+ }
+
+ #[inline]
+ pub fn has_elements(&self) -> bool {
+ let me = self.as_raw_MatConstIterator();
+ cpp!(unsafe [me as "const MatConstIterator*"] -> bool as "bool" {
+ return me->ptr != me->sliceEnd;
+ })
+ }
+
+ pub fn get<T: DataType>(&self) -> Result<&T> {
+ self.m().match_format::<T>()?;
+ if self.has_elements() {
+ unsafe { self.get_unchecked() }
+ } else {
+ Err(Error::new(core::StsOutOfRange, "MatConstIterator doesn't have any more elements".to_owned()))
+ }
+ }
+
+ #[inline]
+ pub unsafe fn get_unchecked<T: DataType>(&self) -> Result<&T> {
+ let me = self.as_raw_MatConstIterator();
+ cpp!([me as "const MatConstIterator*"] -> *const c_uchar as "const uchar*" {
+ return me->ptr;
+ }).as_ref()
+ .map(convert_ptr)
+ .ok_or_else(|| Error::new(core::StsNullPtr, format!("Function returned Null pointer")))
+ }
+}
+
mod private {
pub trait Sealed {}
}

MODIFY
tests/mat.rs
tests/mat.rs
@@ -3,7 +3,7 @@ use std::mem::transmute;
use matches::assert_matches;
use opencv::{
- core::{self, Rect, Scalar, Size, Vec2b, Vec3d, Vec3f, Vec4w},
+ core::{self, MatConstIterator, Point, Rect, Scalar, Size, Vec2b, Vec3d, Vec3f, Vec4w},
Error,
prelude::*,
Result,
@@ -386,3 +386,33 @@ fn mat_from_data() -> Result<()> {
assert_eq!(row[89], 0x82);
Ok(())
}
+
+#[test]
+fn mat_iterator() -> Result<()> {
+ let mat = Mat::from_slice(&[1, 2, 3, 4])?;
+ let mut iter = MatConstIterator::over(&mat)?;
+ assert_eq!(1, *iter.get::<i32>()?);
+ assert_eq!(Point::new(0, 0), iter.pos()?);
+ assert!(iter.has_elements());
+ iter.seek(1, true)?;
+ assert_eq!(2, *iter.get::<i32>()?);
+ assert_eq!(Point::new(1, 0), iter.pos()?);
+ assert!(iter.has_elements());
+ iter.seek(1, true)?;
+ assert_eq!(3, *iter.get::<i32>()?);
+ assert_eq!(Point::new(2, 0), iter.pos()?);
+ assert!(iter.has_elements());
+ iter.seek(1, true)?;
+ assert_eq!(4, *iter.get::<i32>()?);
+ assert_eq!(Point::new(3, 0), iter.pos()?);
+ assert!(iter.has_elements());
+ iter.seek(1, true)?;
+ assert_matches!(iter.get::<i32>(), Err(Error { code: core::StsOutOfRange, .. }));
+ assert_eq!(Point::new(0, 1), iter.pos()?);
+ assert!(!iter.has_elements());
+ iter.seek(1, true)?;
+ assert_matches!(iter.get::<i32>(), Err(Error { code: core::StsOutOfRange, .. }));
+ assert_eq!(Point::new(0, 1), iter.pos()?);
+ assert!(!iter.has_elements());
+ Ok(())
+}

enable MatConstIterator and SparseMat