diff --git a/src/OpenCvSharp/Fundamentals/MatMemoryManager.cs b/src/OpenCvSharp/Fundamentals/MatMemoryManager.cs
new file mode 100644
index 0000000000..76af982737
--- /dev/null
+++ b/src/OpenCvSharp/Fundamentals/MatMemoryManager.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Buffers;
+
+namespace OpenCvSharp;
+
+///
+/// A MemoryManager over an OpenCvSharpMat
+///
+/// The pointer is assumed to be fully unmanaged, or externally pinned - no attempt will be made to pin this data
+public sealed unsafe class MatMemoryManager : MemoryManager
+ where T : unmanaged
+{
+ private readonly Mat wrapped;
+
+ ///
+ /// Create a new UnmanagedMemoryManager instance at the given pointer and size
+ ///
+ /// It is assumed that the span provided is already unmanaged or externally pinned
+ public MatMemoryManager(Mat mat, bool isDataOwner = true)
+ {
+ if (!mat.IsContinuous())
+ {
+ throw new ArgumentException("mat is not continuous", nameof(mat));
+ }
+
+ wrapped = isDataOwner ? mat : new Mat(mat);
+ }
+
+ ///
+ public override Span GetSpan() => new((void*)wrapped.Data, (int)wrapped.Total());
+
+ ///
+ /// Provides access to a pointer that represents the data (note: no actual pin occurs)
+ ///
+ public override MemoryHandle Pin(int elementIndex = 0)
+ {
+ if (elementIndex < 0 || elementIndex >= wrapped.Total())
+ {
+ throw new ArgumentOutOfRangeException(nameof(elementIndex));
+ }
+
+ var dims = wrapped.Dims;
+ var idxs = new int[dims];
+ var remainIdx = elementIndex;
+ for (var dim = dims - 1; dim >= 0; dim--)
+ {
+ remainIdx = Math.DivRem(remainIdx, wrapped.Size(dim), out idxs[dim]);
+ }
+
+ return new MemoryHandle((void*)wrapped.Ptr(idxs));
+ }
+
+ ///
+ /// Has no effect
+ ///
+ public override void Unpin()
+ {
+ }
+
+ ///
+ /// Releases all resources associated with this object
+ ///
+ protected override void Dispose(bool disposing)
+ => wrapped.Dispose();
+}
diff --git a/src/OpenCvSharp/Modules/core/Mat/Mat.cs b/src/OpenCvSharp/Modules/core/Mat/Mat.cs
index 698c56dbf1..dc3ef4e403 100644
--- a/src/OpenCvSharp/Modules/core/Mat/Mat.cs
+++ b/src/OpenCvSharp/Modules/core/Mat/Mat.cs
@@ -3572,7 +3572,7 @@ public bool GetRectangularArray(out T[,] data)
///
/// Primitive or Vec array to be copied
/// Length of copied bytes
- public bool SetArray(T[] data)
+ public bool SetArray(params T[] data)
where T : unmanaged
{
CheckArgumentsForConvert(data);
@@ -4107,5 +4107,13 @@ public void ForEachAsVec6d(MatForeachFunctionVec6d operation)
#endregion
+ ///
+ /// Creates a new span over the Mat.
+ ///
+ ///
+ ///
+ public unsafe Span AsSpan() where T : unmanaged
+ => IsContinuous() ? new Span(DataPointer, (int)Total()) : Span.Empty;
+
#endregion
}