diff --git a/src/ImageSharp/Colors/Color.BulkOperations.cs b/src/ImageSharp/Colors/Color.BulkOperations.cs
index 5c040e04c5..039fafced6 100644
--- a/src/ImageSharp/Colors/Color.BulkOperations.cs
+++ b/src/ImageSharp/Colors/Color.BulkOperations.cs
@@ -24,8 +24,8 @@ namespace ImageSharp
/// SIMD optimized bulk implementation of
/// that works only with `count` divisible by .
///
- /// The to the source colors.
- /// The to the dstination vectors.
+ /// The to the source colors.
+ /// The to the dstination vectors.
/// The number of pixels to convert.
///
/// Implementation adapted from:
@@ -38,8 +38,8 @@ namespace ImageSharp
///
///
internal static unsafe void ToVector4SimdAligned(
- BufferPointer sourceColors,
- BufferPointer destVectors,
+ BufferSpan sourceColors,
+ BufferSpan destVectors,
int count)
{
int vecSize = Vector.Count;
@@ -85,12 +85,12 @@ namespace ImageSharp
vf.CopyTo(fTemp, i);
}
- BufferPointer.Copy(tempBuf, (BufferPointer)destVectors, unpackedRawCount);
+ BufferSpan.Copy(tempBuf, (BufferSpan)destVectors, unpackedRawCount);
}
}
///
- internal override void ToVector4(BufferPointer sourceColors, BufferPointer destVectors, int count)
+ internal override void ToVector4(BufferSpan sourceColors, BufferSpan destVectors, int count)
{
if (count < 256)
{
@@ -117,7 +117,7 @@ namespace ImageSharp
}
///
- internal override unsafe void PackFromXyzBytes(BufferPointer sourceBytes, BufferPointer destColors, int count)
+ internal override unsafe void PackFromXyzBytes(BufferSpan sourceBytes, BufferSpan destColors, int count)
{
byte* source = (byte*)sourceBytes;
byte* destination = (byte*)destColors;
@@ -132,7 +132,7 @@ namespace ImageSharp
}
///
- internal override unsafe void ToXyzBytes(BufferPointer sourceColors, BufferPointer destBytes, int count)
+ internal override unsafe void ToXyzBytes(BufferSpan sourceColors, BufferSpan destBytes, int count)
{
byte* source = (byte*)sourceColors;
byte* destination = (byte*)destBytes;
@@ -149,19 +149,19 @@ namespace ImageSharp
}
///
- internal override void PackFromXyzwBytes(BufferPointer sourceBytes, BufferPointer destColors, int count)
+ internal override void PackFromXyzwBytes(BufferSpan sourceBytes, BufferSpan destColors, int count)
{
- BufferPointer.Copy(sourceBytes, destColors, count);
+ BufferSpan.Copy(sourceBytes, destColors, count);
}
///
- internal override void ToXyzwBytes(BufferPointer sourceColors, BufferPointer destBytes, int count)
+ internal override void ToXyzwBytes(BufferSpan sourceColors, BufferSpan destBytes, int count)
{
- BufferPointer.Copy(sourceColors, destBytes, count);
+ BufferSpan.Copy(sourceColors, destBytes, count);
}
///
- internal override unsafe void PackFromZyxBytes(BufferPointer sourceBytes, BufferPointer destColors, int count)
+ internal override unsafe void PackFromZyxBytes(BufferSpan sourceBytes, BufferSpan destColors, int count)
{
byte* source = (byte*)sourceBytes;
byte* destination = (byte*)destColors;
@@ -176,7 +176,7 @@ namespace ImageSharp
}
///
- internal override unsafe void ToZyxBytes(BufferPointer sourceColors, BufferPointer destBytes, int count)
+ internal override unsafe void ToZyxBytes(BufferSpan sourceColors, BufferSpan destBytes, int count)
{
byte* source = (byte*)sourceColors;
byte* destination = (byte*)destBytes;
@@ -193,7 +193,7 @@ namespace ImageSharp
}
///
- internal override unsafe void PackFromZyxwBytes(BufferPointer sourceBytes, BufferPointer destColors, int count)
+ internal override unsafe void PackFromZyxwBytes(BufferSpan sourceBytes, BufferSpan destColors, int count)
{
byte* source = (byte*)sourceBytes;
byte* destination = (byte*)destColors;
@@ -208,7 +208,7 @@ namespace ImageSharp
}
///
- internal override unsafe void ToZyxwBytes(BufferPointer sourceColors, BufferPointer destBytes, int count)
+ internal override unsafe void ToZyxwBytes(BufferSpan sourceColors, BufferSpan destBytes, int count)
{
byte* source = (byte*)sourceColors;
byte* destination = (byte*)destBytes;
diff --git a/src/ImageSharp/Colors/PackedPixel/BulkPixelOperations{TColor}.cs b/src/ImageSharp/Colors/PackedPixel/BulkPixelOperations{TColor}.cs
index 259b1c9b47..7b6169f9c6 100644
--- a/src/ImageSharp/Colors/PackedPixel/BulkPixelOperations{TColor}.cs
+++ b/src/ImageSharp/Colors/PackedPixel/BulkPixelOperations{TColor}.cs
@@ -29,12 +29,12 @@ namespace ImageSharp
///
/// Bulk version of
///
- /// The to the source vectors.
- /// The to the destination colors.
+ /// The to the source vectors.
+ /// The to the destination colors.
/// The number of pixels to convert.
internal virtual void PackFromVector4(
- BufferPointer sourceVectors,
- BufferPointer destColors,
+ BufferSpan sourceVectors,
+ BufferSpan destColors,
int count)
{
Vector4* sp = (Vector4*)sourceVectors.PointerAtOffset;
@@ -55,12 +55,12 @@ namespace ImageSharp
///
/// Bulk version of .
///
- /// The to the source colors.
- /// The to the destination vectors.
+ /// The to the source colors.
+ /// The to the destination vectors.
/// The number of pixels to convert.
internal virtual void ToVector4(
- BufferPointer sourceColors,
- BufferPointer destVectors,
+ BufferSpan sourceColors,
+ BufferSpan destVectors,
int count)
{
byte* sp = (byte*)sourceColors;
@@ -78,12 +78,12 @@ namespace ImageSharp
///
/// Bulk version of that converts data in .
///
- /// The to the source bytes.
- /// The to the destination colors.
+ /// The to the source bytes.
+ /// The to the destination colors.
/// The number of pixels to convert.
internal virtual void PackFromXyzBytes(
- BufferPointer sourceBytes,
- BufferPointer destColors,
+ BufferSpan sourceBytes,
+ BufferSpan destColors,
int count)
{
byte* sp = (byte*)sourceBytes;
@@ -102,15 +102,15 @@ namespace ImageSharp
///
/// Bulk version of .
///
- /// The to the source colors.
- /// The to the destination bytes.
+ /// The to the source colors.
+ /// The to the destination bytes.
/// The number of pixels to convert.
- internal virtual void ToXyzBytes(BufferPointer sourceColors, BufferPointer destBytes, int count)
+ internal virtual void ToXyzBytes(BufferSpan sourceColors, BufferSpan destBytes, int count)
{
byte* sp = (byte*)sourceColors;
byte[] dest = destBytes.Array;
- for (int i = destBytes.Offset; i < destBytes.Offset + (count * 3); i += 3)
+ for (int i = destBytes.Start; i < destBytes.Start + (count * 3); i += 3)
{
TColor c = Unsafe.Read(sp);
c.ToXyzBytes(dest, i);
@@ -121,12 +121,12 @@ namespace ImageSharp
///
/// Bulk version of that converts data in .
///
- /// The to the source bytes.
- /// The to the destination colors.
+ /// The to the source bytes.
+ /// The to the destination colors.
/// The number of pixels to convert.
internal virtual void PackFromXyzwBytes(
- BufferPointer sourceBytes,
- BufferPointer destColors,
+ BufferSpan sourceBytes,
+ BufferSpan destColors,
int count)
{
byte* sp = (byte*)sourceBytes;
@@ -145,18 +145,18 @@ namespace ImageSharp
///
/// Bulk version of .
///
- /// The to the source colors.
- /// The to the destination bytes.
+ /// The to the source colors.
+ /// The to the destination bytes.
/// The number of pixels to convert.
internal virtual void ToXyzwBytes(
- BufferPointer sourceColors,
- BufferPointer destBytes,
+ BufferSpan sourceColors,
+ BufferSpan destBytes,
int count)
{
byte* sp = (byte*)sourceColors;
byte[] dest = destBytes.Array;
- for (int i = destBytes.Offset; i < destBytes.Offset + (count * 4); i += 4)
+ for (int i = destBytes.Start; i < destBytes.Start + (count * 4); i += 4)
{
TColor c = Unsafe.Read(sp);
c.ToXyzwBytes(dest, i);
@@ -167,12 +167,12 @@ namespace ImageSharp
///
/// Bulk version of that converts data in .
///
- /// The to the source bytes.
- /// The to the destination colors.
+ /// The to the source bytes.
+ /// The to the destination colors.
/// The number of pixels to convert.
internal virtual void PackFromZyxBytes(
- BufferPointer sourceBytes,
- BufferPointer destColors,
+ BufferSpan sourceBytes,
+ BufferSpan destColors,
int count)
{
byte* sp = (byte*)sourceBytes;
@@ -191,15 +191,15 @@ namespace ImageSharp
///
/// Bulk version of .
///
- /// The to the source colors.
- /// The to the destination bytes.
+ /// The to the source colors.
+ /// The to the destination bytes.
/// The number of pixels to convert.
- internal virtual void ToZyxBytes(BufferPointer sourceColors, BufferPointer destBytes, int count)
+ internal virtual void ToZyxBytes(BufferSpan sourceColors, BufferSpan destBytes, int count)
{
byte* sp = (byte*)sourceColors;
byte[] dest = destBytes.Array;
- for (int i = destBytes.Offset; i < destBytes.Offset + (count * 3); i += 3)
+ for (int i = destBytes.Start; i < destBytes.Start + (count * 3); i += 3)
{
TColor c = Unsafe.Read(sp);
c.ToZyxBytes(dest, i);
@@ -210,12 +210,12 @@ namespace ImageSharp
///
/// Bulk version of that converts data in .
///
- /// The to the source bytes.
- /// The to the destination colors.
+ /// The to the source bytes.
+ /// The to the destination colors.
/// The number of pixels to convert.
internal virtual void PackFromZyxwBytes(
- BufferPointer sourceBytes,
- BufferPointer destColors,
+ BufferSpan sourceBytes,
+ BufferSpan destColors,
int count)
{
byte* sp = (byte*)sourceBytes;
@@ -234,18 +234,18 @@ namespace ImageSharp
///
/// Bulk version of .
///
- /// The to the source colors.
- /// The to the destination bytes.
+ /// The to the source colors.
+ /// The to the destination bytes.
/// The number of pixels to convert.
internal virtual void ToZyxwBytes(
- BufferPointer sourceColors,
- BufferPointer destBytes,
+ BufferSpan sourceColors,
+ BufferSpan destBytes,
int count)
{
byte* sp = (byte*)sourceColors;
byte[] dest = destBytes.Array;
- for (int i = destBytes.Offset; i < destBytes.Offset + (count * 4); i += 4)
+ for (int i = destBytes.Start; i < destBytes.Start + (count * 4); i += 4)
{
TColor c = Unsafe.Read(sp);
c.ToZyxwBytes(dest, i);
diff --git a/src/ImageSharp/Common/Memory/BufferPointer{T}.cs b/src/ImageSharp/Common/Memory/BufferPointer{T}.cs
deleted file mode 100644
index 441f6b8ce0..0000000000
--- a/src/ImageSharp/Common/Memory/BufferPointer{T}.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageSharp
-{
- using System;
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
-
- ///
- /// Provides access to elements in an array from a given position.
- /// This type shares many similarities with corefx System.Span<T> but there are significant differences in it's functionalities and semantics:
- /// - It's not possible to use it with stack objects or pointers to unmanaged memory, only with managed arrays
- /// - It's possible to retrieve a reference to the array () so we can pass it to API-s like
- /// - There is no bounds checking for performance reasons. Therefore we don't need to store length. (However this could be added as DEBUG-only feature.)
- /// This makes an unsafe type!
- /// - Currently the arrays provided to BufferPointer need to be pinned. This behaviour could be changed using C#7 features.
- ///
- /// The type of elements of the array
- internal unsafe struct BufferPointer
- where T : struct
- {
- ///
- /// Initializes a new instance of the struct from a pinned array and an offset.
- ///
- /// The pinned array
- /// Pointer to the beginning of array
- /// The offset inside the array
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public BufferPointer(T[] array, void* pointerToArray, int offset)
- {
- DebugGuard.NotNull(array, nameof(array));
-
- this.Array = array;
- this.Offset = offset;
- this.PointerAtOffset = (IntPtr)pointerToArray + (Unsafe.SizeOf() * offset);
- }
-
- ///
- /// Initializes a new instance of the struct from a pinned array.
- ///
- /// The pinned array
- /// Pointer to the start of 'array'
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public BufferPointer(T[] array, void* pointerToArray)
- {
- DebugGuard.NotNull(array, nameof(array));
-
- this.Array = array;
- this.Offset = 0;
- this.PointerAtOffset = (IntPtr)pointerToArray;
- }
-
- ///
- /// Gets the array
- ///
- public T[] Array { get; private set; }
-
- ///
- /// Gets the offset inside
- ///
- public int Offset { get; private set; }
-
- ///
- /// Gets the offset inside in bytes.
- ///
- public int ByteOffset => this.Offset * Unsafe.SizeOf();
-
- ///
- /// Gets the pointer to the offseted array position
- ///
- public IntPtr PointerAtOffset { get; private set; }
-
- ///
- /// Convertes instance to a raw 'void*' pointer
- ///
- /// The to convert
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator void*(BufferPointer bufferPointer)
- {
- return (void*)bufferPointer.PointerAtOffset;
- }
-
- ///
- /// Converts instance to a raw 'byte*' pointer
- ///
- /// The to convert
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator byte*(BufferPointer bufferPointer)
- {
- return (byte*)bufferPointer.PointerAtOffset;
- }
-
- ///
- /// Converts instance to
- /// setting it's and to correct values.
- ///
- /// The to convert
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static explicit operator BufferPointer(BufferPointer source)
- {
- BufferPointer result = default(BufferPointer);
- result.Array = Unsafe.As(source.Array);
- result.Offset = source.Offset * Unsafe.SizeOf();
- result.PointerAtOffset = source.PointerAtOffset;
- return result;
- }
-
- ///
- /// Forms a slice out of the given BufferPointer, beginning at 'offset'.
- ///
- /// The offset in number of elements
- /// The offseted (sliced) BufferPointer
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public BufferPointer Slice(int offset)
- {
- BufferPointer result = default(BufferPointer);
- result.Array = this.Array;
- result.Offset = this.Offset + offset;
- result.PointerAtOffset = this.PointerAtOffset + (Unsafe.SizeOf() * offset);
- return result;
- }
-
- ///
- /// Clears `count` elements beginning from the pointed position.
- ///
- /// The number of elements to clear
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Clear(int count)
- {
- if (count < 256)
- {
- Unsafe.InitBlock((void*)this.PointerAtOffset, 0, BufferPointer.USizeOf(count));
- }
- else
- {
- System.Array.Clear(this.Array, this.Offset, count);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Common/Memory/BufferPointer.cs b/src/ImageSharp/Common/Memory/BufferSpan.cs
similarity index 81%
rename from src/ImageSharp/Common/Memory/BufferPointer.cs
rename to src/ImageSharp/Common/Memory/BufferSpan.cs
index 523889611f..42a6fbc6be 100644
--- a/src/ImageSharp/Common/Memory/BufferPointer.cs
+++ b/src/ImageSharp/Common/Memory/BufferSpan.cs
@@ -1,4 +1,4 @@
-//
+//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
@@ -11,9 +11,9 @@ namespace ImageSharp
using System.Runtime.InteropServices;
///
- /// Utility methods for
+ /// Utility methods for
///
- internal static class BufferPointer
+ internal static class BufferSpan
{
///
/// It's worth to use Marshal.Copy() or Buffer.BlockCopy() over this size.
@@ -24,11 +24,11 @@ namespace ImageSharp
/// Copy 'count' number of elements of the same type from 'source' to 'dest'
///
/// The element type.
- /// The input
- /// The destination .
+ /// The input
+ /// The destination .
/// The number of elements to copy
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Copy(BufferPointer source, BufferPointer destination, int count)
+ public static void Copy(BufferSpan source, BufferSpan destination, int count)
where T : struct
{
CopyImpl(source, destination, count);
@@ -42,7 +42,7 @@ namespace ImageSharp
/// The destination buffer.
/// The number of elements to copy from 'source'
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Copy(BufferPointer source, BufferPointer destination, int countInSource)
+ public static void Copy(BufferSpan source, BufferSpan destination, int countInSource)
where T : struct
{
CopyImpl(source, destination, countInSource);
@@ -56,14 +56,14 @@ namespace ImageSharp
/// The destination buffer"/>
/// The number of elements to copy.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static unsafe void Copy(BufferPointer source, BufferPointer destination, int countInDest)
+ public static unsafe void Copy(BufferSpan source, BufferSpan destination, int countInDest)
where T : struct
{
int byteCount = SizeOf(countInDest);
if (byteCount > (int)ByteCountThreshold)
{
- Marshal.Copy(source.Array, source.Offset, destination.PointerAtOffset, byteCount);
+ Marshal.Copy(source.Array, source.Start, destination.PointerAtOffset, byteCount);
}
else
{
@@ -93,7 +93,7 @@ namespace ImageSharp
=> (uint)SizeOf(count);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static unsafe void CopyImpl(BufferPointer source, BufferPointer destination, int count)
+ private static unsafe void CopyImpl(BufferSpan source, BufferSpan destination, int count)
where T : struct
where TDest : struct
{
@@ -103,22 +103,22 @@ namespace ImageSharp
{
if (Unsafe.SizeOf() == sizeof(long))
{
- Marshal.Copy(Unsafe.As(source.Array), source.Offset, destination.PointerAtOffset, count);
+ Marshal.Copy(Unsafe.As(source.Array), source.Start, destination.PointerAtOffset, count);
return;
}
else if (Unsafe.SizeOf() == sizeof(int))
{
- Marshal.Copy(Unsafe.As(source.Array), source.Offset, destination.PointerAtOffset, count);
+ Marshal.Copy(Unsafe.As(source.Array), source.Start, destination.PointerAtOffset, count);
return;
}
else if (Unsafe.SizeOf() == sizeof(short))
{
- Marshal.Copy(Unsafe.As(source.Array), source.Offset, destination.PointerAtOffset, count);
+ Marshal.Copy(Unsafe.As(source.Array), source.Start, destination.PointerAtOffset, count);
return;
}
else if (Unsafe.SizeOf() == sizeof(byte))
{
- Marshal.Copy(Unsafe.As(source.Array), source.Offset, destination.PointerAtOffset, count);
+ Marshal.Copy(Unsafe.As(source.Array), source.Start, destination.PointerAtOffset, count);
return;
}
}
diff --git a/src/ImageSharp/Common/Memory/BufferSpan{T}.cs b/src/ImageSharp/Common/Memory/BufferSpan{T}.cs
new file mode 100644
index 0000000000..0507173e90
--- /dev/null
+++ b/src/ImageSharp/Common/Memory/BufferSpan{T}.cs
@@ -0,0 +1,209 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp
+{
+ using System;
+ using System.Diagnostics;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+
+ ///
+ /// Represents a contiguous region of a pinned managed array.
+ /// The array is usually owned by a instance.
+ ///
+ ///
+ /// is very similar to corefx System.Span<T>, and we try to maintain a compatible API.
+ /// There are several differences though:
+ /// - It's not possible to use it with stack objects or pointers to unmanaged memory, only with managed arrays.
+ /// - It's possible to retrieve a reference to the array () so we can pass it to API-s like
+ /// - It's possible to retrieve the pinned pointer. This enables optimized (unchecked) unsafe operations.
+ /// - There is no bounds checking for performance reasons, only in debug mode. This makes an unsafe type!
+ ///
+ /// The type of elements of the array
+ internal unsafe struct BufferSpan
+ where T : struct
+ {
+ ///
+ /// Initializes a new instance of the struct from a pinned array and an start.
+ ///
+ /// The pinned array
+ /// Pointer to the beginning of the array
+ /// The index at which to begin the span.
+ /// The length
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public BufferSpan(T[] array, void* pointerToArray, int start, int length)
+ {
+ GuardArrayAndPointer(array, pointerToArray);
+
+ DebugGuard.MustBeLessThanOrEqualTo(start, array.Length, nameof(start));
+ DebugGuard.MustBeLessThanOrEqualTo(length, array.Length - start, nameof(length));
+
+ this.Array = array;
+ this.Length = length;
+ this.Start = start;
+ this.PointerAtOffset = (IntPtr)pointerToArray + (Unsafe.SizeOf() * start);
+ }
+
+ ///
+ /// Initializes a new instance of the struct from a pinned array and an start.
+ ///
+ /// The pinned array
+ /// Pointer to the beginning of the array
+ /// The index at which to begin the span.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public BufferSpan(T[] array, void* pointerToArray, int start)
+ {
+ GuardArrayAndPointer(array, pointerToArray);
+ DebugGuard.MustBeLessThanOrEqualTo(start, array.Length, nameof(start));
+
+ this.Array = array;
+ this.Length = array.Length - start;
+ this.Start = start;
+ this.PointerAtOffset = (IntPtr)pointerToArray + (Unsafe.SizeOf() * start);
+ }
+
+ ///
+ /// Initializes a new instance of the struct from a pinned array.
+ ///
+ /// The pinned array
+ /// Pointer to the start of 'array'
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public BufferSpan(T[] array, void* pointerToArray)
+ {
+ GuardArrayAndPointer(array, pointerToArray);
+
+ this.Array = array;
+ this.Start = 0;
+ this.Length = array.Length;
+ this.PointerAtOffset = (IntPtr)pointerToArray;
+ }
+
+ ///
+ /// Gets the backing array
+ ///
+ public T[] Array { get; private set; }
+
+ ///
+ /// Gets the length of the
+ ///
+ public int Length { get; private set; }
+
+ ///
+ /// Gets the start inside
+ ///
+ public int Start { get; private set; }
+
+ ///
+ /// Gets the start inside in bytes.
+ ///
+ public int ByteOffset => this.Start * Unsafe.SizeOf();
+
+ ///
+ /// Gets the pointer to the offseted array position
+ ///
+ public IntPtr PointerAtOffset { get; private set; }
+
+ ///
+ /// Convertes instance to a raw 'void*' pointer
+ ///
+ /// The to convert
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static explicit operator void*(BufferSpan bufferSpan)
+ {
+ return (void*)bufferSpan.PointerAtOffset;
+ }
+
+ ///
+ /// Converts instance to a raw 'byte*' pointer
+ ///
+ /// The to convert
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static explicit operator byte*(BufferSpan bufferSpan)
+ {
+ return (byte*)bufferSpan.PointerAtOffset;
+ }
+
+ ///
+ /// Converts generic to a of bytes
+ /// setting it's and to correct values.
+ ///
+ /// The to convert
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static explicit operator BufferSpan(BufferSpan source)
+ {
+ BufferSpan result = default(BufferSpan);
+ result.Array = Unsafe.As(source.Array);
+ result.Start = source.Start * Unsafe.SizeOf();
+ result.PointerAtOffset = source.PointerAtOffset;
+ return result;
+ }
+
+ ///
+ /// Forms a slice out of the given BufferSpan, beginning at 'start'.
+ ///
+ /// TThe index at which to begin this slice.
+ /// The offseted (sliced) BufferSpan
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public BufferSpan Slice(int start)
+ {
+ DebugGuard.MustBeLessThan(start, this.Length, nameof(start));
+
+ BufferSpan result = default(BufferSpan);
+ result.Array = this.Array;
+ result.Start = this.Start + start;
+ result.PointerAtOffset = this.PointerAtOffset + (Unsafe.SizeOf() * start);
+ result.Length = this.Length - start;
+ return result;
+ }
+
+ ///
+ /// Forms a slice out of the given BufferSpan, beginning at 'start'.
+ ///
+ /// The index at which to begin this slice.
+ /// The desired length for the slice (exclusive).
+ /// The sliced BufferSpan
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public BufferSpan Slice(int start, int length)
+ {
+ DebugGuard.MustBeLessThanOrEqualTo(start, this.Length, nameof(start));
+ DebugGuard.MustBeLessThanOrEqualTo(length, this.Length - start, nameof(length));
+
+ BufferSpan result = default(BufferSpan);
+ result.Array = this.Array;
+ result.Start = this.Start + start;
+ result.PointerAtOffset = this.PointerAtOffset + (Unsafe.SizeOf() * start);
+ result.Length = length;
+ return result;
+ }
+
+ ///
+ /// Clears `count` elements beginning from the pointed position.
+ ///
+ /// The number of elements to clear
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void Clear(int count)
+ {
+ if (count < 256)
+ {
+ Unsafe.InitBlock((void*)this.PointerAtOffset, 0, BufferSpan.USizeOf(count));
+ }
+ else
+ {
+ System.Array.Clear(this.Array, this.Start, count);
+ }
+ }
+
+ [Conditional("DEBUG")]
+ private static void GuardArrayAndPointer(T[] array, void* pointerToArray)
+ {
+ DebugGuard.NotNull(array, nameof(array));
+ DebugGuard.IsFalse(
+ pointerToArray == (void*)0,
+ nameof(pointerToArray),
+ "pointerToArray should not be null pointer!");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Common/Memory/PinnedBuffer{T}.cs b/src/ImageSharp/Common/Memory/PinnedBuffer{T}.cs
index d002e08fbd..7378a8d640 100644
--- a/src/ImageSharp/Common/Memory/PinnedBuffer{T}.cs
+++ b/src/ImageSharp/Common/Memory/PinnedBuffer{T}.cs
@@ -32,11 +32,11 @@ namespace ImageSharp
///
/// Initializes a new instance of the class.
///
- /// The desired count of elements. (Minimum size for )
- public PinnedBuffer(int count)
+ /// The desired count of elements. (Minimum size for )
+ public PinnedBuffer(int length)
{
- this.Count = count;
- this.Array = PixelDataPool.Rent(count);
+ this.Length = length;
+ this.Array = PixelDataPool.Rent(length);
this.isPoolingOwner = true;
this.Pin();
}
@@ -47,7 +47,7 @@ namespace ImageSharp
/// The array to pin.
public PinnedBuffer(T[] array)
{
- this.Count = array.Length;
+ this.Length = array.Length;
this.Array = array;
this.isPoolingOwner = false;
this.Pin();
@@ -56,16 +56,16 @@ namespace ImageSharp
///
/// Initializes a new instance of the class.
///
- /// The count of "relevant" elements in 'array'.
+ /// The count of "relevant" elements in 'array'.
/// The array to pin.
- public PinnedBuffer(int count, T[] array)
+ public PinnedBuffer(int length, T[] array)
{
- if (array.Length < count)
+ if (array.Length < length)
{
throw new ArgumentException("Can't initialize a PinnedBuffer with array.Length < count", nameof(array));
}
- this.Count = count;
+ this.Length = length;
this.Array = array;
this.isPoolingOwner = false;
this.Pin();
@@ -85,9 +85,9 @@ namespace ImageSharp
public bool IsDisposedOrLostArrayOwnership { get; private set; }
///
- /// Gets the count of "relevant" elements. Usually be smaller than 'Array.Length' when is pooled.
+ /// Gets the count of "relevant" elements. It's usually smaller than 'Array.Length' when is pooled.
///
- public int Count { get; private set; }
+ public int Length { get; private set; }
///
/// Gets the backing pinned array.
@@ -100,11 +100,11 @@ namespace ImageSharp
public IntPtr Pointer { get; private set; }
///
- /// Converts to an .
+ /// Converts to an .
///
/// The to convert.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator BufferPointer(PinnedBuffer buffer)
+ public static implicit operator BufferSpan(PinnedBuffer buffer)
{
return buffer.Slice();
}
@@ -122,24 +122,24 @@ namespace ImageSharp
}
///
- /// Gets a to the beginning of the raw data of the buffer.
+ /// Gets a to the beginning of the raw data of the buffer.
///
- /// The
+ /// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe BufferPointer Slice()
+ public unsafe BufferSpan Slice()
{
- return new BufferPointer(this.Array, (void*)this.Pointer);
+ return new BufferSpan(this.Array, (void*)this.Pointer);
}
///
- /// Gets a to an offseted position inside the buffer.
+ /// Gets a to an offseted position inside the buffer.
///
/// The offset
- /// The
+ /// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe BufferPointer Slice(int offset)
+ public unsafe BufferSpan Slice(int offset)
{
- return new BufferPointer(this.Array, (void*)this.Pointer, offset);
+ return new BufferSpan(this.Array, (void*)this.Pointer, offset);
}
///
@@ -163,7 +163,7 @@ namespace ImageSharp
this.isPoolingOwner = false;
this.Array = null;
- this.Count = 0;
+ this.Length = 0;
GC.SuppressFinalize(this);
}
@@ -190,12 +190,12 @@ namespace ImageSharp
}
///
- /// Clears the buffer, filling elements between 0 and -1 with default(T)
+ /// Clears the buffer, filling elements between 0 and -1 with default(T)
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear()
{
- this.Slice().Clear(this.Count);
+ this.Slice().Clear(this.Length);
}
///
diff --git a/src/ImageSharp/Image/PixelAccessor{TColor}.cs b/src/ImageSharp/Image/PixelAccessor{TColor}.cs
index 25e232cf86..d22deec742 100644
--- a/src/ImageSharp/Image/PixelAccessor{TColor}.cs
+++ b/src/ImageSharp/Image/PixelAccessor{TColor}.cs
@@ -239,12 +239,12 @@ namespace ImageSharp
}
///
- /// Gets a to the row 'y' beginning from the pixel at 'x'.
+ /// Gets a to the row 'y' beginning from the pixel at 'x'.
///
/// The x coordinate
/// The y coordinate
- /// The
- internal BufferPointer GetRowPointer(int x, int y)
+ /// The
+ internal BufferSpan GetRowPointer(int x, int y)
{
return this.pixelBuffer.Slice((y * this.Width) + x);
}
@@ -288,8 +288,8 @@ namespace ImageSharp
{
for (int y = 0; y < height; y++)
{
- BufferPointer source = area.GetRowPointer(y);
- BufferPointer destination = this.GetRowPointer(targetX, targetY + y);
+ BufferSpan source = area.GetRowPointer(y);
+ BufferSpan destination = this.GetRowPointer(targetX, targetY + y);
Operations.PackFromZyxBytes(source, destination, width);
}
@@ -308,8 +308,8 @@ namespace ImageSharp
{
for (int y = 0; y < height; y++)
{
- BufferPointer source = area.GetRowPointer(y);
- BufferPointer destination = this.GetRowPointer(targetX, targetY + y);
+ BufferSpan source = area.GetRowPointer(y);
+ BufferSpan destination = this.GetRowPointer(targetX, targetY + y);
Operations.PackFromZyxwBytes(source, destination, width);
}
@@ -328,8 +328,8 @@ namespace ImageSharp
{
for (int y = 0; y < height; y++)
{
- BufferPointer source = area.GetRowPointer(y);
- BufferPointer destination = this.GetRowPointer(targetX, targetY + y);
+ BufferSpan source = area.GetRowPointer(y);
+ BufferSpan destination = this.GetRowPointer(targetX, targetY + y);
Operations.PackFromXyzBytes(source, destination, width);
}
@@ -348,8 +348,8 @@ namespace ImageSharp
{
for (int y = 0; y < height; y++)
{
- BufferPointer source = area.GetRowPointer(y);
- BufferPointer destination = this.GetRowPointer(targetX, targetY + y);
+ BufferSpan source = area.GetRowPointer(y);
+ BufferSpan destination = this.GetRowPointer(targetX, targetY + y);
Operations.PackFromXyzwBytes(source, destination, width);
}
}
@@ -367,8 +367,8 @@ namespace ImageSharp
{
for (int y = 0; y < height; y++)
{
- BufferPointer source = this.GetRowPointer(sourceX, sourceY + y);
- BufferPointer destination = area.GetRowPointer(y);
+ BufferSpan source = this.GetRowPointer(sourceX, sourceY + y);
+ BufferSpan destination = area.GetRowPointer(y);
Operations.ToZyxBytes(source, destination, width);
}
}
@@ -386,8 +386,8 @@ namespace ImageSharp
{
for (int y = 0; y < height; y++)
{
- BufferPointer source = this.GetRowPointer(sourceX, sourceY + y);
- BufferPointer destination = area.GetRowPointer(y);
+ BufferSpan source = this.GetRowPointer(sourceX, sourceY + y);
+ BufferSpan destination = area.GetRowPointer(y);
Operations.ToZyxwBytes(source, destination, width);
}
}
@@ -405,8 +405,8 @@ namespace ImageSharp
{
for (int y = 0; y < height; y++)
{
- BufferPointer source = this.GetRowPointer(sourceX, sourceY + y);
- BufferPointer destination = area.GetRowPointer(y);
+ BufferSpan source = this.GetRowPointer(sourceX, sourceY + y);
+ BufferSpan destination = area.GetRowPointer(y);
Operations.ToXyzBytes(source, destination, width);
}
}
@@ -424,8 +424,8 @@ namespace ImageSharp
{
for (int y = 0; y < height; y++)
{
- BufferPointer source = this.GetRowPointer(sourceX, sourceY + y);
- BufferPointer destination = area.GetRowPointer(y);
+ BufferSpan source = this.GetRowPointer(sourceX, sourceY + y);
+ BufferSpan destination = area.GetRowPointer(y);
Operations.ToXyzwBytes(source, destination, width);
}
}
diff --git a/src/ImageSharp/Image/PixelArea{TColor}.cs b/src/ImageSharp/Image/PixelArea{TColor}.cs
index 8f2fa5b7a1..0a3c5710ce 100644
--- a/src/ImageSharp/Image/PixelArea{TColor}.cs
+++ b/src/ImageSharp/Image/PixelArea{TColor}.cs
@@ -202,11 +202,11 @@ namespace ImageSharp
}
///
- /// Gets a to the row y.
+ /// Gets a to the row y.
///
/// The y coordinate
- /// The
- internal BufferPointer GetRowPointer(int y)
+ /// The
+ internal BufferSpan GetRowPointer(int y)
{
return this.byteBuffer.Slice(y * this.RowStride);
}
diff --git a/tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs b/tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs
index fa950c4cf2..141c9d888d 100644
--- a/tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs
+++ b/tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs
@@ -314,8 +314,8 @@ namespace ImageSharp.Tests.Colors
public PinnedBuffer ActualDestBuffer { get; }
public PinnedBuffer ExpectedDestBuffer { get; }
- public BufferPointer Source => this.SourceBuffer.Slice();
- public BufferPointer ActualDest => this.ActualDestBuffer.Slice();
+ public BufferSpan Source => this.SourceBuffer.Slice();
+ public BufferSpan ActualDest => this.ActualDestBuffer.Slice();
public TestBuffers(TSource[] source, TDest[] expectedDest)
{
@@ -335,7 +335,7 @@ namespace ImageSharp.Tests.Colors
public void Verify()
{
- int count = this.ExpectedDestBuffer.Count;
+ int count = this.ExpectedDestBuffer.Length;
if (typeof(TDest) == typeof(Vector4))
{
@@ -364,7 +364,7 @@ namespace ImageSharp.Tests.Colors
internal static void TestOperation(
TSource[] source,
TDest[] expected,
- Action, BufferPointer> action)
+ Action, BufferSpan> action)
where TSource : struct
where TDest : struct
{
diff --git a/tests/ImageSharp.Tests/Common/BufferPointerTests.cs b/tests/ImageSharp.Tests/Common/BufferSpanTests.cs
similarity index 66%
rename from tests/ImageSharp.Tests/Common/BufferPointerTests.cs
rename to tests/ImageSharp.Tests/Common/BufferSpanTests.cs
index c82b63f115..f524bdb437 100644
--- a/tests/ImageSharp.Tests/Common/BufferPointerTests.cs
+++ b/tests/ImageSharp.Tests/Common/BufferSpanTests.cs
@@ -7,7 +7,7 @@ namespace ImageSharp.Tests.Common
using Xunit;
- public unsafe class BufferPointerTests
+ public unsafe class BufferSpanTests
{
public struct Foo
{
@@ -70,68 +70,122 @@ namespace ImageSharp.Tests.Common
using (PinnedBuffer colorBuf = new PinnedBuffer(fooz))
{
- BufferPointer orig = colorBuf.Slice(1);
- BufferPointer asBytes = (BufferPointer < byte > )orig;
+ BufferSpan orig = colorBuf.Slice(1);
+ BufferSpan asBytes = (BufferSpan < byte > )orig;
- Assert.Equal(asBytes.Offset, sizeof(Foo));
+ Assert.Equal(asBytes.Start, sizeof(Foo));
Assert.Equal(orig.PointerAtOffset, asBytes.PointerAtOffset);
}
}
-
- [Fact]
- public void ConstructWithoutOffset()
+
+ public class Construct
{
- Foo[] array = Foo.CreateArray(3);
- fixed (Foo* p = array)
+ [Fact]
+ public void Basic()
{
- // Act:
- BufferPointer ap = new BufferPointer(array, p);
+ Foo[] array = Foo.CreateArray(3);
+ fixed (Foo* p = array)
+ {
+ // Act:
+ BufferSpan span = new BufferSpan(array, p);
- // Assert:
- Assert.Equal(array, ap.Array);
- Assert.Equal((IntPtr)p, ap.PointerAtOffset);
+ // Assert:
+ Assert.Equal(array, span.Array);
+ Assert.Equal((IntPtr)p, span.PointerAtOffset);
+ Assert.Equal(3, span.Length);
+ }
}
- }
- [Fact]
- public void ConstructWithOffset()
- {
- Foo[] array = Foo.CreateArray(3);
- int offset = 2;
- fixed (Foo* p = array)
+ [Fact]
+ public void WithStart()
{
- // Act:
- BufferPointer ap = new BufferPointer(array, p, offset);
+ Foo[] array = Foo.CreateArray(4);
+ int start = 2;
+ fixed (Foo* p = array)
+ {
+ // Act:
+ BufferSpan span = new BufferSpan(array, p, start);
+
+ // Assert:
+ Assert.Equal(array, span.Array);
+ Assert.Equal(start, span.Start);
+ Assert.Equal((IntPtr)(p + start), span.PointerAtOffset);
+ Assert.Equal(array.Length - start, span.Length);
+ }
+ }
- // Assert:
- Assert.Equal(array, ap.Array);
- Assert.Equal(offset, ap.Offset);
- Assert.Equal((IntPtr)(p+offset), ap.PointerAtOffset);
+ [Fact]
+ public void WithStartAndLength()
+ {
+ Foo[] array = Foo.CreateArray(10);
+ int start = 2;
+ int length = 3;
+ fixed (Foo* p = array)
+ {
+ // Act:
+ BufferSpan span = new BufferSpan(array, p, start, length);
+
+ // Assert:
+ Assert.Equal(array, span.Array);
+ Assert.Equal(start, span.Start);
+ Assert.Equal((IntPtr)(p + start), span.PointerAtOffset);
+ Assert.Equal(length, span.Length);
+ }
}
}
- [Fact]
- public void Slice()
+ public class Slice
{
- Foo[] array = Foo.CreateArray(5);
- int offset0 = 2;
- int offset1 = 2;
- int totalOffset = offset0 + offset1;
- fixed (Foo* p = array)
+ [Fact]
+ public void StartOnly()
{
- BufferPointer ap = new BufferPointer(array, p, offset0);
+ Foo[] array = Foo.CreateArray(5);
+ int start0 = 2;
+ int start1 = 2;
+ int totalOffset = start0 + start1;
- // Act:
- ap = ap.Slice(offset1);
+ fixed (Foo* p = array)
+ {
+ BufferSpan span = new BufferSpan(array, p, start0);
+
+ // Act:
+ span = span.Slice(start1);
- // Assert:
- Assert.Equal(array, ap.Array);
- Assert.Equal(totalOffset, ap.Offset);
- Assert.Equal((IntPtr)(p + totalOffset), ap.PointerAtOffset);
+ // Assert:
+ Assert.Equal(array, span.Array);
+ Assert.Equal(totalOffset, span.Start);
+ Assert.Equal((IntPtr)(p + totalOffset), span.PointerAtOffset);
+ Assert.Equal(array.Length - totalOffset, span.Length);
+ }
+ }
+
+ [Fact]
+ public void StartAndLength()
+ {
+ Foo[] array = Foo.CreateArray(10);
+ int start0 = 2;
+ int start1 = 2;
+ int totalOffset = start0 + start1;
+ int sliceLength = 3;
+
+ fixed (Foo* p = array)
+ {
+ BufferSpan span = new BufferSpan(array, p, start0);
+
+ // Act:
+ span = span.Slice(start1, sliceLength);
+
+ // Assert:
+ Assert.Equal(array, span.Array);
+ Assert.Equal(totalOffset, span.Start);
+ Assert.Equal((IntPtr)(p + totalOffset), span.PointerAtOffset);
+ Assert.Equal(sliceLength, span.Length);
+ }
}
}
+
[Theory]
[InlineData(4)]
[InlineData(1500)]
@@ -142,7 +196,7 @@ namespace ImageSharp.Tests.Common
int offset = 2;
fixed (Foo* p = array)
{
- BufferPointer ap = new BufferPointer(array, p, offset);
+ BufferSpan ap = new BufferSpan