Browse Source

CopyPixelDataTo

af/UniformUnmanagedMemoryPoolMemoryAllocator-02-MemoryGuards
Anton Firszov 5 years ago
parent
commit
2d6596f26b
  1. 12
      src/ImageSharp/ImageFrame{TPixel}.cs
  2. 13
      src/ImageSharp/Image{TPixel}.cs
  3. 55
      tests/ImageSharp.Tests/Image/ImageFrameTests.cs
  4. 54
      tests/ImageSharp.Tests/Image/ImageTests.cs
  5. 26
      tests/ImageSharp.Tests/TestUtilities/TestUtils.cs

12
src/ImageSharp/ImageFrame{TPixel}.cs

@ -266,6 +266,18 @@ namespace SixLabors.ImageSharp
}
}
/// <summary>
/// Copy image pixels to <paramref name="destination"/>.
/// </summary>
/// <param name="destination">The <see cref="Span{TPixel}"/> to copy image pixels to.</param>
public void CopyPixelDataTo(Span<TPixel> destination) => this.GetPixelMemoryGroup().CopyTo(destination);
/// <summary>
/// Copy image pixels to <paramref name="destination"/>.
/// </summary>
/// <param name="destination">The <see cref="Span{T}"/> of <see cref="byte"/> to copy image pixels to.</param>
public void CopyPixelDataTo(Span<byte> destination) => this.GetPixelMemoryGroup().CopyTo(MemoryMarshal.Cast<byte, TPixel>(destination));
/// <summary>
/// Gets the representation of the pixels as a <see cref="Memory{T}"/> in the source image's pixel format
/// stored in row major order, if the backing buffer is contiguous.

13
src/ImageSharp/Image{TPixel}.cs

@ -6,6 +6,7 @@ using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
@ -300,6 +301,18 @@ namespace SixLabors.ImageSharp
}
}
/// <summary>
/// Copy image pixels to <paramref name="destination"/>.
/// </summary>
/// <param name="destination">The <see cref="Span{TPixel}"/> to copy image pixels to.</param>
public void CopyPixelDataTo(Span<TPixel> destination) => this.GetPixelMemoryGroup().CopyTo(destination);
/// <summary>
/// Copy image pixels to <paramref name="destination"/>.
/// </summary>
/// <param name="destination">The <see cref="Span{T}"/> of <see cref="byte"/> to copy image pixels to.</param>
public void CopyPixelDataTo(Span<byte> destination) => this.GetPixelMemoryGroup().CopyTo(MemoryMarshal.Cast<byte, TPixel>(destination));
/// <summary>
/// Gets the representation of the pixels as a <see cref="Memory{T}"/> in the source image's pixel format
/// stored in row major order, if the backing buffer is contiguous.

55
tests/ImageSharp.Tests/Image/ImageFrameTests.cs

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.Memory;
@ -93,6 +95,59 @@ namespace SixLabors.ImageSharp.Tests
ArgumentOutOfRangeException ex = Assert.Throws<ArgumentOutOfRangeException>(() => frame[3, y] = default);
Assert.Equal("y", ex.ParamName);
}
[Theory]
[InlineData(false, false)]
[InlineData(false, true)]
[InlineData(true, false)]
[InlineData(true, true)]
public void CopyPixelDataTo_Success(bool disco, bool byteSpan)
{
if (disco)
{
this.LimitBufferCapacity(20);
}
using var image = new Image<La16>(this.configuration, 10, 10);
if (disco)
{
Assert.True(image.GetPixelMemoryGroup().Count > 1);
}
byte[] expected = TestUtils.FillImageWithRandomBytes(image);
byte[] actual = new byte[expected.Length];
if (byteSpan)
{
image.Frames.RootFrame.CopyPixelDataTo(actual);
}
else
{
Span<La16> destination = MemoryMarshal.Cast<byte, La16>(actual);
image.Frames.RootFrame.CopyPixelDataTo(destination);
}
Assert.True(expected.AsSpan().SequenceEqual(actual));
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void CopyPixelDataTo_DestinationTooShort_Throws(bool byteSpan)
{
using var image = new Image<La16>(this.configuration, 10, 10);
Assert.ThrowsAny<ArgumentOutOfRangeException>(() =>
{
if (byteSpan)
{
image.Frames.RootFrame.CopyPixelDataTo(new byte[199]);
}
else
{
image.Frames.RootFrame.CopyPixelDataTo(new La16[99]);
}
});
}
}
public class ProcessPixelRows : ProcessPixelRowsTestBase

54
tests/ImageSharp.Tests/Image/ImageTests.cs

@ -3,6 +3,7 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Memory;
@ -167,6 +168,59 @@ namespace SixLabors.ImageSharp.Tests
ArgumentOutOfRangeException ex = Assert.Throws<ArgumentOutOfRangeException>(() => image[3, y] = default);
Assert.Equal("y", ex.ParamName);
}
[Theory]
[InlineData(false, false)]
[InlineData(false, true)]
[InlineData(true, false)]
[InlineData(true, true)]
public void CopyPixelDataTo_Success(bool disco, bool byteSpan)
{
if (disco)
{
this.LimitBufferCapacity(20);
}
using var image = new Image<La16>(this.configuration, 10, 10);
if (disco)
{
Assert.True(image.GetPixelMemoryGroup().Count > 1);
}
byte[] expected = TestUtils.FillImageWithRandomBytes(image);
byte[] actual = new byte[expected.Length];
if (byteSpan)
{
image.CopyPixelDataTo(actual);
}
else
{
Span<La16> destination = MemoryMarshal.Cast<byte, La16>(actual);
image.CopyPixelDataTo(destination);
}
Assert.True(expected.AsSpan().SequenceEqual(actual));
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void CopyPixelDataTo_DestinationTooShort_Throws(bool byteSpan)
{
using var image = new Image<La16>(this.configuration, 10, 10);
Assert.ThrowsAny<ArgumentOutOfRangeException>(() =>
{
if (byteSpan)
{
image.CopyPixelDataTo(new byte[199]);
}
else
{
image.CopyPixelDataTo(new La16[99]);
}
});
}
}
public class ProcessPixelRows : ProcessPixelRowsTestBase

26
tests/ImageSharp.Tests/TestUtilities/TestUtils.cs

@ -54,6 +54,32 @@ namespace SixLabors.ImageSharp.Tests
public static bool HasFlag(this PixelTypes pixelTypes, PixelTypes flag) => (pixelTypes & flag) == flag;
public static byte[] GetRandomBytes(int length, int seed = 42)
{
var rnd = new Random(42);
byte[] bytes = new byte[length];
rnd.NextBytes(bytes);
return bytes;
}
internal static byte[] FillImageWithRandomBytes(Image<La16> image)
{
byte[] expected = TestUtils.GetRandomBytes(image.Width * image.Height * 2);
image.ProcessPixelRows(accessor =>
{
int cnt = 0;
for (int y = 0; y < accessor.Height; y++)
{
Span<La16> row = accessor.GetRowSpan(y);
for (int x = 0; x < row.Length; x++)
{
row[x] = new La16(expected[cnt++], expected[cnt++]);
}
}
});
return expected;
}
public static bool IsEquivalentTo<TPixel>(this Image<TPixel> a, Image<TPixel> b, bool compareAlpha = true)
where TPixel : unmanaged, IPixel<TPixel>
{

Loading…
Cancel
Save