Skip to content

Commit e624cb6

Browse files
committed
Fix addressing in Mat::at() and Mat::at_mut()
1 parent f153fb8 commit e624cb6

File tree

2 files changed

+17
-31
lines changed

2 files changed

+17
-31
lines changed

src/manual/core/mat.rs

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -122,21 +122,22 @@ fn match_length(sizes: &[i32], slice_len: usize, size_mul: usize) -> Result<()>
122122
Ok(())
123123
}
124124

125+
/// Port of the algo from `Mat::at(int i0)`, includes OpenCV 5 specifics
125126
#[inline(always)]
126-
fn idx_to_row_col(mat: &(impl MatTraitConst + ?Sized), i0: i32) -> Result<(i32, i32)> {
127-
Ok(if mat.is_continuous() {
128-
(0, i0)
127+
unsafe fn data_at_idx<T: DataType>(mat: &(impl MatTraitConst + ?Sized), i0: usize) -> *const T {
128+
let size = mat.mat_size();
129+
let size = &*size;
130+
let data = mat.data();
131+
if size.len() <= 1 || mat.is_continuous() || size[0] == 1 {
132+
unsafe { data.cast::<T>().add(i0) }
133+
} else if size[1] == 1 {
134+
unsafe { data.add(mat.mat_step()[0] * i0) }.cast::<T>()
129135
} else {
130-
let mat_size = mat.size()?;
131-
if mat_size.width == 1 {
132-
(0, i0)
133-
} else if mat_size.height == 1 {
134-
(i0, 0)
135-
} else {
136-
let i = i0 / mat_size.height;
137-
(i, i0 - i * mat_size.height)
138-
}
139-
})
136+
let cols = usize::try_from(size[1]).unwrap_or(1);
137+
let i = i0 / cols;
138+
let j = i0 - i * cols;
139+
unsafe { data.add(mat.mat_step()[0] * i).cast::<T>().add(j) }
140+
}
140141
}
141142

142143
#[inline]
@@ -479,16 +480,7 @@ pub trait MatTraitConstManual: MatTraitConst {
479480
/// Caller must ensure that index is within Mat bounds
480481
#[inline]
481482
unsafe fn at_unchecked<T: DataType>(&self, i0: i32) -> Result<&T> {
482-
let mat_size = self.size()?;
483-
let (i, j) = if self.is_continuous() || mat_size.width == 1 {
484-
(0, i0)
485-
} else if mat_size.height == 1 {
486-
(i0, 0)
487-
} else {
488-
let i = i0 / mat_size.height;
489-
(i, i0 - i * mat_size.height)
490-
};
491-
self.ptr_2d(i, j).map(|ptr| unsafe { convert_ptr(ptr) })
483+
Ok(unsafe { &*data_at_idx::<T>(self, i0 as usize) })
492484
}
493485

494486
/// Like `Mat::at_2d()` but performs no bounds or type checks
@@ -656,8 +648,7 @@ pub trait MatTraitManual: MatTraitConstManual + MatTrait {
656648
/// Caller must ensure that index is within Mat bounds
657649
#[inline]
658650
unsafe fn at_unchecked_mut<T: DataType>(&mut self, i0: i32) -> Result<&mut T> {
659-
let (i, j) = idx_to_row_col(self, i0)?;
660-
self.ptr_2d_mut(i, j).map(|ptr| unsafe { convert_ptr_mut(ptr) })
651+
Ok(unsafe { &mut *data_at_idx::<T>(self, i0 as usize).cast_mut() })
661652
}
662653

663654
/// Like `Mat::at_2d_mut()` but performs no bounds or type checks

tests/mat.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -609,12 +609,7 @@ fn mat_from_data() -> Result<()> {
609609

610610
{
611611
let src = unsafe { Mat::new_nd_with_data_unsafe_def(&[3, 5, 6], u8::opencv_type(), bytes.as_mut_ptr().cast::<c_void>())? };
612-
let expected_size = if cfg!(ocvrs_opencv_branch_5) {
613-
Size::new(0, 0)
614-
} else {
615-
Size::new(5, 3)
616-
};
617-
assert_eq!(expected_size, src.size()?);
612+
assert_eq!(&[3, 5, 6], &*src.mat_size());
618613
assert_eq!(3, src.dims());
619614
assert_eq!(-1, src.rows());
620615
assert_eq!(-1, src.cols());

0 commit comments

Comments
 (0)