Browse Source

introduce BufferArea2D, move Memory utility tests to proper place

af/merge-core
Anton Firszov 9 years ago
parent
commit
5ec9310d73
  1. 2
      src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
  2. 33
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/ComponentPostprocessor.cs
  3. 14
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockPostProcessor.cs
  4. 11
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs
  5. 14
      src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
  6. 25
      src/ImageSharp/Memory/Buffer2DExtensions.cs
  7. 30
      src/ImageSharp/Memory/BufferArea2D.cs
  8. 38
      tests/ImageSharp.Tests/Memory/Buffer2DTests.cs
  9. 77
      tests/ImageSharp.Tests/Memory/BufferTests.cs
  10. 12
      tests/ImageSharp.Tests/Memory/Fast2DArrayTests.cs
  11. 11
      tests/ImageSharp.Tests/Memory/PixelDataPoolTests.cs
  12. 185
      tests/ImageSharp.Tests/Memory/SpanUtilityTests.cs
  13. 6
      tests/ImageSharp.Tests/Memory/TestStructs.cs

2
src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs

@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
short* fp = blockPtr->data;
fp[idx] = value;
}
public Block8x8F AsFloatBlock()
{
// TODO: Optimize this

33
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/ComponentPostprocessor.cs

@ -0,0 +1,33 @@
using System;
using SixLabors.ImageSharp.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
{
internal class ComponentPostProcessor : IDisposable
{
public Size ImageSizeInBlocks { get; }
public int NumberOfRowGroupScans
{
get;
}
class RowGroupProcessor : IDisposable
{
public Buffer2D<float> ColorBuffer { get; }
public void Dispose()
{
}
}
public void Dispose()
{
}
}
}

14
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockProcessor.cs → src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockPostProcessor.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// Encapsulates the implementation of processing "raw" <see cref="Buffer{T}"/>-s into Jpeg image channels.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct JpegBlockProcessor
internal unsafe struct JpegBlockPostProcessor
{
/// <summary>
/// The <see cref="ComputationData"/>
@ -30,15 +30,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
private int componentIndex;
/// <summary>
/// Initialize the <see cref="JpegBlockProcessor"/> instance on the stack.
/// Initialize the <see cref="JpegBlockPostProcessor"/> instance on the stack.
/// </summary>
/// <param name="processor">The <see cref="JpegBlockProcessor"/> instance</param>
/// <param name="postProcessor">The <see cref="JpegBlockPostProcessor"/> instance</param>
/// <param name="componentIndex">The current component index</param>
public static void Init(JpegBlockProcessor* processor, int componentIndex)
public static void Init(JpegBlockPostProcessor* postProcessor, int componentIndex)
{
processor->componentIndex = componentIndex;
processor->data = ComputationData.Create();
processor->pointers = new DataPointers(&processor->data);
postProcessor->componentIndex = componentIndex;
postProcessor->data = ComputationData.Create();
postProcessor->pointers = new DataPointers(&postProcessor->data);
}
/// <summary>

11
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs

@ -669,17 +669,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
int val = bu >= 0 ? bu + delta : bu - delta;
Block8x8.SetScalarAt(b, u, (short)val);
//if (bu >= 0)
//{
// // b[u] += delta;
// Block8x8.SetScalarAt(b, u, bu + delta);
//}
//else
//{
// // b[u] -= delta;
// Block8x8.SetScalarAt(b, u, bu - delta);
//}
}
return zig;

14
src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs

@ -3,23 +3,21 @@
using System;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.MetaData.Profiles.Icc;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
using Block8x8F = SixLabors.ImageSharp.Formats.Jpeg.Common.Block8x8F;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
{
using System.Linq;
using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.Primitives;
/// <summary>
/// Performs the jpeg decoding operation.
/// </summary>
@ -476,9 +474,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
this.ComponentCount,
componentIndex =>
{
JpegBlockProcessor processor = default(JpegBlockProcessor);
JpegBlockProcessor.Init(&processor, componentIndex);
processor.ProcessAllBlocks(this);
JpegBlockPostProcessor postProcessor = default(JpegBlockPostProcessor);
JpegBlockPostProcessor.Init(&postProcessor, componentIndex);
postProcessor.ProcessAllBlocks(this);
});
}

25
src/ImageSharp/Memory/Buffer2DExtensions.cs

@ -3,6 +3,7 @@
using System;
using System.Runtime.CompilerServices;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Memory
{
@ -39,5 +40,29 @@ namespace SixLabors.ImageSharp.Memory
{
return buffer.Span.Slice(y * buffer.Width, buffer.Width);
}
/// <summary>
/// Returns the size of the buffer.
/// </summary>
/// <typeparam name="T">The element type</typeparam>
/// <param name="buffer">The <see cref="IBuffer2D{T}"/></param>
/// <returns>The <see cref="Size{T}"/> of the buffer</returns>
public static Size Size<T>(this IBuffer2D<T> buffer)
where T : struct
{
return new Size(buffer.Width, buffer.Height);
}
/// <summary>
/// Returns a <see cref="Rectangle"/> representing the full area of the buffer.
/// </summary>
/// <typeparam name="T">The element type</typeparam>
/// <param name="buffer">The <see cref="IBuffer2D{T}"/></param>
/// <returns>The <see cref="Rectangle"/></returns>
public static Rectangle FullRectangle<T>(this IBuffer2D<T> buffer)
where T : struct
{
return new Rectangle(0, 0, buffer.Width, buffer.Height);
}
}
}

30
src/ImageSharp/Memory/BufferArea2D.cs

@ -0,0 +1,30 @@
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Represents a rectangular area inside a 2D memory buffer. (Most commonly <see cref="Buffer2D{T}"/>)
/// This type is kind-of 2D Span.
/// </summary>
/// <typeparam name="T">The element type</typeparam>
internal struct BufferArea2D<T>
where T : struct
{
public IBuffer2D<T> DestinationBuffer { get; }
public readonly Rectangle Rectangle;
public BufferArea2D(IBuffer2D<T> destinationBuffer, Rectangle rectangle)
{
this.DestinationBuffer = destinationBuffer;
this.Rectangle = rectangle;
}
public BufferArea2D(Buffer2D<T> destinationBuffer)
: this(destinationBuffer, destinationBuffer.FullRectangle())
{
}
public Size Size => this.Rectangle.Size;
}
}

38
tests/ImageSharp.Tests/Common/Buffer2DTests.cs → tests/ImageSharp.Tests/Memory/Buffer2DTests.cs

@ -1,14 +1,16 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using Xunit;
using static SixLabors.ImageSharp.Tests.Common.TestStructs;
namespace SixLabors.ImageSharp.Tests.Common
namespace SixLabors.ImageSharp.Tests.Memory
{
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Tests.Common;
using Xunit;
public unsafe class Buffer2DTests
{
// ReSharper disable once ClassNeverInstantiated.Local
@ -29,7 +31,7 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(1025, 17)]
public void Construct(int width, int height)
{
using (Buffer2D<Foo> buffer = new Buffer2D<Foo>(width, height))
using (Buffer2D<TestStructs.Foo> buffer = new Buffer2D<TestStructs.Foo>(width, height))
{
Assert.Equal(width, buffer.Width);
Assert.Equal(height, buffer.Height);
@ -42,8 +44,8 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(1025, 17)]
public void Construct_FromExternalArray(int width, int height)
{
Foo[] array = new Foo[width * height + 10];
using (Buffer2D<Foo> buffer = new Buffer2D<Foo>(array, width, height))
TestStructs.Foo[] array = new TestStructs.Foo[width * height + 10];
using (Buffer2D<TestStructs.Foo> buffer = new Buffer2D<TestStructs.Foo>(array, width, height))
{
Assert.Equal(width, buffer.Width);
Assert.Equal(height, buffer.Height);
@ -74,9 +76,9 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(17, 42, 41)]
public void GetRowSpanY(int width, int height, int y)
{
using (Buffer2D<Foo> buffer = new Buffer2D<Foo>(width, height))
using (Buffer2D<TestStructs.Foo> buffer = new Buffer2D<TestStructs.Foo>(width, height))
{
Span<Foo> span = buffer.GetRowSpan(y);
Span<TestStructs.Foo> span = buffer.GetRowSpan(y);
// Assert.Equal(width * y, span.Start);
Assert.Equal(width, span.Length);
@ -90,9 +92,9 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(17, 42, 0, 41)]
public void GetRowSpanXY(int width, int height, int x, int y)
{
using (Buffer2D<Foo> buffer = new Buffer2D<Foo>(width, height))
using (Buffer2D<TestStructs.Foo> buffer = new Buffer2D<TestStructs.Foo>(width, height))
{
Span<Foo> span = buffer.GetRowSpan(x, y);
Span<TestStructs.Foo> span = buffer.GetRowSpan(x, y);
// Assert.Equal(width * y + x, span.Start);
Assert.Equal(width - x, span.Length);
@ -106,13 +108,13 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(99, 88, 98, 87)]
public void Indexer(int width, int height, int x, int y)
{
using (Buffer2D<Foo> buffer = new Buffer2D<Foo>(width, height))
using (Buffer2D<TestStructs.Foo> buffer = new Buffer2D<TestStructs.Foo>(width, height))
{
Foo[] array = buffer.Array;
TestStructs.Foo[] array = buffer.Array;
ref Foo actual = ref buffer[x, y];
ref TestStructs.Foo actual = ref buffer[x, y];
ref Foo expected = ref array[y * width + x];
ref TestStructs.Foo expected = ref array[y * width + x];
Assert.True(Unsafe.AreSame(ref expected, ref actual));
}

77
tests/ImageSharp.Tests/Common/BufferTests.cs → tests/ImageSharp.Tests/Memory/BufferTests.cs

@ -1,16 +1,15 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Memory;
using Xunit;
using static SixLabors.ImageSharp.Tests.Common.TestStructs;
namespace SixLabors.ImageSharp.Tests.Common
namespace SixLabors.ImageSharp.Tests.Memory
{
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using Xunit;
public unsafe class BufferTests
{
// ReSharper disable once ClassNeverInstantiated.Local
@ -36,7 +35,7 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(1111)]
public void ConstructWithOwnArray(int count)
{
using (Buffer<Foo> buffer = new Buffer<Foo>(count))
using (Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(count))
{
Assert.False(buffer.IsDisposedOrLostArrayOwnership);
Assert.NotNull(buffer.Array);
@ -50,8 +49,8 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(1111)]
public void ConstructWithExistingArray(int count)
{
Foo[] array = new Foo[count];
using (Buffer<Foo> buffer = new Buffer<Foo>(array))
TestStructs.Foo[] array = new TestStructs.Foo[count];
using (Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(array))
{
Assert.False(buffer.IsDisposedOrLostArrayOwnership);
Assert.Equal(array, buffer.Array);
@ -62,13 +61,13 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void Clear()
{
Foo[] a = { new Foo() { A = 1, B = 2 }, new Foo() { A = 3, B = 4 } };
using (Buffer<Foo> buffer = new Buffer<Foo>(a))
TestStructs.Foo[] a = { new TestStructs.Foo() { A = 1, B = 2 }, new TestStructs.Foo() { A = 3, B = 4 } };
using (Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(a))
{
buffer.Clear();
Assert.Equal(default(Foo), a[0]);
Assert.Equal(default(Foo), a[1]);
Assert.Equal(default(TestStructs.Foo), a[0]);
Assert.Equal(default(TestStructs.Foo), a[1]);
}
}
@ -102,11 +101,11 @@ namespace SixLabors.ImageSharp.Tests.Common
[MemberData(nameof(IndexerData))]
public void Read(int length, int index)
{
Foo[] a = Foo.CreateArray(length);
TestStructs.Foo[] a = TestStructs.Foo.CreateArray(length);
using (Buffer<Foo> buffer = new Buffer<Foo>(a))
using (Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(a))
{
Foo element = buffer[index];
TestStructs.Foo element = buffer[index];
Assert.Equal(a[index], element);
}
@ -116,13 +115,13 @@ namespace SixLabors.ImageSharp.Tests.Common
[MemberData(nameof(IndexerData))]
public void Write(int length, int index)
{
Foo[] a = Foo.CreateArray(length);
TestStructs.Foo[] a = TestStructs.Foo.CreateArray(length);
using (Buffer<Foo> buffer = new Buffer<Foo>(a))
using (Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(a))
{
buffer[index] = new Foo(666, 666);
buffer[index] = new TestStructs.Foo(666, 666);
Assert.Equal(new Foo(666, 666), a[index]);
Assert.Equal(new TestStructs.Foo(666, 666), a[index]);
}
}
}
@ -130,7 +129,7 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void Dispose()
{
Buffer<Foo> buffer = new Buffer<Foo>(42);
Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(42);
buffer.Dispose();
Assert.True(buffer.IsDisposedOrLostArrayOwnership);
@ -141,9 +140,9 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(123)]
public void CastToSpan(int bufferLength)
{
using (Buffer<Foo> buffer = new Buffer<Foo>(bufferLength))
using (Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(bufferLength))
{
Span<Foo> span = buffer;
Span<TestStructs.Foo> span = buffer;
//Assert.Equal(buffer.Array, span.ToArray());
//Assert.Equal(0, span.Start);
@ -155,9 +154,9 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void Span()
{
using (Buffer<Foo> buffer = new Buffer<Foo>(42))
using (Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(42))
{
Span<Foo> span = buffer.Span;
Span<TestStructs.Foo> span = buffer.Span;
// Assert.Equal(buffer.Array, span.ToArray());
// Assert.Equal(0, span.Start);
@ -174,9 +173,9 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(123, 17)]
public void WithStartOnly(int bufferLength, int start)
{
using (Buffer<Foo> buffer = new Buffer<Foo>(bufferLength))
using (Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(bufferLength))
{
Span<Foo> span = buffer.Slice(start);
Span<TestStructs.Foo> span = buffer.Slice(start);
Assert.SpanPointsTo(span, buffer, start);
Assert.Equal(span.Length, bufferLength - start);
@ -188,9 +187,9 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(123, 17, 42)]
public void WithStartAndLength(int bufferLength, int start, int spanLength)
{
using (Buffer<Foo> buffer = new Buffer<Foo>(bufferLength))
using (Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(bufferLength))
{
Span<Foo> span = buffer.Slice(start, spanLength);
Span<TestStructs.Foo> span = buffer.Slice(start, spanLength);
Assert.SpanPointsTo(span, buffer, start);
Assert.Equal(span.Length, spanLength);
@ -201,8 +200,8 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void UnPinAndTakeArrayOwnership()
{
Foo[] data = null;
using (Buffer<Foo> buffer = new Buffer<Foo>(42))
TestStructs.Foo[] data = null;
using (Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(42))
{
data = buffer.TakeArrayOwnership();
Assert.True(buffer.IsDisposedOrLostArrayOwnership);
@ -217,10 +216,10 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void ReturnsPinnedPointerToTheBeginningOfArray()
{
using (Buffer<Foo> buffer = new Buffer<Foo>(42))
using (Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(42))
{
Foo* actual = (Foo*)buffer.Pin();
fixed (Foo* expected = buffer.Array)
TestStructs.Foo* actual = (TestStructs.Foo*)buffer.Pin();
fixed (TestStructs.Foo* expected = buffer.Array)
{
Assert.Equal(expected, actual);
}
@ -230,7 +229,7 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void SecondCallReturnsTheSamePointer()
{
using (Buffer<Foo> buffer = new Buffer<Foo>(42))
using (Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(42))
{
IntPtr ptr1 = buffer.Pin();
IntPtr ptr2 = buffer.Pin();
@ -242,7 +241,7 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void WhenCalledOnDisposedBuffer_ThrowsInvalidOperationException()
{
Buffer<Foo> buffer = new Buffer<Foo>(42);
Buffer<TestStructs.Foo> buffer = new Buffer<TestStructs.Foo>(42);
buffer.Dispose();
Assert.Throws<InvalidOperationException>(() => buffer.Pin());

12
tests/ImageSharp.Tests/Common/Fast2DArrayTests.cs → tests/ImageSharp.Tests/Memory/Fast2DArrayTests.cs

@ -1,12 +1,14 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Memory;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Common
namespace SixLabors.ImageSharp.Tests.Memory
{
using System;
using SixLabors.ImageSharp.Memory;
using Xunit;
public class Fast2DArrayTests
{
private static readonly float[,] FloydSteinbergMatrix =

11
tests/ImageSharp.Tests/Common/PixelDataPoolTests.cs → tests/ImageSharp.Tests/Memory/PixelDataPoolTests.cs

@ -1,14 +1,15 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Linq;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests
namespace SixLabors.ImageSharp.Tests.Memory
{
using SixLabors.ImageSharp.Memory;
using Xunit;
/// <summary>
/// Tests the <see cref="PixelDataPool{T}"/> class.
/// </summary>

185
tests/ImageSharp.Tests/Common/BufferSpanTests.cs → tests/ImageSharp.Tests/Memory/SpanUtilityTests.cs

@ -1,17 +1,18 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
using static SixLabors.ImageSharp.Tests.Common.TestStructs;
namespace SixLabors.ImageSharp.Tests.Common
namespace SixLabors.ImageSharp.Tests.Memory
{
public unsafe class SpanTests
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Tests.Common;
using Xunit;
public unsafe class SpanUtilityTests
{
// ReSharper disable once ClassNeverInstantiated.Local
private class Assert : Xunit.Assert
@ -20,7 +21,7 @@ namespace SixLabors.ImageSharp.Tests.Common
{
ref T1 bb = ref Unsafe.As<T2, T1>(ref b);
True(Unsafe.AreSame(ref a, ref bb), "References are not same!");
Assert.True(Unsafe.AreSame(ref a, ref bb), "References are not same!");
}
}
@ -42,15 +43,15 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void AsBytes()
{
Foo[] fooz = { new Foo(1, 2), new Foo(3, 4), new Foo(5, 6) };
TestStructs.Foo[] fooz = { new TestStructs.Foo(1, 2), new TestStructs.Foo(3, 4), new TestStructs.Foo(5, 6) };
using (Buffer<Foo> colorBuf = new Buffer<Foo>(fooz))
using (Buffer<TestStructs.Foo> colorBuf = new Buffer<TestStructs.Foo>(fooz))
{
Span<Foo> orig = colorBuf.Slice(1);
Span<TestStructs.Foo> orig = colorBuf.Slice(1);
Span<byte> asBytes = orig.AsBytes();
// Assert.Equal(asBytes.Start, sizeof(Foo));
Assert.Equal(orig.Length * Unsafe.SizeOf<Foo>(), asBytes.Length);
Assert.Equal(orig.Length * Unsafe.SizeOf<TestStructs.Foo>(), asBytes.Length);
Assert.SameRefs(ref orig.DangerousGetPinnableReference(), ref asBytes.DangerousGetPinnableReference());
}
}
@ -60,10 +61,10 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void Basic()
{
Foo[] array = Foo.CreateArray(3);
TestStructs.Foo[] array = TestStructs.Foo.CreateArray(3);
// Act:
Span<Foo> span = new Span<Foo>(array);
Span<TestStructs.Foo> span = new Span<TestStructs.Foo>(array);
// Assert:
Assert.Equal(array, span.ToArray());
@ -74,11 +75,11 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void WithStart()
{
Foo[] array = Foo.CreateArray(4);
TestStructs.Foo[] array = TestStructs.Foo.CreateArray(4);
int start = 2;
// Act:
Span<Foo> span = new Span<Foo>(array, start);
Span<TestStructs.Foo> span = new Span<TestStructs.Foo>(array, start);
// Assert:
Assert.SameRefs(ref array[start], ref span.DangerousGetPinnableReference());
@ -88,11 +89,11 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void WithStartAndLength()
{
Foo[] array = Foo.CreateArray(10);
TestStructs.Foo[] array = TestStructs.Foo.CreateArray(10);
int start = 2;
int length = 3;
// Act:
Span<Foo> span = new Span<Foo>(array, start, length);
Span<TestStructs.Foo> span = new Span<TestStructs.Foo>(array, start, length);
// Assert:
Assert.SameRefs(ref array[start], ref span.DangerousGetPinnableReference());
@ -105,12 +106,12 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void StartOnly()
{
Foo[] array = Foo.CreateArray(5);
TestStructs.Foo[] array = TestStructs.Foo.CreateArray(5);
int start0 = 2;
int start1 = 2;
int totalOffset = start0 + start1;
Span<Foo> span = new Span<Foo>(array, start0);
Span<TestStructs.Foo> span = new Span<TestStructs.Foo>(array, start0);
// Act:
span = span.Slice(start1);
@ -123,13 +124,13 @@ namespace SixLabors.ImageSharp.Tests.Common
[Fact]
public void StartAndLength()
{
Foo[] array = Foo.CreateArray(10);
TestStructs.Foo[] array = TestStructs.Foo.CreateArray(10);
int start0 = 2;
int start1 = 2;
int totalOffset = start0 + start1;
int sliceLength = 3;
Span<Foo> span = new Span<Foo>(array, start0);
Span<TestStructs.Foo> span = new Span<TestStructs.Foo>(array, start0);
// Act:
span = span.Slice(start1, sliceLength);
@ -176,10 +177,10 @@ namespace SixLabors.ImageSharp.Tests.Common
[MemberData(nameof(IndexerData))]
public void Read(int length, int start, int index)
{
Foo[] a = Foo.CreateArray(length);
Span<Foo> span = new Span<Foo>(a, start);
TestStructs.Foo[] a = TestStructs.Foo.CreateArray(length);
Span<TestStructs.Foo> span = new Span<TestStructs.Foo>(a, start);
Foo element = span[index];
TestStructs.Foo element = span[index];
Assert.Equal(a[start + index], element);
}
@ -188,12 +189,12 @@ namespace SixLabors.ImageSharp.Tests.Common
[MemberData(nameof(IndexerData))]
public void Write(int length, int start, int index)
{
Foo[] a = Foo.CreateArray(length);
Span<Foo> span = new Span<Foo>(a, start);
TestStructs.Foo[] a = TestStructs.Foo.CreateArray(length);
Span<TestStructs.Foo> span = new Span<TestStructs.Foo>(a, start);
span[index] = new Foo(666, 666);
span[index] = new TestStructs.Foo(666, 666);
Assert.Equal(new Foo(666, 666), a[start + index]);
Assert.Equal(new TestStructs.Foo(666, 666), a[start + index]);
}
[Theory]
@ -203,15 +204,15 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(10, 1, 1, 7)]
public void AsBytes_Read(int length, int start, int index, int byteOffset)
{
Foo[] a = Foo.CreateArray(length);
Span<Foo> span = new Span<Foo>(a, start);
TestStructs.Foo[] a = TestStructs.Foo.CreateArray(length);
Span<TestStructs.Foo> span = new Span<TestStructs.Foo>(a, start);
Span<byte> bytes = span.AsBytes();
byte actual = bytes[index * Unsafe.SizeOf<Foo>() + byteOffset];
byte actual = bytes[index * Unsafe.SizeOf<TestStructs.Foo>() + byteOffset];
ref byte baseRef = ref Unsafe.As<Foo, byte>(ref a[0]);
byte expected = Unsafe.Add(ref baseRef, (start + index) * Unsafe.SizeOf<Foo>() + byteOffset);
ref byte baseRef = ref Unsafe.As<TestStructs.Foo, byte>(ref a[0]);
byte expected = Unsafe.Add(ref baseRef, (start + index) * Unsafe.SizeOf<TestStructs.Foo>() + byteOffset);
Assert.Equal(expected, actual);
}
@ -223,9 +224,9 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(3, 4)]
public void DangerousGetPinnableReference(int start, int length)
{
Foo[] a = Foo.CreateArray(length);
Span<Foo> span = new Span<Foo>(a, start);
ref Foo r = ref span.DangerousGetPinnableReference();
TestStructs.Foo[] a = TestStructs.Foo.CreateArray(length);
Span<TestStructs.Foo> span = new Span<TestStructs.Foo>(a, start);
ref TestStructs.Foo r = ref span.DangerousGetPinnableReference();
Assert.True(Unsafe.AreSame(ref a[start], ref r));
}
@ -263,11 +264,11 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(1500)]
public void GenericToOwnType(int count)
{
Foo[] source = Foo.CreateArray(count + 2);
Foo[] dest = new Foo[count + 5];
TestStructs.Foo[] source = TestStructs.Foo.CreateArray(count + 2);
TestStructs.Foo[] dest = new TestStructs.Foo[count + 5];
Span<Foo> apSource = new Span<Foo>(source, 1);
Span<Foo> apDest = new Span<Foo>(dest, 1);
Span<TestStructs.Foo> apSource = new Span<TestStructs.Foo>(source, 1);
Span<TestStructs.Foo> apDest = new Span<TestStructs.Foo>(dest, 1);
SpanHelper.Copy(apSource, apDest, count - 1);
@ -286,11 +287,11 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(1500)]
public void GenericToOwnType_Aligned(int count)
{
AlignedFoo[] source = AlignedFoo.CreateArray(count + 2);
AlignedFoo[] dest = new AlignedFoo[count + 5];
TestStructs.AlignedFoo[] source = TestStructs.AlignedFoo.CreateArray(count + 2);
TestStructs.AlignedFoo[] dest = new TestStructs.AlignedFoo[count + 5];
Span<AlignedFoo> apSource = new Span<AlignedFoo>(source, 1);
Span<AlignedFoo> apDest = new Span<AlignedFoo>(dest, 1);
Span<TestStructs.AlignedFoo> apSource = new Span<TestStructs.AlignedFoo>(source, 1);
Span<TestStructs.AlignedFoo> apDest = new Span<TestStructs.AlignedFoo>(dest, 1);
SpanHelper.Copy(apSource, apDest, count - 1);
@ -332,22 +333,22 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(1500)]
public void GenericToBytes(int count)
{
int destCount = count * sizeof(Foo);
Foo[] source = Foo.CreateArray(count + 2);
byte[] dest = new byte[destCount + sizeof(Foo) * 2];
int destCount = count * sizeof(TestStructs.Foo);
TestStructs.Foo[] source = TestStructs.Foo.CreateArray(count + 2);
byte[] dest = new byte[destCount + sizeof(TestStructs.Foo) * 2];
Span<Foo> apSource = new Span<Foo>(source, 1);
Span<byte> apDest = new Span<byte>(dest, sizeof(Foo));
Span<TestStructs.Foo> apSource = new Span<TestStructs.Foo>(source, 1);
Span<byte> apDest = new Span<byte>(dest, sizeof(TestStructs.Foo));
SpanHelper.Copy(apSource.AsBytes(), apDest, (count - 1) * sizeof(Foo));
SpanHelper.Copy(apSource.AsBytes(), apDest, (count - 1) * sizeof(TestStructs.Foo));
AssertNotDefault(source, 1);
Assert.False(ElementsAreEqual(source, dest, 0));
Assert.True(ElementsAreEqual(source, dest, 1));
Assert.True(ElementsAreEqual(source, dest, 2));
Assert.True(ElementsAreEqual(source, dest, count - 1));
Assert.False(ElementsAreEqual(source, dest, count));
Assert.False((bool)ElementsAreEqual(source, dest, 0));
Assert.True((bool)ElementsAreEqual(source, dest, 1));
Assert.True((bool)ElementsAreEqual(source, dest, 2));
Assert.True((bool)ElementsAreEqual(source, dest, count - 1));
Assert.False((bool)ElementsAreEqual(source, dest, count));
}
[Theory]
@ -355,22 +356,22 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(1500)]
public void GenericToBytes_Aligned(int count)
{
int destCount = count * sizeof(Foo);
AlignedFoo[] source = AlignedFoo.CreateArray(count + 2);
byte[] dest = new byte[destCount + sizeof(AlignedFoo) * 2];
int destCount = count * sizeof(TestStructs.Foo);
TestStructs.AlignedFoo[] source = TestStructs.AlignedFoo.CreateArray(count + 2);
byte[] dest = new byte[destCount + sizeof(TestStructs.AlignedFoo) * 2];
Span<AlignedFoo> apSource = new Span<AlignedFoo>(source, 1);
Span<byte> apDest = new Span<byte>(dest, sizeof(AlignedFoo));
Span<TestStructs.AlignedFoo> apSource = new Span<TestStructs.AlignedFoo>(source, 1);
Span<byte> apDest = new Span<byte>(dest, sizeof(TestStructs.AlignedFoo));
SpanHelper.Copy(apSource.AsBytes(), apDest, (count - 1) * sizeof(AlignedFoo));
SpanHelper.Copy(apSource.AsBytes(), apDest, (count - 1) * sizeof(TestStructs.AlignedFoo));
AssertNotDefault(source, 1);
Assert.False(ElementsAreEqual(source, dest, 0));
Assert.True(ElementsAreEqual(source, dest, 1));
Assert.True(ElementsAreEqual(source, dest, 2));
Assert.True(ElementsAreEqual(source, dest, count - 1));
Assert.False(ElementsAreEqual(source, dest, count));
Assert.False((bool)ElementsAreEqual(source, dest, 0));
Assert.True((bool)ElementsAreEqual(source, dest, 1));
Assert.True((bool)ElementsAreEqual(source, dest, 2));
Assert.True((bool)ElementsAreEqual(source, dest, count - 1));
Assert.False((bool)ElementsAreEqual(source, dest, count));
}
[Theory]
@ -389,9 +390,9 @@ namespace SixLabors.ImageSharp.Tests.Common
AssertNotDefault(source, 1);
Assert.True(ElementsAreEqual(source, dest, 0));
Assert.True(ElementsAreEqual(source, dest, count - 1));
Assert.False(ElementsAreEqual(source, dest, count));
Assert.True((bool)ElementsAreEqual(source, dest, 0));
Assert.True((bool)ElementsAreEqual(source, dest, count - 1));
Assert.False((bool)ElementsAreEqual(source, dest, count));
}
[Theory]
@ -399,22 +400,22 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(1500)]
public void BytesToGeneric(int count)
{
int srcCount = count * sizeof(Foo);
int srcCount = count * sizeof(TestStructs.Foo);
byte[] source = CreateTestBytes(srcCount);
Foo[] dest = new Foo[count + 2];
TestStructs.Foo[] dest = new TestStructs.Foo[count + 2];
Span<byte> apSource = new Span<byte>(source);
Span<Foo> apDest = new Span<Foo>(dest);
Span<TestStructs.Foo> apDest = new Span<TestStructs.Foo>(dest);
SpanHelper.Copy(apSource, apDest.AsBytes(), count * sizeof(Foo));
SpanHelper.Copy(apSource, apDest.AsBytes(), count * sizeof(TestStructs.Foo));
AssertNotDefault(source, sizeof(Foo) + 1);
AssertNotDefault(source, sizeof(TestStructs.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));
Assert.True((bool)ElementsAreEqual(dest, source, 0));
Assert.True((bool)ElementsAreEqual(dest, source, 1));
Assert.True((bool)ElementsAreEqual(dest, source, count - 1));
Assert.False((bool)ElementsAreEqual(dest, source, count));
}
[Fact]
@ -436,29 +437,29 @@ namespace SixLabors.ImageSharp.Tests.Common
}
}
internal static bool ElementsAreEqual(Foo[] array, byte[] rawArray, int index)
internal static bool ElementsAreEqual(TestStructs.Foo[] array, byte[] rawArray, int index)
{
fixed (Foo* pArray = array)
fixed (TestStructs.Foo* pArray = array)
fixed (byte* pRaw = rawArray)
{
Foo* pCasted = (Foo*)pRaw;
TestStructs.Foo* pCasted = (TestStructs.Foo*)pRaw;
Foo val1 = pArray[index];
Foo val2 = pCasted[index];
TestStructs.Foo val1 = pArray[index];
TestStructs.Foo val2 = pCasted[index];
return val1.Equals(val2);
}
}
internal static bool ElementsAreEqual(AlignedFoo[] array, byte[] rawArray, int index)
internal static bool ElementsAreEqual(TestStructs.AlignedFoo[] array, byte[] rawArray, int index)
{
fixed (AlignedFoo* pArray = array)
fixed (TestStructs.AlignedFoo* pArray = array)
fixed (byte* pRaw = rawArray)
{
AlignedFoo* pCasted = (AlignedFoo*)pRaw;
TestStructs.AlignedFoo* pCasted = (TestStructs.AlignedFoo*)pRaw;
AlignedFoo val1 = pArray[index];
AlignedFoo val2 = pCasted[index];
TestStructs.AlignedFoo val1 = pArray[index];
TestStructs.AlignedFoo val2 = pCasted[index];
return val1.Equals(val2);
}

6
tests/ImageSharp.Tests/Common/TestStructs.cs → tests/ImageSharp.Tests/Memory/TestStructs.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using Xunit;
namespace SixLabors.ImageSharp.Tests.Common
namespace SixLabors.ImageSharp.Tests.Memory
{
using Xunit;
public static class TestStructs
{
public struct Foo
Loading…
Cancel
Save