diff --git a/src/DlibDotNet/Dlib.cs b/src/DlibDotNet/Dlib.cs index 37e8bce0..d9c5c161 100644 --- a/src/DlibDotNet/Dlib.cs +++ b/src/DlibDotNet/Dlib.cs @@ -453,6 +453,24 @@ public static Array2D LoadPng(string path) #region LoadImageData + public static Array2D LoadImageData(IntPtr data, uint rows, uint columns, uint steps) + where T : struct + { + if (data == IntPtr.Zero) + throw new ArgumentException(nameof(data)); + + if (!Array2D.TryParse(out var type)) + throw new NotSupportedException(); + + var srcType = type.ToNativeArray2DType(); + var dstType = type.ToNativeArray2DType(); + var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); + if (ret == IntPtr.Zero) + throw new ArgumentException($"Can not import from pointer to {dstType}."); + + return new Array2D(ret, type); + } + public static Array2D LoadImageData(byte[] data, uint rows, uint columns, uint steps) where T : struct { @@ -471,6 +489,34 @@ public static Array2D LoadImageData(byte[] data, uint rows, uint columns, return new Array2D(ret, type); } + public static Array2D LoadImageData(byte[] data, uint rows, uint columns, uint steps) + { + if (data == null) + throw new ArgumentNullException(nameof(data)); + + var srcType = ImageTypes.UInt8.ToNativeArray2DType(); + var dstType = ImageTypes.UInt8.ToNativeArray2DType(); + var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); + if (ret == IntPtr.Zero) + throw new ArgumentException($"Can not import from {ImageTypes.UInt8} to {dstType}."); + + return new Array2D(ret, ImageTypes.UInt8); + } + + //public static Array2D LoadImageData(sbyte[] data, uint rows, uint columns, uint steps) + //{ + // if (data == null) + // throw new ArgumentNullException(nameof(data)); + + // var srcType = ImageTypes.Int8.ToNativeArray2DType(); + // var dstType = ImageTypes.Int8.ToNativeArray2DType(); + // var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); + // if (ret == IntPtr.Zero) + // throw new ArgumentException($"Can not import from {ImageTypes.Int8} to {dstType}."); + + // return new Array2D(ret, ImageTypes.Int8); + //} + public static Array2D LoadImageData(ImagePixelFormat format, byte[] data, uint rows, uint columns, uint steps) where T : struct { @@ -490,184 +536,144 @@ public static Array2D LoadImageData(ImagePixelFormat format, byte[] data, return new Array2D(ret, type); } - public static Array2D LoadImageData(ushort[] data, uint rows, uint columns, uint steps) - where T : struct + public static Array2D LoadImageData(ushort[] data, uint rows, uint columns, uint steps) { if (data == null) throw new ArgumentNullException(nameof(data)); - if (!Array2D.TryParse(out var type)) - throw new NotSupportedException(); - var srcType = ImageTypes.UInt16.ToNativeArray2DType(); - var dstType = type.ToNativeArray2DType(); + var dstType = ImageTypes.UInt16.ToNativeArray2DType(); var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); if (ret == IntPtr.Zero) throw new ArgumentException($"Can not import from {ImageTypes.UInt16} to {dstType}."); - return new Array2D(ret, type); + return new Array2D(ret, ImageTypes.UInt16); } - public static Array2D LoadImageData(short[] data, uint rows, uint columns, uint steps) - where T : struct + public static Array2D LoadImageData(short[] data, uint rows, uint columns, uint steps) { if (data == null) throw new ArgumentNullException(nameof(data)); - if (!Array2D.TryParse(out var type)) - throw new NotSupportedException(); - var srcType = ImageTypes.Int16.ToNativeArray2DType(); - var dstType = type.ToNativeArray2DType(); + var dstType = ImageTypes.Int16.ToNativeArray2DType(); var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); if (ret == IntPtr.Zero) throw new ArgumentException($"Can not import from {ImageTypes.Int16} to {dstType}."); - return new Array2D(ret, type); + return new Array2D(ret, ImageTypes.Int16); } - public static Array2D LoadImageData(int[] data, uint rows, uint columns, uint steps) - where T : struct + public static Array2D LoadImageData(int[] data, uint rows, uint columns, uint steps) { if (data == null) throw new ArgumentNullException(nameof(data)); - if (!Array2D.TryParse(out var type)) - throw new NotSupportedException(); - var srcType = ImageTypes.Int32.ToNativeArray2DType(); - var dstType = type.ToNativeArray2DType(); + var dstType = ImageTypes.Int32.ToNativeArray2DType(); var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); if (ret == IntPtr.Zero) throw new ArgumentException($"Can not import from {ImageTypes.Int32} to {dstType}."); - return new Array2D(ret, type); + return new Array2D(ret, ImageTypes.Int32); } - public static Array2D LoadImageData(float[] data, uint rows, uint columns, uint steps) - where T : struct + public static Array2D LoadImageData(float[] data, uint rows, uint columns, uint steps) { if (data == null) throw new ArgumentNullException(nameof(data)); - if (!Array2D.TryParse(out var type)) - throw new NotSupportedException(); - var srcType = ImageTypes.Float.ToNativeArray2DType(); - var dstType = type.ToNativeArray2DType(); + var dstType = ImageTypes.Float.ToNativeArray2DType(); var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); if (ret == IntPtr.Zero) throw new ArgumentException($"Can not import from {ImageTypes.Float} to {dstType}."); - return new Array2D(ret, type); + return new Array2D(ret, ImageTypes.Float); } - public static Array2D LoadImageData(double[] data, uint rows, uint columns, uint steps) - where T : struct + public static Array2D LoadImageData(double[] data, uint rows, uint columns, uint steps) { if (data == null) throw new ArgumentNullException(nameof(data)); - if (!Array2D.TryParse(out var type)) - throw new NotSupportedException(); - var srcType = ImageTypes.Double.ToNativeArray2DType(); - var dstType = type.ToNativeArray2DType(); + var dstType = ImageTypes.Double.ToNativeArray2DType(); var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); if (ret == IntPtr.Zero) throw new ArgumentException($"Can not import from {ImageTypes.Double} to {dstType}."); - return new Array2D(ret, type); + return new Array2D(ret, ImageTypes.Double); } - public static Array2D LoadImageData(RgbPixel[] data, uint rows, uint columns, uint steps) - where T : struct + public static Array2D LoadImageData(RgbPixel[] data, uint rows, uint columns, uint steps) { if (data == null) throw new ArgumentNullException(nameof(data)); - if (!Array2D.TryParse(out var type)) - throw new NotSupportedException(); - var srcType = ImageTypes.RgbPixel.ToNativeArray2DType(); - var dstType = type.ToNativeArray2DType(); + var dstType = ImageTypes.RgbPixel.ToNativeArray2DType(); var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); if (ret == IntPtr.Zero) throw new ArgumentException($"Can not import from {ImageTypes.RgbPixel} to {dstType}."); - return new Array2D(ret, type); + return new Array2D(ret, ImageTypes.RgbPixel); } - public static Array2D LoadImageData(BgrPixel[] data, uint rows, uint columns, uint steps) - where T : struct + public static Array2D LoadImageData(BgrPixel[] data, uint rows, uint columns, uint steps) { if (data == null) throw new ArgumentNullException(nameof(data)); - if (!Array2D.TryParse(out var type)) - throw new NotSupportedException(); - var srcType = ImageTypes.BgrPixel.ToNativeArray2DType(); - var dstType = type.ToNativeArray2DType(); + var dstType = ImageTypes.BgrPixel.ToNativeArray2DType(); var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); if (ret == IntPtr.Zero) throw new ArgumentException($"Can not import from {ImageTypes.BgrPixel} to {dstType}."); - return new Array2D(ret, type); + return new Array2D(ret, ImageTypes.BgrPixel); } - public static Array2D LoadImageData(RgbAlphaPixel[] data, uint rows, uint columns, uint steps) - where T : struct + public static Array2D LoadImageData(RgbAlphaPixel[] data, uint rows, uint columns, uint steps) { if (data == null) throw new ArgumentNullException(nameof(data)); - if (!Array2D.TryParse(out var type)) - throw new NotSupportedException(); - var srcType = ImageTypes.RgbAlphaPixel.ToNativeArray2DType(); - var dstType = type.ToNativeArray2DType(); + var dstType = ImageTypes.RgbAlphaPixel.ToNativeArray2DType(); var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); if (ret == IntPtr.Zero) throw new ArgumentException($"Can not import from {ImageTypes.RgbAlphaPixel} to {dstType}."); - return new Array2D(ret, type); + return new Array2D(ret, ImageTypes.RgbAlphaPixel); } - public static Array2D LoadImageData(HsiPixel[] data, uint rows, uint columns, uint steps) - where T : struct + public static Array2D LoadImageData(HsiPixel[] data, uint rows, uint columns, uint steps) { if (data == null) throw new ArgumentNullException(nameof(data)); - if (!Array2D.TryParse(out var type)) - throw new NotSupportedException(); - var srcType = ImageTypes.HsiPixel.ToNativeArray2DType(); - var dstType = type.ToNativeArray2DType(); + var dstType = ImageTypes.HsiPixel.ToNativeArray2DType(); var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); if (ret == IntPtr.Zero) throw new ArgumentException($"Can not import from {ImageTypes.HsiPixel} to {dstType}."); - return new Array2D(ret, type); + return new Array2D(ret, ImageTypes.HsiPixel); } - public static Array2D LoadImageData(LabPixel[] data, uint rows, uint columns, uint steps) - where T : struct + public static Array2D LoadImageData(LabPixel[] data, uint rows, uint columns, uint steps) { if (data == null) throw new ArgumentNullException(nameof(data)); - if (!Array2D.TryParse(out var type)) - throw new NotSupportedException(); - var srcType = ImageTypes.LabPixel.ToNativeArray2DType(); - var dstType = type.ToNativeArray2DType(); + var dstType = ImageTypes.LabPixel.ToNativeArray2DType(); var ret = NativeMethods.extensions_load_image_data(dstType, srcType, data, rows, columns, steps); if (ret == IntPtr.Zero) throw new ArgumentException($"Can not import from {ImageTypes.LabPixel} to {dstType}."); - return new Array2D(ret, type); + return new Array2D(ret, ImageTypes.LabPixel); } #endregion diff --git a/src/DlibDotNet/PInvoke/Dlib.cs b/src/DlibDotNet/PInvoke/Dlib.cs index 79d10a68..ef7bde23 100644 --- a/src/DlibDotNet/PInvoke/Dlib.cs +++ b/src/DlibDotNet/PInvoke/Dlib.cs @@ -595,7 +595,10 @@ public static extern ErrorType object_detector_scan_fhog_pyramid_serialize(byte[ #region extensions - #region extensions_load_image_data + #region extensions_load_image_data + + [DllImport(NativeLibrary, CallingConvention = CallingConvention)] + public static extern IntPtr extensions_load_image_data(Array2DType dst_type, Array2DType src_type, IntPtr data, uint rows, uint columns, uint steps); [DllImport(NativeLibrary, CallingConvention = CallingConvention)] public static extern IntPtr extensions_load_image_data(Array2DType dst_type, Array2DType src_type, byte[] data, uint rows, uint columns, uint steps); diff --git a/test/DlibDotNet.Tests/DlibTest.cs b/test/DlibDotNet.Tests/DlibTest.cs index 14ecbf9d..19cb3e90 100644 --- a/test/DlibDotNet.Tests/DlibTest.cs +++ b/test/DlibDotNet.Tests/DlibTest.cs @@ -2392,7 +2392,7 @@ public void LoadImageData() switch (test.Type) { case ImageTypes.UInt8: - image = Dlib.LoadImageData(data, 512, 512, 512); + image = Dlib.LoadImageData(data, 512, 512, 512); if (this.CanGuiDebug) { @@ -2441,6 +2441,7 @@ public void LoadImageData2() { new { Type = ImageTypes.UInt8, ExpectResult = true}, new { Type = ImageTypes.UInt16, ExpectResult = true}, + //new { Type = ImageTypes.Int8, ExpectResult = true}, new { Type = ImageTypes.Int16, ExpectResult = true}, new { Type = ImageTypes.Int32, ExpectResult = true}, new { Type = ImageTypes.HsiPixel, ExpectResult = true}, @@ -2468,7 +2469,269 @@ public void LoadImageData2() for (var c = 0; c < cols; c++) data[steps * r + c] = (byte)random.Next(0, 255); - image = Dlib.LoadImageData(data, rows, cols, steps); + image = Dlib.LoadImageData(data, rows, cols, steps); + + if (this.CanGuiDebug) + { + win.SetImage((Array2D)image); + win.WaitUntilClosed(); + } + } + break; + //case ImageTypes.Int8: + // { + // var data = new sbyte[rows * cols]; + // for (var r = 0; r < rows; r++) + // for (var c = 0; c < cols; c++) + // data[steps * r + c] = (sbyte)random.Next(sbyte.MinValue, sbyte.MaxValue); + + // image = Dlib.LoadImageData(data, rows, cols, steps); + + // if (this.CanGuiDebug) + // { + // win.SetImage((Array2D)image); + // win.WaitUntilClosed(); + // } + // } + // break; + case ImageTypes.UInt16: + { + var data = new ushort[rows * cols]; + for (var r = 0; r < rows; r++) + for (var c = 0; c < cols; c++) + data[steps * r + c] = (ushort)random.Next(0, 255); + + image = Dlib.LoadImageData(data, rows, cols, steps); + + if (this.CanGuiDebug) + { + win.SetImage((Array2D)image); + win.WaitUntilClosed(); + } + } + break; + case ImageTypes.Int16: + { + var data = new short[rows * cols]; + for (var r = 0; r < rows; r++) + for (var c = 0; c < cols; c++) + data[steps * r + c] = (short)random.Next(0, 255); + + image = Dlib.LoadImageData(data, rows, cols, steps); + + if (this.CanGuiDebug) + { + win.SetImage((Array2D)image); + win.WaitUntilClosed(); + } + } + break; + case ImageTypes.Int32: + { + var data = new int[rows * cols]; + for (var r = 0; r < rows; r++) + for (var c = 0; c < cols; c++) + data[steps * r + c] = random.Next(0, 255); + + image = Dlib.LoadImageData(data, rows, cols, steps); + + if (this.CanGuiDebug) + { + win.SetImage((Array2D)image); + win.WaitUntilClosed(); + } + } + break; + case ImageTypes.Float: + { + var data = new float[rows * cols]; + for (var r = 0; r < rows; r++) + for (var c = 0; c < cols; c++) + data[steps * r + c] = (float)random.NextDouble(); + + image = Dlib.LoadImageData(data, rows, cols, steps); + + if (this.CanGuiDebug) + { + win.SetImage((Array2D)image); + win.WaitUntilClosed(); + } + } + break; + case ImageTypes.Double: + { + var data = new double[rows * cols]; + for (var r = 0; r < rows; r++) + for (var c = 0; c < cols; c++) + data[steps * r + c] = random.NextDouble(); + + image = Dlib.LoadImageData(data, rows, cols, steps); + + if (this.CanGuiDebug) + { + win.SetImage((Array2D)image); + win.WaitUntilClosed(); + } + } + break; + case ImageTypes.HsiPixel: + { + var data = new HsiPixel[rows * cols]; + for (var r = 0; r < rows; r++) + for (var c = 0; c < cols; c++) + data[steps * r + c] = new HsiPixel + { + H = (byte)random.Next(0, 255), + S = (byte)random.Next(0, 255), + I = (byte)random.Next(0, 255) + }; + + image = Dlib.LoadImageData(data, rows, cols, steps); + + if (this.CanGuiDebug) + { + win.SetImage((Array2D)image); + win.WaitUntilClosed(); + } + } + break; + case ImageTypes.LabPixel: + { + var data = new LabPixel[rows * cols]; + for (var r = 0; r < rows; r++) + for (var c = 0; c < cols; c++) + data[steps * r + c] = new LabPixel + { + L = (byte)random.Next(0, 255), + A = (byte)random.Next(0, 255), + B = (byte)random.Next(0, 255) + }; + + image = Dlib.LoadImageData(data, rows, cols, steps); + + if (this.CanGuiDebug) + { + win.SetImage((Array2D)image); + win.WaitUntilClosed(); + } + } + break; + case ImageTypes.BgrPixel: + { + var data = new BgrPixel[rows * cols]; + for (var r = 0; r < rows; r++) + for (var c = 0; c < cols; c++) + data[steps * r + c] = new BgrPixel + { + Red = (byte)random.Next(0, 255), + Green = (byte)random.Next(0, 255), + Blue = (byte)random.Next(0, 255) + }; + + image = Dlib.LoadImageData(data, rows, cols, steps); + + if (this.CanGuiDebug) + { + win.SetImage((Array2D)image); + win.WaitUntilClosed(); + } + } + break; + case ImageTypes.RgbPixel: + { + var data = new RgbPixel[rows * cols]; + for (var r = 0; r < rows; r++) + for (var c = 0; c < cols; c++) + data[steps * r + c] = new RgbPixel + { + Red = (byte)random.Next(0, 255), + Green = (byte)random.Next(0, 255), + Blue = (byte)random.Next(0, 255) + }; + + image = Dlib.LoadImageData(data, rows, cols, steps); + + if (this.CanGuiDebug) + { + win.SetImage((Array2D)image); + win.WaitUntilClosed(); + } + } + break; + case ImageTypes.RgbAlphaPixel: + { + var data = new RgbAlphaPixel[rows * cols]; + for (var r = 0; r < rows; r++) + for (var c = 0; c < cols; c++) + data[steps * r + c] = new RgbAlphaPixel + { + Red = (byte)random.Next(0, 255), + Green = (byte)random.Next(0, 255), + Blue = (byte)random.Next(0, 255), + Alpha = (byte)random.Next(0, 255) + }; + + image = Dlib.LoadImageData(data, rows, cols, steps); + + if (this.CanGuiDebug) + { + win.SetImage((Array2D)image); + win.WaitUntilClosed(); + } + } + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + Assert.True(image.Columns == cols, $"Failed to load {test.Type}."); + Assert.True(image.Rows == rows, $"Failed to load {test.Type}."); + + this.DisposeAndCheckDisposedState(image); + } + } + + [Fact] + public unsafe void LoadImageDataPointer() + { + const int cols = 512; + const int rows = 512; + const int steps = 512; + + var tests = new[] + { + new { Type = ImageTypes.UInt8, ExpectResult = true}, + new { Type = ImageTypes.UInt16, ExpectResult = true}, + new { Type = ImageTypes.Int16, ExpectResult = true}, + new { Type = ImageTypes.Int32, ExpectResult = true}, + new { Type = ImageTypes.HsiPixel, ExpectResult = true}, + new { Type = ImageTypes.LabPixel, ExpectResult = true}, + new { Type = ImageTypes.BgrPixel, ExpectResult = true}, + new { Type = ImageTypes.RgbPixel, ExpectResult = true}, + new { Type = ImageTypes.RgbAlphaPixel, ExpectResult = true}, + new { Type = ImageTypes.Float, ExpectResult = true}, + new { Type = ImageTypes.Double, ExpectResult = true} + }; + + var random = new Random(0); + + foreach (var test in tests) + { + TwoDimensionObjectBase image; + using (var win = new ImageWindow()) + { + switch (test.Type) + { + case ImageTypes.UInt8: + { + var data = new byte[rows * cols]; + for (var r = 0; r < rows; r++) + for (var c = 0; c < cols; c++) + data[steps * r + c] = (byte)random.Next(0, 255); + + fixed (byte* p = &data[0]) + image = Dlib.LoadImageData((IntPtr)p, rows, cols, steps); if (this.CanGuiDebug) { @@ -2484,7 +2747,8 @@ public void LoadImageData2() for (var c = 0; c < cols; c++) data[steps * r + c] = (ushort)random.Next(0, 255); - image = Dlib.LoadImageData(data, rows, cols, steps); + fixed (ushort* p = &data[0]) + image = Dlib.LoadImageData((IntPtr)p, rows, cols, steps); if (this.CanGuiDebug) { @@ -2500,7 +2764,8 @@ public void LoadImageData2() for (var c = 0; c < cols; c++) data[steps * r + c] = (short)random.Next(0, 255); - image = Dlib.LoadImageData(data, rows, cols, steps); + fixed (short* p = &data[0]) + image = Dlib.LoadImageData((IntPtr)p, rows, cols, steps); if (this.CanGuiDebug) { @@ -2516,7 +2781,8 @@ public void LoadImageData2() for (var c = 0; c < cols; c++) data[steps * r + c] = random.Next(0, 255); - image = Dlib.LoadImageData(data, rows, cols, steps); + fixed (int* p = &data[0]) + image = Dlib.LoadImageData((IntPtr)p, rows, cols, steps); if (this.CanGuiDebug) { @@ -2532,7 +2798,8 @@ public void LoadImageData2() for (var c = 0; c < cols; c++) data[steps * r + c] = (float)random.NextDouble(); - image = Dlib.LoadImageData(data, rows, cols, steps); + fixed (float* p = &data[0]) + image = Dlib.LoadImageData((IntPtr)p, rows, cols, steps); if (this.CanGuiDebug) { @@ -2548,7 +2815,8 @@ public void LoadImageData2() for (var c = 0; c < cols; c++) data[steps * r + c] = random.NextDouble(); - image = Dlib.LoadImageData(data, rows, cols, steps); + fixed (double* p = &data[0]) + image = Dlib.LoadImageData((IntPtr)p, rows, cols, steps); if (this.CanGuiDebug) { @@ -2569,7 +2837,8 @@ public void LoadImageData2() I = (byte)random.Next(0, 255) }; - image = Dlib.LoadImageData(data, rows, cols, steps); + fixed (HsiPixel* p = &data[0]) + image = Dlib.LoadImageData((IntPtr)p, rows, cols, steps); if (this.CanGuiDebug) { @@ -2590,7 +2859,8 @@ public void LoadImageData2() B = (byte)random.Next(0, 255) }; - image = Dlib.LoadImageData(data, rows, cols, steps); + fixed (LabPixel* p = &data[0]) + image = Dlib.LoadImageData((IntPtr)p, rows, cols, steps); if (this.CanGuiDebug) { @@ -2611,7 +2881,8 @@ public void LoadImageData2() Blue = (byte)random.Next(0, 255) }; - image = Dlib.LoadImageData(data, rows, cols, steps); + fixed (BgrPixel* p = &data[0]) + image = Dlib.LoadImageData((IntPtr)p, rows, cols, steps); if (this.CanGuiDebug) { @@ -2632,7 +2903,8 @@ public void LoadImageData2() Blue = (byte)random.Next(0, 255) }; - image = Dlib.LoadImageData(data, rows, cols, steps); + fixed (RgbPixel* p = &data[0]) + image = Dlib.LoadImageData((IntPtr)p, rows, cols, steps); if (this.CanGuiDebug) { @@ -2654,7 +2926,8 @@ public void LoadImageData2() Alpha = (byte)random.Next(0, 255) }; - image = Dlib.LoadImageData(data, rows, cols, steps); + fixed (RgbAlphaPixel* p = &data[0]) + image = Dlib.LoadImageData((IntPtr)p, rows, cols, steps); if (this.CanGuiDebug) {