Skip to content

Commit

Permalink
Merge pull request #1026 from shimat/imdecode_span
Browse files Browse the repository at this point in the history
add cv::imdecode overload (ReadOnlySpan<byte>)
  • Loading branch information
shimat committed Aug 21, 2020
2 parents d581c3e + 8e7a7cf commit 6bb03fb
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 18 deletions.
5 changes: 5 additions & 0 deletions nuget/OpenCvSharp4.nuspec
Expand Up @@ -18,22 +18,27 @@
<group targetFramework="net48">
<dependency id="System.Drawing.Common" version="4.7.0" />
<dependency id="System.Runtime.CompilerServices.Unsafe" version="4.7.1" />
<dependency id="System.Memory" version="4.5.4" />
</group>
<group targetFramework="net461">
<dependency id="System.Drawing.Common" version="4.7.0" />
<dependency id="System.Runtime.CompilerServices.Unsafe" version="4.7.1" />
<dependency id="System.Memory" version="4.5.4" />
</group>
<group targetFramework="netstandard2.0">
<dependency id="System.Drawing.Common" version="4.7.0" />
<dependency id="System.Runtime.CompilerServices.Unsafe" version="4.7.1" />
<dependency id="System.Memory" version="4.5.4" />
</group>
<group targetFramework="netstandard2.1">
<dependency id="System.Drawing.Common" version="4.7.0" />
<dependency id="System.Runtime.CompilerServices.Unsafe" version="4.7.1" />
<dependency id="System.Memory" version="4.5.4" />
</group>
<group targetFramework="netcoreapp2.1">
<dependency id="System.Drawing.Common" version="4.7.0" />
<dependency id="System.Runtime.CompilerServices.Unsafe" version="4.7.1" />
<dependency id="System.Memory" version="4.5.4" />
</group>
</dependencies>
<frameworkAssemblies>
Expand Down
2 changes: 1 addition & 1 deletion src/OpenCvSharp.Blob/OpenCvSharp.Blob.csproj
Expand Up @@ -25,7 +25,7 @@


<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.0.0">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
2 changes: 1 addition & 1 deletion src/OpenCvSharp.Extensions/OpenCvSharp.Extensions.csproj
Expand Up @@ -24,7 +24,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.0.0">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
Expand Up @@ -35,7 +35,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.0.0">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
22 changes: 22 additions & 0 deletions src/OpenCvSharp/Cv2/Cv2_imgcodecs.cs
Expand Up @@ -181,6 +181,28 @@ public static Mat ImDecode(byte[] buf, ImreadModes flags)
return new Mat(ret);
}

/// <summary>
/// Reads image from the specified buffer in memory.
/// </summary>
/// <param name="span">The input slice of bytes.</param>
/// <param name="flags">The same flags as in imread</param>
/// <returns></returns>
public static Mat ImDecode(ReadOnlySpan<byte> span, ImreadModes flags)
{
if (span.IsEmpty)
throw new ArgumentException("Empty span", nameof(span));

unsafe
{
fixed (byte* pBuf = span)
{
NativeMethods.HandleException(
NativeMethods.imgcodecs_imdecode_vector(pBuf, new IntPtr(span.Length), (int) flags, out var ret));
return new Mat(ret);
}
}
}

/// <summary>
/// Compresses the image and stores it in the memory buffer
/// </summary>
Expand Down
26 changes: 24 additions & 2 deletions src/OpenCvSharp/Modules/core/Mat/Mat.cs
Expand Up @@ -650,7 +650,7 @@ public static Mat FromStream(Stream stream, ImreadModes mode)

#if LANG_JP
/// <summary>
/// 画像データ(JPEG等の画像をメモリに展開したもの)からMatを生成する (cv::decode)
/// 画像データ(JPEG等の画像をメモリに展開したもの)からMatを生成する (cv::imdecode)
/// </summary>
/// <param name="imageBytes"></param>
/// <param name="mode"></param>
Expand All @@ -670,9 +670,20 @@ public static Mat ImDecode(byte[] imageBytes, ImreadModes mode = ImreadModes.Col
return Cv2.ImDecode(imageBytes, mode);
}

/// <summary>
/// Reads image from the specified buffer in memory.
/// </summary>
/// <param name="span">The input slice of bytes.</param>
/// <param name="mode">The same flags as in imread</param>
/// <returns></returns>
public static Mat ImDecode(ReadOnlySpan<byte> span, ImreadModes mode = ImreadModes.Color)
{
return Cv2.ImDecode(span, mode);
}

#if LANG_JP
/// <summary>
/// 画像データ(JPEG等の画像をメモリに展開したもの)からMatを生成する (cv::decode)
/// 画像データ(JPEG等の画像をメモリに展開したもの)からMatを生成する (cv::imdecode)
/// </summary>
/// <param name="imageBytes"></param>
/// <param name="mode"></param>
Expand All @@ -690,6 +701,17 @@ public static Mat FromImageData(byte[] imageBytes, ImreadModes mode = ImreadMode
return ImDecode(imageBytes, mode);
}

/// <summary>
/// Reads image from the specified buffer in memory.
/// </summary>
/// <param name="span">The input slice of bytes.</param>
/// <param name="mode">The same flags as in imread</param>
/// <returns></returns>
public static Mat FromImageData(ReadOnlySpan<byte> span, ImreadModes mode = ImreadModes.Color)
{
return Cv2.ImDecode(span, mode);
}

#endregion

#endregion
Expand Down
9 changes: 8 additions & 1 deletion src/OpenCvSharp/Modules/stitching/ImageFeatures.cs
Expand Up @@ -31,11 +31,17 @@ public ImageFeatures(int imgIdx, Size imgSize, IReadOnlyList<KeyPoint> keypoints
Descriptors = descriptors;
}

/// <summary>
/// Destructor
/// </summary>
~ImageFeatures()
{
Dispose(false);
}

/// <summary>
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
Expand All @@ -44,14 +50,15 @@ protected virtual void Dispose(bool disposing)
}
}

/// <inheritdoc />
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}

#pragma warning restore 1591
#pragma warning disable 1591
[StructLayout(LayoutKind.Sequential)]
public struct WImageFeatures
{
Expand Down
3 changes: 2 additions & 1 deletion src/OpenCvSharp/OpenCvSharp.csproj
Expand Up @@ -26,14 +26,15 @@


<ItemGroup Condition=" '$(Configuration)' == 'FxCop' ">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.0.0">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.1" />
<PackageReference Include="System.Memory" Version="4.5.4" />
</ItemGroup>

<ItemGroup>
Expand Down
Expand Up @@ -97,6 +97,9 @@ public static ExceptionStatus imgcodecs_imwrite_multi(string fileName, IntPtr im
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus imgcodecs_imdecode_vector(
byte[] buf, IntPtr bufLength, int flags, out IntPtr returnValue);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe ExceptionStatus imgcodecs_imdecode_vector(
byte* buf, IntPtr bufLength, int flags, out IntPtr returnValue);

[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus imgcodecs_imdecode_InputArray(
Expand Down
5 changes: 3 additions & 2 deletions src/OpenCvSharpExtern/imgcodecs.h
Expand Up @@ -50,8 +50,9 @@ CVAPI(ExceptionStatus) imgcodecs_imdecode_Mat(cv::Mat *buf, int flags, cv::Mat *
CVAPI(ExceptionStatus) imgcodecs_imdecode_vector(uchar *buf, size_t bufLength, int flags, cv::Mat **returnValue)
{
BEGIN_WRAP
const std::vector<uchar> bufVec(buf, buf + bufLength);
const auto ret = cv::imdecode(bufVec, flags);
//const std::vector<uchar> bufVec(buf, buf + bufLength);
const cv::Mat bufMat(1, bufLength, CV_8UC1, buf, cv::Mat::AUTO_STEP);
const auto ret = cv::imdecode(bufMat, flags);
*returnValue = new cv::Mat(ret);
END_WRAP
}
Expand Down
12 changes: 4 additions & 8 deletions test/OpenCvSharp.Tests/OpenCvSharp.Tests.csproj
Expand Up @@ -50,22 +50,18 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.0.0">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="SharpZipLib" Version="1.2.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.2">
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Xunit.StaFact" Version="0.3.18" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net48' ">
<PackageReference Include="System.Memory" Version="4.5.3" />
<PackageReference Include="Xunit.StaFact" Version="1.0.37" />
</ItemGroup>

<ItemGroup>
Expand Down
Binary file added test/OpenCvSharp.Tests/_data/image/mandrill.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 35 additions & 1 deletion test/OpenCvSharp.Tests/imgcodecs/ImgCodecsTest.cs
Expand Up @@ -400,7 +400,7 @@ public void ImDecode(string imageFormatName)
var imageFormat = imageFormatProperty!.GetValue(null) as ImageFormat;
Assert.NotNull(imageFormat);

using var bitmap = new Bitmap("_data/image/lenna.png");
using var bitmap = new Bitmap("_data/image/mandrill.png");
using var stream = new MemoryStream();
bitmap.Save(stream, imageFormat);
var imageData = stream.ToArray();
Expand All @@ -411,6 +411,40 @@ public void ImDecode(string imageFormatName)
Assert.False(mat.Empty());
Assert.Equal(bitmap.Width, mat.Cols);
Assert.Equal(bitmap.Height, mat.Rows);

ShowImagesWhenDebugMode(mat);
}

[Fact]
public void ImDecodeSpan()
{
var imageBytes = File.ReadAllBytes("_data/image/mandrill.png");
Assert.NotEmpty(imageBytes);

// whole range
{
var span = imageBytes.AsSpan();
using var mat = Cv2.ImDecode(span, ImreadModes.Color);
Assert.NotNull(mat);
Assert.False(mat.Empty());
ShowImagesWhenDebugMode(mat);
}

// slice
{
var dummyBytes = Enumerable.Repeat((byte)123, 100).ToArray();
var imageBytesWithDummy = dummyBytes.Concat(imageBytes).Concat(dummyBytes).ToArray();

#if NET48
var span = imageBytesWithDummy.AsSpan(100, imageBytes.Length);
#else
var span = imageBytesWithDummy.AsSpan()[100..^100];
#endif
using var mat = Cv2.ImDecode(span, ImreadModes.Color);
Assert.NotNull(mat);
Assert.False(mat.Empty());
ShowImagesWhenDebugMode(mat);
}
}

[Fact]
Expand Down
2 changes: 2 additions & 0 deletions test/OpenCvSharp.Tests/imgproc/LineIteratorTest.cs
Expand Up @@ -14,7 +14,9 @@ public void CountPixels()
using (Mat mat = Mat.Zeros(10, 10, MatType.CV_8UC1))
using (var lineIterator = new LineIterator(mat, p1, p2))
{
#pragma warning disable CA1829
var count = lineIterator.Count();
#pragma warning restore CA1829
Assert.Equal(10, count);
}
}
Expand Down

0 comments on commit 6bb03fb

Please sign in to comment.