Browse Source

PinnedBuffer<T> and PinnedImageBuffer<T> indexers

af/merge-core
Anton Firszov 9 years ago
parent
commit
24e1334d72
  1. 17
      src/ImageSharp/Common/Memory/PinnedBuffer{T}.cs
  2. 9
      src/ImageSharp/Common/Memory/PinnedImageBuffer{T}.cs
  3. 20
      src/ImageSharp/Image/PixelAccessor{TColor}.cs
  4. 56
      tests/ImageSharp.Tests/Common/BufferSpanTests.cs
  5. 48
      tests/ImageSharp.Tests/Common/PinnedBufferTests.cs
  6. 34
      tests/ImageSharp.Tests/Common/PinnedImageBufferTests.cs
  7. 62
      tests/ImageSharp.Tests/Common/TestStructs.cs

17
src/ImageSharp/Common/Memory/PinnedBuffer{T}.cs

@ -104,6 +104,23 @@ namespace ImageSharp
/// </summary>
public BufferSpan<T> Span => this;
/// <summary>
/// Returns a reference to specified element of the buffer.
/// </summary>
/// <param name="index">The index</param>
/// <returns>The reference to the specified element</returns>
public unsafe ref T this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
DebugGuard.MustBeLessThan(index, this.Length, nameof(index));
byte* ptr = (byte*)this.Pointer + BufferSpan.SizeOf<T>(index);
return ref Unsafe.AsRef<T>(ptr);
}
}
/// <summary>
/// Converts <see cref="PinnedBuffer{T}"/> to an <see cref="BufferSpan{T}"/>.
/// </summary>

9
src/ImageSharp/Common/Memory/PinnedImageBuffer{T}.cs

@ -6,6 +6,7 @@
namespace ImageSharp
{
using System;
using System.Runtime.CompilerServices;
/// <summary>
/// Represents a pinned buffer of value type objects
@ -46,6 +47,14 @@ namespace ImageSharp
/// <inheritdoc />
public int Height { get; }
/// <summary>
/// Gets a reference to the element at the specified position.
/// </summary>
/// <param name="x">The x coordinate (row)</param>
/// <param name="y">The y coordinate (position at row)</param>
/// <returns>A reference to the element.</returns>
public ref T this[int x, int y] => ref this.Array[(this.Width * y) + x];
/// <summary>
/// Creates a clean instance of <see cref="PinnedImageBuffer{T}"/> initializing it's elements with 'default(T)'.
/// </summary>

20
src/ImageSharp/Image/PixelAccessor{TColor}.cs

@ -241,16 +241,16 @@ namespace ImageSharp
this.CopyTo(area, sourceX, sourceY, width, height);
}
/// <summary>
/// Gets a <see cref="BufferSpan{T}"/> to the row 'y' beginning from the pixel at 'x'.
/// </summary>
/// <param name="x">The x coordinate</param>
/// <param name="y">The y coordinate</param>
/// <returns>The <see cref="BufferSpan{T}"/></returns>
internal BufferSpan<TColor> GetRowSpan(int x, int y)
{
return this.pixelBuffer.Slice((y * this.Width) + x, this.Width - x);
}
///// <summary>
///// Gets a <see cref="BufferSpan{T}"/> to the row 'y' beginning from the pixel at 'x'.
///// </summary>
///// <param name="x">The x coordinate</param>
///// <param name="y">The y coordinate</param>
///// <returns>The <see cref="BufferSpan{T}"/></returns>
//internal BufferSpan<TColor> GetRowSpan(int x, int y)
//{
// return this.pixelBuffer.Slice((y * this.Width) + x, this.Width - x);
//}
/// <summary>
/// Sets the pixel buffer in an unsafe manner. This should not be used unless you know what its doing!!!

56
tests/ImageSharp.Tests/Common/BufferSpanTests.cs

@ -7,62 +7,10 @@ namespace ImageSharp.Tests.Common
using Xunit;
using static TestStructs;
public unsafe class BufferSpanTests
{
public struct Foo
{
public int A;
public double B;
public Foo(int a, double b)
{
this.A = a;
this.B = b;
}
internal static Foo[] CreateArray(int size)
{
Foo[] result = new Foo[size];
for (int i = 0; i < size; i++)
{
result[i] = new Foo(i+1, i+1);
}
return result;
}
}
/// <summary>
/// sizeof(AlignedFoo) == sizeof(long)
/// </summary>
public struct AlignedFoo
{
public int A;
public int B;
static AlignedFoo()
{
Assert.Equal(sizeof(AlignedFoo), sizeof(long));
}
public AlignedFoo(int a, int b)
{
this.A = a;
this.B = b;
}
internal static AlignedFoo[] CreateArray(int size)
{
AlignedFoo[] result = new AlignedFoo[size];
for (int i = 0; i < size; i++)
{
result[i] = new AlignedFoo(i + 1, i + 1);
}
return result;
}
}
[Fact]
public void AsBytes()
{

48
tests/ImageSharp.Tests/Common/PinnedBufferTests.cs

@ -7,15 +7,10 @@
using Xunit;
using static TestStructs;
public unsafe class PinnedBufferTests
{
public struct Foo
{
public int A;
public double B;
}
[Theory]
[InlineData(42)]
[InlineData(1111)]
@ -79,6 +74,45 @@
}
}
public class Indexer
{
public static readonly TheoryData<int, int> IndexerData =
new TheoryData<int,int>()
{
{ 10, 0 },
{ 16, 3 },
{ 10, 9 }
};
[Theory]
[MemberData(nameof(IndexerData))]
public void Read(int length, int index)
{
Foo[] a = Foo.CreateArray(length);
using (PinnedBuffer<Foo> buffer = new PinnedBuffer<Foo>(a))
{
Foo element = buffer[index];
Assert.Equal(a[index], element);
}
}
[Theory]
[MemberData(nameof(IndexerData))]
public void Write(int length, int index)
{
Foo[] a = Foo.CreateArray(length);
using (PinnedBuffer<Foo> buffer = new PinnedBuffer<Foo>(a))
{
buffer[index] = new Foo(666, 666);
Assert.Equal(new Foo(666, 666), a[index]);
}
}
}
[Fact]
public void Dispose()
{

34
tests/ImageSharp.Tests/Common/PinnedImageBufferTests.cs

@ -5,6 +5,8 @@ namespace ImageSharp.Tests.Common
using Xunit;
using static TestStructs;
public unsafe class PinnedImageBufferTests
{
[Theory]
@ -12,7 +14,7 @@ namespace ImageSharp.Tests.Common
[InlineData(1025, 17)]
public void Construct(int width, int height)
{
using (PinnedImageBuffer<int> buffer = new PinnedImageBuffer<int>(width, height))
using (PinnedImageBuffer<Foo> buffer = new PinnedImageBuffer<Foo>(width, height))
{
Assert.Equal(width, buffer.Width);
Assert.Equal(height, buffer.Height);
@ -25,8 +27,8 @@ namespace ImageSharp.Tests.Common
[InlineData(1025, 17)]
public void Construct_FromExternalArray(int width, int height)
{
int[] array = new int[width * height + 10];
using (PinnedImageBuffer<int> buffer = new PinnedImageBuffer<int>(array, width, height))
Foo[] array = new Foo[width * height + 10];
using (PinnedImageBuffer<Foo> buffer = new PinnedImageBuffer<Foo>(array, width, height))
{
Assert.Equal(width, buffer.Width);
Assert.Equal(height, buffer.Height);
@ -57,9 +59,9 @@ namespace ImageSharp.Tests.Common
[InlineData(17, 42, 41)]
public void GetRowSpanY(int width, int height, int y)
{
using (PinnedImageBuffer<int> buffer = new PinnedImageBuffer<int>(width, height))
using (PinnedImageBuffer<Foo> buffer = new PinnedImageBuffer<Foo>(width, height))
{
BufferSpan<int> span = buffer.GetRowSpan(y);
BufferSpan<Foo> span = buffer.GetRowSpan(y);
Assert.Equal(width * y, span.Start);
Assert.Equal(width, span.Length);
@ -73,14 +75,32 @@ namespace ImageSharp.Tests.Common
[InlineData(17, 42, 0, 41)]
public void GetRowSpanXY(int width, int height, int x, int y)
{
using (PinnedImageBuffer<int> buffer = new PinnedImageBuffer<int>(width, height))
using (PinnedImageBuffer<Foo> buffer = new PinnedImageBuffer<Foo>(width, height))
{
BufferSpan<int> span = buffer.GetRowSpan(x, y);
BufferSpan<Foo> span = buffer.GetRowSpan(x, y);
Assert.Equal(width * y + x, span.Start);
Assert.Equal(width - x, span.Length);
Assert.Equal(buffer.Pointer + sizeof(int) * (width * y + x), span.PointerAtOffset);
}
}
[Theory]
[InlineData(42, 8, 0, 0)]
[InlineData(400, 1000, 20, 10)]
[InlineData(99, 88, 98, 87)]
public void Indexer(int width, int height, int x, int y)
{
using (PinnedImageBuffer<Foo> buffer = new PinnedImageBuffer<Foo>(width, height))
{
Foo[] array = buffer.Array;
ref Foo actual = ref buffer[x, y];
ref Foo expected = ref array[y * width + x];
Assert.True(Unsafe.AreSame(ref expected, ref actual));
}
}
}
}

62
tests/ImageSharp.Tests/Common/TestStructs.cs

@ -0,0 +1,62 @@
namespace ImageSharp.Tests.Common
{
using Xunit;
public static class TestStructs
{
public struct Foo
{
public int A;
public double B;
public Foo(int a, double b)
{
this.A = a;
this.B = b;
}
internal static Foo[] CreateArray(int size)
{
Foo[] result = new Foo[size];
for (int i = 0; i < size; i++)
{
result[i] = new Foo(i + 1, i + 1);
}
return result;
}
}
/// <summary>
/// sizeof(AlignedFoo) == sizeof(long)
/// </summary>
public unsafe struct AlignedFoo
{
public int A;
public int B;
static AlignedFoo()
{
Assert.Equal(sizeof(AlignedFoo), sizeof(long));
}
public AlignedFoo(int a, int b)
{
this.A = a;
this.B = b;
}
internal static AlignedFoo[] CreateArray(int size)
{
AlignedFoo[] result = new AlignedFoo[size];
for (int i = 0; i < size; i++)
{
result[i] = new AlignedFoo(i + 1, i + 1);
}
return result;
}
}
}
}
Loading…
Cancel
Save