diff --git a/src/ImageSharp/Colors/Color.BulkOperations.cs b/src/ImageSharp/Colors/Color.BulkOperations.cs
index 9d698b8ac..18f9d92a6 100644
--- a/src/ImageSharp/Colors/Color.BulkOperations.cs
+++ b/src/ImageSharp/Colors/Color.BulkOperations.cs
@@ -125,6 +125,115 @@ namespace ImageSharp
base.ToVector4(sourceColors, destVectors, remainder);
}
}
+
+ ///
+ internal override unsafe void PackFromXyzBytes(BufferPointer sourceBytes, BufferPointer destColors, int count)
+ {
+ byte* source = (byte*)sourceBytes;
+ byte* destination = (byte*)destColors;
+
+ for (int x = 0; x < count; x++)
+ {
+ Unsafe.Write(destination, (uint)(*source << 0 | *(source + 1) << 8 | *(source + 2) << 16 | 255 << 24));
+
+ source += 3;
+ destination += 4;
+ }
+ }
+
+ ///
+ internal override unsafe void ToXyzBytes(BufferPointer sourceColors, BufferPointer destBytes, int count)
+ {
+ byte* source = (byte*)sourceColors;
+ byte* destination = (byte*)destBytes;
+
+ for (int x = 0; x < count; x++)
+ {
+ *destination = *(source + 0);
+ *(destination + 1) = *(source + 1);
+ *(destination + 2) = *(source + 2);
+
+ source += 4;
+ destination += 3;
+ }
+ }
+
+ ///
+ internal override void PackFromXyzwBytes(BufferPointer sourceBytes, BufferPointer destColors, int count)
+ {
+ BufferPointer.Copy(sourceBytes, destColors, count);
+ }
+
+ ///
+ internal override void ToXyzwBytes(BufferPointer sourceColors, BufferPointer destBytes, int count)
+ {
+ BufferPointer.Copy(sourceColors, destBytes, count);
+ }
+
+ ///
+ internal override unsafe void PackFromZyxBytes(BufferPointer sourceBytes, BufferPointer destColors, int count)
+ {
+ byte* source = (byte*)sourceBytes;
+ byte* destination = (byte*)destColors;
+
+ for (int x = 0; x < count; x++)
+ {
+ Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | 255 << 24));
+
+ source += 3;
+ destination += 4;
+ }
+ }
+
+ ///
+ internal override unsafe void ToZyxBytes(BufferPointer sourceColors, BufferPointer destBytes, int count)
+ {
+ byte* source = (byte*)sourceColors;
+ byte* destination = (byte*)destBytes;
+
+ for (int x = 0; x < count; x++)
+ {
+ *destination = *(source + 2);
+ *(destination + 1) = *(source + 1);
+ *(destination + 2) = *(source + 0);
+
+ source += 4;
+ destination += 3;
+ }
+ }
+
+ ///
+ internal override unsafe void PackFromZyxwBytes(BufferPointer sourceBytes, BufferPointer destColors, int count)
+ {
+ byte* source = (byte*)sourceBytes;
+ byte* destination = (byte*)destColors;
+
+ for (int x = 0; x < count; x++)
+ {
+ Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | *(source + 3) << 24));
+
+ source += 4;
+ destination += 4;
+ }
+ }
+
+ ///
+ internal override unsafe void ToZyxwBytes(BufferPointer sourceColors, BufferPointer destBytes, int count)
+ {
+ byte* source = (byte*)sourceColors;
+ byte* destination = (byte*)destBytes;
+
+ for (int x = 0; x < count; x++)
+ {
+ *destination = *(source + 2);
+ *(destination + 1) = *(source + 1);
+ *(destination + 2) = *(source + 0);
+ *(destination + 3) = *(source + 3);
+
+ source += 4;
+ destination += 4;
+ }
+ }
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Common/Memory/BufferPointer.cs b/src/ImageSharp/Common/Memory/BufferPointer.cs
index c80e22e21..f8798ba24 100644
--- a/src/ImageSharp/Common/Memory/BufferPointer.cs
+++ b/src/ImageSharp/Common/Memory/BufferPointer.cs
@@ -12,18 +12,7 @@ namespace ImageSharp
///
internal static class BufferPointer
{
- ///
- /// Gets a to the beginning of the raw data in 'buffer'.
- ///
- /// The element type
- /// The input
- /// The
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static unsafe BufferPointer Slice(this PinnedBuffer buffer)
- where T : struct
- {
- return new BufferPointer(buffer.Array, (void*)buffer.Pointer);
- }
+
///
/// Copy 'count' number of elements of the same type from 'source' to 'dest'
@@ -36,7 +25,7 @@ namespace ImageSharp
public static unsafe void Copy(BufferPointer source, BufferPointer destination, int count)
where T : struct
{
- Unsafe.CopyBlock((void*)source.PointerAtOffset, (void*)destination.PointerAtOffset, USizeOf(count));
+ Unsafe.CopyBlock((void*)destination.PointerAtOffset, (void*)source.PointerAtOffset, USizeOf(count));
}
///
@@ -50,7 +39,7 @@ namespace ImageSharp
public static unsafe void Copy(BufferPointer source, BufferPointer destination, int countInSource)
where T : struct
{
- Unsafe.CopyBlock((void*)source.PointerAtOffset, (void*)destination.PointerAtOffset, USizeOf(countInSource));
+ Unsafe.CopyBlock((void*)destination.PointerAtOffset, (void*)source.PointerAtOffset, USizeOf(countInSource));
}
///
@@ -64,7 +53,7 @@ namespace ImageSharp
public static unsafe void Copy(BufferPointer source, BufferPointer destination, int countInDest)
where T : struct
{
- Unsafe.CopyBlock((void*)source.PointerAtOffset, (void*)destination.PointerAtOffset, USizeOf(countInDest));
+ Unsafe.CopyBlock((void*)destination.PointerAtOffset, (void*)source.PointerAtOffset, USizeOf(countInDest));
}
///
diff --git a/src/ImageSharp/Common/Memory/BufferPointer{T}.cs b/src/ImageSharp/Common/Memory/BufferPointer{T}.cs
index fff4e513e..e05650a70 100644
--- a/src/ImageSharp/Common/Memory/BufferPointer{T}.cs
+++ b/src/ImageSharp/Common/Memory/BufferPointer{T}.cs
@@ -79,7 +79,7 @@ namespace ImageSharp
}
///
- /// Convertes instance to a raw 'byte*' pointer
+ /// Converts instance to a raw 'byte*' pointer
///
/// The to convert
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -87,7 +87,7 @@ namespace ImageSharp
{
return (byte*)bufferPointer.PointerAtOffset;
}
-
+
///
/// Forms a slice out of the given BufferPointer, beginning at 'offset'.
///
diff --git a/src/ImageSharp/Common/Memory/PinnedBuffer{T}.cs b/src/ImageSharp/Common/Memory/PinnedBuffer{T}.cs
index 04217a012..8e5ded048 100644
--- a/src/ImageSharp/Common/Memory/PinnedBuffer{T}.cs
+++ b/src/ImageSharp/Common/Memory/PinnedBuffer{T}.cs
@@ -7,6 +7,7 @@ namespace ImageSharp
{
using System;
using System.Buffers;
+ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
///
@@ -94,6 +95,27 @@ namespace ImageSharp
/// Gets a pointer to the pinned .
///
public IntPtr Pointer { get; private set; }
+
+ ///
+ /// Converts to an .
+ ///
+ /// The to convert.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator BufferPointer(PinnedBuffer buffer)
+ {
+ return buffer.Slice();
+ }
+
+ ///
+ /// Gets a to the beginning of the raw data in 'buffer'.
+ ///
+ /// The element type
+ /// The
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe BufferPointer Slice()
+ {
+ return new BufferPointer(this.Array, (void*)this.Pointer);
+ }
///
/// Disposes the instance by unpinning the array, and returning the pooled buffer when necessary.
diff --git a/tests/ImageSharp.Tests/Common/BufferPointerTests.cs b/tests/ImageSharp.Tests/Common/BufferPointerTests.cs
index 4b5847d53..a0b91b4c4 100644
--- a/tests/ImageSharp.Tests/Common/BufferPointerTests.cs
+++ b/tests/ImageSharp.Tests/Common/BufferPointerTests.cs
@@ -15,12 +15,18 @@ namespace ImageSharp.Tests.Common
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() { A = i, B = i };
+ result[i] = new Foo(i, i);
}
return result;
}
@@ -81,6 +87,12 @@ namespace ImageSharp.Tests.Common
public class Copy
{
+ private static void AssertNotDefault(T[] data, int idx)
+ where T : struct
+ {
+ Assert.NotEqual(default(T), data[idx]);
+ }
+
[Theory]
[InlineData(4)]
[InlineData(1500)]
@@ -98,7 +110,11 @@ namespace ImageSharp.Tests.Common
BufferPointer.Copy(apSource, apDest, count);
}
+ AssertNotDefault(source, 1);
+ AssertNotDefault(dest, 1);
+
Assert.Equal(source[0], dest[0]);
+ Assert.Equal(source[1], dest[1]);
Assert.Equal(source[count-1], dest[count-1]);
Assert.NotEqual(source[count], dest[count]);
}
@@ -121,19 +137,31 @@ namespace ImageSharp.Tests.Common
BufferPointer.Copy(apSource, apDest, count);
}
+ AssertNotDefault(source, 1);
+
Assert.True(ElementsAreEqual(source, dest, 0));
Assert.True(ElementsAreEqual(source, dest, count - 1));
Assert.False(ElementsAreEqual(source, dest, count));
}
+ private static byte[] CreateTestBytes(int count)
+ {
+ byte[] result = new byte[count];
+ for (int i = 0; i < result.Length; i++)
+ {
+ result[i] = (byte)(i % 255);
+ }
+ return result;
+ }
+
[Theory]
[InlineData(4)]
[InlineData(1500)]
public void BytesToGeneric(int count)
{
- int destCount = count * sizeof(Foo);
- byte[] source = new byte[destCount + sizeof(Foo) + 1];
- Foo[] dest = Foo.CreateArray(count + 2);
+ int srcCount = count * sizeof(Foo);
+ byte[] source = CreateTestBytes(srcCount);
+ Foo[] dest = new Foo[count + 2];
fixed(byte* pSource = source)
fixed (Foo* pDest = dest)
@@ -144,10 +172,33 @@ namespace ImageSharp.Tests.Common
BufferPointer.Copy(apSource, apDest, count);
}
+ AssertNotDefault(source, sizeof(Foo) + 1);
+ AssertNotDefault(dest, 1);
+
Assert.True(ElementsAreEqual(dest, source, 0));
+ Assert.True(ElementsAreEqual(dest, source, 1));
Assert.True(ElementsAreEqual(dest, source, count - 1));
Assert.False(ElementsAreEqual(dest, source, count));
}
+
+ [Fact]
+ public void ColorToBytes()
+ {
+ Color[] colors = { new Color(0, 1, 2, 3), new Color(4, 5, 6, 7), new Color(8, 9, 10, 11), };
+
+ using (PinnedBuffer colorBuf = new PinnedBuffer(colors))
+ using (PinnedBuffer byteBuf = new PinnedBuffer(colors.Length*4))
+ {
+ BufferPointer.Copy(colorBuf, byteBuf, colorBuf.Count);
+
+ byte[] a = byteBuf.Array;
+
+ for (int i = 0; i < byteBuf.Count; i++)
+ {
+ Assert.Equal((byte)i, a[i]);
+ }
+ }
+ }
private static bool ElementsAreEqual(Foo[] array, byte[] rawArray, int index)
{