diff --git a/src/ImageSharp/Colors/PackedPixel/BulkPixelOperations.cs b/src/ImageSharp/Colors/PackedPixel/BulkPixelOperations.cs index c914b3921c..a0dceadedc 100644 --- a/src/ImageSharp/Colors/PackedPixel/BulkPixelOperations.cs +++ b/src/ImageSharp/Colors/PackedPixel/BulkPixelOperations.cs @@ -1,17 +1,34 @@ namespace ImageSharp { + using System; using System.Numerics; + using System.Runtime.CompilerServices; public unsafe class BulkPixelOperations where TColor : struct, IPixel { public static BulkPixelOperations Instance { get; } = default(TColor).BulkOperations; + + private static readonly int ColorSize = Unsafe.SizeOf(); internal virtual void PackFromVector4( ArrayPointer sourceVectors, ArrayPointer destColors, int count) { + Vector4* sp = (Vector4*)sourceVectors.PointerAtOffset; + byte* dp = (byte*)destColors; + + for (int i = 0; i < count; i++) + { + Vector4 v = Unsafe.Read(sp); + TColor c = default(TColor); + c.PackFromVector4(v); + Unsafe.Write(dp, c); + + sp++; + dp += ColorSize; + } } internal virtual void PackToVector4( @@ -19,16 +36,51 @@ ArrayPointer destVectors, int count) { + byte* sp = (byte*)sourceColors; + Vector4* dp = (Vector4*)destVectors.PointerAtOffset; + + for (int i = 0; i < count; i++) + { + TColor c = Unsafe.Read(sp); + *dp = c.ToVector4(); + sp += ColorSize; + dp++; + } } - internal virtual void PackToXyzBytes(ArrayPointer sourceColors, ArrayPointer destBytes, int count) + internal virtual void PackFromXyzBytes( + ArrayPointer sourceBytes, + ArrayPointer destColors, + int count) { + byte* sp = (byte*)sourceBytes; + byte* dp = (byte*)destColors.PointerAtOffset; + + for (int i = 0; i < count; i++) + { + TColor c = default(TColor); + c.PackFromBytes(sp[0], sp[1], sp[2], 255); + Unsafe.Write(dp, c); + sp += 3; + dp += ColorSize; + } } - internal virtual void PackFromXyzBytes(ArrayPointer sourceBytes, ArrayPointer destColors, int count) + internal virtual void PackToXyzBytes( + ArrayPointer sourceColors, + ArrayPointer destBytes, int count) { - } + byte* sp = (byte*)sourceColors; + + byte[] dest = destBytes.Array; + for (int i = destBytes.Offset; i < destBytes.Offset + count*3; i+=3) + { + TColor c = Unsafe.Read(sp); + c.ToXyzBytes(dest, i); + } + } + internal virtual void PackToXyzwBytes(ArrayPointer sourceColors, ArrayPointer destBytes, int count) { } diff --git a/src/ImageSharp/Common/Memory/ArrayPointer{T}.cs b/src/ImageSharp/Common/Memory/ArrayPointer{T}.cs index 1ea7706d44..8f99327ba2 100644 --- a/src/ImageSharp/Common/Memory/ArrayPointer{T}.cs +++ b/src/ImageSharp/Common/Memory/ArrayPointer{T}.cs @@ -73,6 +73,7 @@ namespace ImageSharp /// /// The offset in number of elements /// The offseted (sliced) ArrayPointer + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ArrayPointer Slice(int offset) { ArrayPointer result = default(ArrayPointer); @@ -81,5 +82,25 @@ namespace ImageSharp result.PointerAtOffset = this.PointerAtOffset + (Unsafe.SizeOf() * offset); return result; } + + /// + /// Convertes instance to a raw 'void*' pointer + /// + /// The to convert + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator void*(ArrayPointer arrayPointer) + { + return (void*)arrayPointer.PointerAtOffset; + } + + /// + /// Convertes instance to a raw 'byte*' pointer + /// + /// The to convert + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator byte* (ArrayPointer arrayPointer) + { + return (byte*)arrayPointer.PointerAtOffset; + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs b/tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs index 441b9dacae..4725823107 100644 --- a/tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs @@ -7,12 +7,14 @@ public abstract class BulkPixelOperationsTests { - public class ColorPixels : BulkPixelOperationsTests + public class Color : BulkPixelOperationsTests { + public static TheoryData ArraySizesData = new TheoryData { 7, 16, 1111 }; } - public class ArgbPixels : BulkPixelOperationsTests + public class Argb : BulkPixelOperationsTests { + public static TheoryData ArraySizesData = new TheoryData { 7, 16, 1111 }; } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs index 50e678bf08..12deda577f 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs @@ -38,10 +38,10 @@ namespace ImageSharp.Tests { const int ExecutionCount = 30; - if (!Vector.IsHardwareAccelerated) - { - throw new Exception("Vector.IsHardwareAccelerated == false! ('prefer32 bit' enabled?)"); - } + //if (!Vector.IsHardwareAccelerated) + //{ + // throw new Exception("Vector.IsHardwareAccelerated == false! ('prefer32 bit' enabled?)"); + //} string path = TestFile.GetPath(fileName); byte[] bytes = File.ReadAllBytes(path);