From bcf58cd5a2ef20c4fe8db24769e4d11632d4b3be Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 13 May 2017 02:16:58 +0200 Subject: [PATCH 01/16] Optimized Rgba32 constructors. Created PixelConversion benchmarks. --- src/ImageSharp/PixelFormats/Argb32.cs | 15 +- src/ImageSharp/PixelFormats/Rgba32.cs | 42 ++++- .../General/PixelConversion.cs | 156 ++++++++++++++++++ 3 files changed, 204 insertions(+), 9 deletions(-) create mode 100644 tests/ImageSharp.Benchmarks/General/PixelConversion.cs diff --git a/src/ImageSharp/PixelFormats/Argb32.cs b/src/ImageSharp/PixelFormats/Argb32.cs index 61e860aee..cb2a1b87e 100644 --- a/src/ImageSharp/PixelFormats/Argb32.cs +++ b/src/ImageSharp/PixelFormats/Argb32.cs @@ -58,11 +58,24 @@ namespace ImageSharp.PixelFormats /// The green component. /// The blue component. /// The alpha component. - public Argb32(byte r, byte g, byte b, byte a = 255) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Argb32(byte r, byte g, byte b, byte a) { this.PackedValue = Pack(r, g, b, a); } + /// + /// Initializes a new instance of the struct. + /// + /// The red component. + /// The green component. + /// The blue component. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Argb32(byte r, byte g, byte b) + { + this.PackedValue = Pack(r, g, b, 255); + } + /// /// Initializes a new instance of the struct. /// diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs index 15a9ed0fd..c5f752336 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.cs @@ -49,12 +49,6 @@ namespace ImageSharp [FieldOffset(3)] public byte A; - /// - /// The packed representation of the value. - /// - [FieldOffset(0)] - public uint Rgba; - /// /// The shift count for the red component /// @@ -85,6 +79,21 @@ namespace ImageSharp /// private static readonly Vector4 Half = new Vector4(0.5F); + /// + /// Initializes a new instance of the struct. + /// + /// The red component. + /// The green component. + /// The blue component. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Rgba32(byte r, byte g, byte b) + { + this.R = r; + this.G = g; + this.B = b; + this.A = 255; + } + /// /// Initializes a new instance of the struct. /// @@ -93,8 +102,7 @@ namespace ImageSharp /// The blue component. /// The alpha component. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rgba32(byte r, byte g, byte b, byte a = 255) - : this() + public Rgba32(byte r, byte g, byte b, byte a) { this.R = r; this.G = g; @@ -155,6 +163,24 @@ namespace ImageSharp this.Rgba = packed; } + /// + /// Gets or sets the packed representation of the Rgba32 struct. + /// + public uint Rgba + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return Unsafe.As(ref this); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + Unsafe.As(ref this) = value; + } + } + /// public uint PackedValue { get => this.Rgba; set => this.Rgba = value; } diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion.cs new file mode 100644 index 000000000..77e728280 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion.cs @@ -0,0 +1,156 @@ +namespace ImageSharp.Benchmarks.General +{ + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + + using BenchmarkDotNet.Attributes; + + /// + /// When implementing TPixel --> Rgba32 style conversions on IPixel, should which API should we prefer? + /// 1. Rgba32 ToRgba32(); + /// OR + /// 2. void CopyToRgba32(ref Rgba32 dest); + /// ? + /// + public class PixelConversion + { + interface ITestPixel + where T : struct, ITestPixel + { + Rgba32 ToRgba32(); + + void CopyToRgba32(ref Rgba32 dest); + } + + [StructLayout(LayoutKind.Sequential)] + struct TestArgb : ITestPixel + { + private byte a, r, g, b; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Rgba32 ToRgba32() + { + return new Rgba32(this.r, this.g, this.b, this.a); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyToRgba32(ref Rgba32 dest) + { + dest.R = this.r; + dest.G = this.g; + dest.B = this.b; + dest.A = this.a; + } + } + + [StructLayout(LayoutKind.Sequential)] + struct TestRgba : ITestPixel + { + private byte r, g, b, a; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Rgba32 ToRgba32() + { + return Unsafe.As(ref this); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyToRgba32(ref Rgba32 dest) + { + dest = Unsafe.As(ref this); + } + } + + struct ConversionRunner + where T : struct, ITestPixel + { + private T[] source; + + private Rgba32[] dest; + + public ConversionRunner(int count) + { + this.source = new T[count]; + this.dest = new Rgba32[count]; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RunRetvalConversion() + { + int count = this.source.Length; + + ref T sourceBaseRef = ref this.source[0]; + ref Rgba32 destBaseRef = ref this.dest[0]; + + for (int i = 0; i < count; i++) + { + Unsafe.Add(ref destBaseRef, i) = Unsafe.Add(ref sourceBaseRef, i).ToRgba32(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RunCopyToConversion() + { + int count = this.source.Length; + + ref T sourceBaseRef = ref this.source[0]; + ref Rgba32 destBaseRef = ref this.dest[0]; + + for (int i = 0; i < count; i++) + { + Unsafe.Add(ref sourceBaseRef, i).CopyToRgba32(ref Unsafe.Add(ref destBaseRef, i)); + } + } + } + + private ConversionRunner inOrderRunner; + + private ConversionRunner permutedRunner; + + [Params(128)] + public int Count { get; set; } + + [Setup] + public void Setup() + { + this.inOrderRunner = new ConversionRunner(this.Count); + this.permutedRunner = new ConversionRunner(this.Count); + } + + [Benchmark(Baseline = true)] + public void InOrderRetval() + { + this.inOrderRunner.RunRetvalConversion(); + } + + [Benchmark] + public void InOrderCopyTo() + { + this.inOrderRunner.RunCopyToConversion(); + } + + [Benchmark] + public void PermutedRetval() + { + this.permutedRunner.RunRetvalConversion(); + } + + [Benchmark] + public void PermutedCopyTo() + { + this.permutedRunner.RunCopyToConversion(); + } + } + + /* + * Results: + * + * Method | Count | Mean | StdDev | Scaled | Scaled-StdDev | + * --------------- |------ |------------ |---------- |------- |-------------- | + * InOrderRetval | 128 | 89.7358 ns | 2.2389 ns | 1.00 | 0.00 | + * InOrderCopyTo | 128 | 89.4112 ns | 2.2901 ns | 1.00 | 0.03 | + * PermutedRetval | 128 | 845.4038 ns | 5.6154 ns | 9.43 | 0.23 | + * PermutedCopyTo | 128 | 155.6004 ns | 3.8870 ns | 1.73 | 0.06 | + * + */ +} \ No newline at end of file From 6ef195f812bee2466f2d8477300c91edf3af387d Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 16 May 2017 01:51:43 +0200 Subject: [PATCH 02/16] introducing Rgb24 & Bgr24 --- src/ImageSharp/PixelFormats/Alpha8.cs | 2 +- src/ImageSharp/PixelFormats/Argb32.cs | 2 +- src/ImageSharp/PixelFormats/Bgr24.cs | 94 +++++++++++++++++++ src/ImageSharp/PixelFormats/Bgr565.cs | 2 +- src/ImageSharp/PixelFormats/Bgra4444.cs | 2 +- src/ImageSharp/PixelFormats/Bgra5551.cs | 2 +- src/ImageSharp/PixelFormats/Byte4.cs | 2 +- src/ImageSharp/PixelFormats/HalfSingle.cs | 2 +- src/ImageSharp/PixelFormats/HalfVector2.cs | 2 +- src/ImageSharp/PixelFormats/HalfVector4.cs | 2 +- src/ImageSharp/PixelFormats/IPixel.cs | 2 +- .../PixelFormats/NormalizedByte2.cs | 2 +- .../PixelFormats/NormalizedByte4.cs | 2 +- .../PixelFormats/NormalizedShort2.cs | 2 +- .../PixelFormats/NormalizedShort4.cs | 2 +- .../PixelFormats/PixelOperations{TPixel}.cs | 2 +- src/ImageSharp/PixelFormats/Rg32.cs | 2 +- src/ImageSharp/PixelFormats/Rgb24.cs | 94 +++++++++++++++++++ src/ImageSharp/PixelFormats/Rgba1010102.cs | 2 +- src/ImageSharp/PixelFormats/Rgba32.cs | 8 +- src/ImageSharp/PixelFormats/Rgba64.cs | 2 +- src/ImageSharp/PixelFormats/RgbaVector.cs | 2 +- src/ImageSharp/PixelFormats/Short2.cs | 2 +- src/ImageSharp/PixelFormats/Short4.cs | 2 +- src/Shared/stylecop.json | 6 +- .../Tests/PixelFormats/PixelBlenderTests.cs} | 4 +- .../ImageSharp.Tests/ImageSharp.Tests.csproj | 2 +- .../PixelFormats/Bgr24Tests.cs | 63 +++++++++++++ .../ColorConstructorTests.cs | 0 .../ColorDefinitionTests.cs | 0 .../ColorEqualityTests.cs | 0 .../ColorPackingTests.cs | 0 .../PackedPixelTests.cs | 0 .../PixelOperationsTests.Blender.cs | 50 ++++++++++ .../PixelOperationsTests.cs | 5 +- .../PixelFormats/Rgb24Tests.cs | 65 +++++++++++++ .../{Colors => PixelFormats}/Rgba32Tests.cs | 0 .../RgbaVectorTests.cs | 0 .../UnPackedPixelTests.cs | 0 39 files changed, 400 insertions(+), 33 deletions(-) create mode 100644 src/ImageSharp/PixelFormats/Bgr24.cs create mode 100644 src/ImageSharp/PixelFormats/Rgb24.cs rename tests/{ImageSharp.Tests/PixelFormats/PixelOperations.cs => ImageSharp.Sandbox46/Tests/PixelFormats/PixelBlenderTests.cs} (96%) create mode 100644 tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs rename tests/ImageSharp.Tests/{Colors => PixelFormats}/ColorConstructorTests.cs (100%) rename tests/ImageSharp.Tests/{Colors => PixelFormats}/ColorDefinitionTests.cs (100%) rename tests/ImageSharp.Tests/{Colors => PixelFormats}/ColorEqualityTests.cs (100%) rename tests/ImageSharp.Tests/{Colors => PixelFormats}/ColorPackingTests.cs (100%) rename tests/ImageSharp.Tests/{Colors => PixelFormats}/PackedPixelTests.cs (100%) create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs rename tests/ImageSharp.Tests/{Colors => PixelFormats}/PixelOperationsTests.cs (99%) create mode 100644 tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs rename tests/ImageSharp.Tests/{Colors => PixelFormats}/Rgba32Tests.cs (100%) rename tests/ImageSharp.Tests/{Colors => PixelFormats}/RgbaVectorTests.cs (100%) rename tests/ImageSharp.Tests/{Colors => PixelFormats}/UnPackedPixelTests.cs (100%) diff --git a/src/ImageSharp/PixelFormats/Alpha8.cs b/src/ImageSharp/PixelFormats/Alpha8.cs index c184ed9cf..582c28c78 100644 --- a/src/ImageSharp/PixelFormats/Alpha8.cs +++ b/src/ImageSharp/PixelFormats/Alpha8.cs @@ -62,7 +62,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/Argb32.cs b/src/ImageSharp/PixelFormats/Argb32.cs index 3749571c7..2ca1183a3 100644 --- a/src/ImageSharp/PixelFormats/Argb32.cs +++ b/src/ImageSharp/PixelFormats/Argb32.cs @@ -237,7 +237,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/Bgr24.cs b/src/ImageSharp/PixelFormats/Bgr24.cs new file mode 100644 index 000000000..2555c13a4 --- /dev/null +++ b/src/ImageSharp/PixelFormats/Bgr24.cs @@ -0,0 +1,94 @@ +namespace ImageSharp.PixelFormats +{ + using System; + using System.Numerics; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + + [StructLayout(LayoutKind.Sequential)] + public struct Bgr24 : IPixel + { + /// + /// Gets or sets the blue component. + /// + public byte B; + + /// + /// Gets or sets the green component. + /// + public byte G; + + /// + /// Gets or sets the red component. + /// + public byte R; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Bgr24(byte r, byte g, byte b) + { + this.R = r; + this.G = g; + this.B = b; + } + + public PixelOperations CreatePixelOperations() => new PixelOperations(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(Bgr24 other) + { + return this.R == other.R && this.G == other.G && this.B == other.B; + } + + public override bool Equals(object obj) + { + return obj.GetType() == typeof(Bgr24) && this.Equals((Bgr24)obj); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override int GetHashCode() + { + unchecked + { + int hashCode = this.B; + hashCode = (hashCode * 397) ^ this.G; + hashCode = (hashCode * 397) ^ this.R; + return hashCode; + } + } + + public void PackFromBytes(byte x, byte y, byte z, byte w) + { + throw new NotImplementedException(); + } + + public void PackFromVector4(Vector4 vector) + { + throw new NotImplementedException(); + } + + public Vector4 ToVector4() + { + throw new NotImplementedException(); + } + + public void ToXyzBytes(Span bytes, int startIndex) + { + throw new NotImplementedException(); + } + + public void ToXyzwBytes(Span bytes, int startIndex) + { + throw new NotImplementedException(); + } + + public void ToZyxBytes(Span bytes, int startIndex) + { + throw new NotImplementedException(); + } + + public void ToZyxwBytes(Span bytes, int startIndex) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Bgr565.cs b/src/ImageSharp/PixelFormats/Bgr565.cs index 92bbac14c..6a568eeb5 100644 --- a/src/ImageSharp/PixelFormats/Bgr565.cs +++ b/src/ImageSharp/PixelFormats/Bgr565.cs @@ -71,7 +71,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// /// Expands the packed representation into a . diff --git a/src/ImageSharp/PixelFormats/Bgra4444.cs b/src/ImageSharp/PixelFormats/Bgra4444.cs index 0bac00dfe..2dafd0c98 100644 --- a/src/ImageSharp/PixelFormats/Bgra4444.cs +++ b/src/ImageSharp/PixelFormats/Bgra4444.cs @@ -70,7 +70,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/Bgra5551.cs b/src/ImageSharp/PixelFormats/Bgra5551.cs index f151db644..67fb4e0ec 100644 --- a/src/ImageSharp/PixelFormats/Bgra5551.cs +++ b/src/ImageSharp/PixelFormats/Bgra5551.cs @@ -72,7 +72,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/Byte4.cs b/src/ImageSharp/PixelFormats/Byte4.cs index 264bc7497..2a0e6d75c 100644 --- a/src/ImageSharp/PixelFormats/Byte4.cs +++ b/src/ImageSharp/PixelFormats/Byte4.cs @@ -73,7 +73,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/HalfSingle.cs b/src/ImageSharp/PixelFormats/HalfSingle.cs index 4cc9acc22..b6f93d059 100644 --- a/src/ImageSharp/PixelFormats/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/HalfSingle.cs @@ -76,7 +76,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// /// Expands the packed representation into a . diff --git a/src/ImageSharp/PixelFormats/HalfVector2.cs b/src/ImageSharp/PixelFormats/HalfVector2.cs index f490f7169..e96c5c076 100644 --- a/src/ImageSharp/PixelFormats/HalfVector2.cs +++ b/src/ImageSharp/PixelFormats/HalfVector2.cs @@ -86,7 +86,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// /// Expands the packed representation into a . diff --git a/src/ImageSharp/PixelFormats/HalfVector4.cs b/src/ImageSharp/PixelFormats/HalfVector4.cs index 7c496c161..d84a40198 100644 --- a/src/ImageSharp/PixelFormats/HalfVector4.cs +++ b/src/ImageSharp/PixelFormats/HalfVector4.cs @@ -89,7 +89,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/IPixel.cs b/src/ImageSharp/PixelFormats/IPixel.cs index 030cb93f4..4e777cadf 100644 --- a/src/ImageSharp/PixelFormats/IPixel.cs +++ b/src/ImageSharp/PixelFormats/IPixel.cs @@ -20,7 +20,7 @@ namespace ImageSharp.PixelFormats /// This method is not intended to be consumed directly. Use instead. /// /// The instance. - PixelOperations CreateBulkOperations(); + PixelOperations CreatePixelOperations(); } /// diff --git a/src/ImageSharp/PixelFormats/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/NormalizedByte2.cs index 47a4f3005..d1193e9c1 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte2.cs @@ -91,7 +91,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// /// Expands the packed representation into a . diff --git a/src/ImageSharp/PixelFormats/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/NormalizedByte4.cs index 4559bd082..565f26971 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte4.cs @@ -93,7 +93,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/NormalizedShort2.cs b/src/ImageSharp/PixelFormats/NormalizedShort2.cs index 648b68905..5b791eb25 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort2.cs @@ -91,7 +91,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/NormalizedShort4.cs index 7b520aace..047c6a250 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort4.cs @@ -93,7 +93,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 993a11232..5c51b59f8 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -20,7 +20,7 @@ namespace ImageSharp.PixelFormats /// /// Gets the global instance for the pixel type /// - public static PixelOperations Instance { get; } = default(TPixel).CreateBulkOperations(); + public static PixelOperations Instance { get; } = default(TPixel).CreatePixelOperations(); /// /// Bulk version of diff --git a/src/ImageSharp/PixelFormats/Rg32.cs b/src/ImageSharp/PixelFormats/Rg32.cs index ea7d8729b..0faf2fe80 100644 --- a/src/ImageSharp/PixelFormats/Rg32.cs +++ b/src/ImageSharp/PixelFormats/Rg32.cs @@ -76,7 +76,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// /// Expands the packed representation into a . diff --git a/src/ImageSharp/PixelFormats/Rgb24.cs b/src/ImageSharp/PixelFormats/Rgb24.cs new file mode 100644 index 000000000..ff2b237ad --- /dev/null +++ b/src/ImageSharp/PixelFormats/Rgb24.cs @@ -0,0 +1,94 @@ +namespace ImageSharp.PixelFormats +{ + using System; + using System.Numerics; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + + [StructLayout(LayoutKind.Sequential)] + public struct Rgb24 : IPixel + { + /// + /// Gets or sets the red component. + /// + public byte R; + + /// + /// Gets or sets the green component. + /// + public byte G; + + /// + /// Gets or sets the blue component. + /// + public byte B; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Rgb24(byte r, byte g, byte b) + { + this.R = r; + this.G = g; + this.B = b; + } + + public PixelOperations CreatePixelOperations() => new PixelOperations(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(Rgb24 other) + { + return this.R == other.R && this.G == other.G && this.B == other.B; + } + + public override bool Equals(object obj) + { + return obj.GetType() == typeof(Rgb24) && this.Equals((Rgb24)obj); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override int GetHashCode() + { + unchecked + { + int hashCode = this.R; + hashCode = (hashCode * 397) ^ this.G; + hashCode = (hashCode * 397) ^ this.B; + return hashCode; + } + } + + public void PackFromBytes(byte x, byte y, byte z, byte w) + { + throw new NotImplementedException(); + } + + public void PackFromVector4(Vector4 vector) + { + throw new NotImplementedException(); + } + + public Vector4 ToVector4() + { + throw new NotImplementedException(); + } + + public void ToXyzBytes(Span bytes, int startIndex) + { + throw new NotImplementedException(); + } + + public void ToXyzwBytes(Span bytes, int startIndex) + { + throw new NotImplementedException(); + } + + public void ToZyxBytes(Span bytes, int startIndex) + { + throw new NotImplementedException(); + } + + public void ToZyxwBytes(Span bytes, int startIndex) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Rgba1010102.cs b/src/ImageSharp/PixelFormats/Rgba1010102.cs index ca7b74fbb..8eaf5f771 100644 --- a/src/ImageSharp/PixelFormats/Rgba1010102.cs +++ b/src/ImageSharp/PixelFormats/Rgba1010102.cs @@ -79,7 +79,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs index 446da5abb..ba46332fb 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.cs @@ -23,31 +23,27 @@ namespace ImageSharp /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, /// as it avoids the need to create new values for modification operations. /// - [StructLayout(LayoutKind.Explicit)] + [StructLayout(LayoutKind.Sequential)] public partial struct Rgba32 : IPixel, IPackedVector { /// /// Gets or sets the red component. /// - [FieldOffset(0)] public byte R; /// /// Gets or sets the green component. /// - [FieldOffset(1)] public byte G; /// /// Gets or sets the blue component. /// - [FieldOffset(2)] public byte B; /// /// Gets or sets the alpha component. /// - [FieldOffset(3)] public byte A; /// @@ -233,7 +229,7 @@ namespace ImageSharp } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/Rgba64.cs b/src/ImageSharp/PixelFormats/Rgba64.cs index 417828368..2101d4ba0 100644 --- a/src/ImageSharp/PixelFormats/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/Rgba64.cs @@ -78,7 +78,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/RgbaVector.cs b/src/ImageSharp/PixelFormats/RgbaVector.cs index 5332f4a8e..314ac31e3 100644 --- a/src/ImageSharp/PixelFormats/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/RgbaVector.cs @@ -211,7 +211,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new RgbaVector.PixelOperations(); + public PixelOperations CreatePixelOperations() => new RgbaVector.PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/Short2.cs b/src/ImageSharp/PixelFormats/Short2.cs index b848b5505..a6fe95b49 100644 --- a/src/ImageSharp/PixelFormats/Short2.cs +++ b/src/ImageSharp/PixelFormats/Short2.cs @@ -91,7 +91,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/Short4.cs b/src/ImageSharp/PixelFormats/Short4.cs index 763de19bc..f254c7379 100644 --- a/src/ImageSharp/PixelFormats/Short4.cs +++ b/src/ImageSharp/PixelFormats/Short4.cs @@ -93,7 +93,7 @@ namespace ImageSharp.PixelFormats } /// - public PixelOperations CreateBulkOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Shared/stylecop.json b/src/Shared/stylecop.json index df8f120a5..b74a0af91 100644 --- a/src/Shared/stylecop.json +++ b/src/Shared/stylecop.json @@ -3,7 +3,11 @@ "settings": { "documentationRules": { "companyName": "James Jackson-South", - "copyrightText": "Copyright (c) James Jackson-South and contributors.\nLicensed under the Apache License, Version 2.0." + "copyrightText": "Copyright (c) James Jackson-South and contributors.\nLicensed under the Apache License, Version 2.0.", + + "documentInterfaces": false, + "documentInternalElements": false, + "documentExposedElements": false } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations.cs b/tests/ImageSharp.Sandbox46/Tests/PixelFormats/PixelBlenderTests.cs similarity index 96% rename from tests/ImageSharp.Tests/PixelFormats/PixelOperations.cs rename to tests/ImageSharp.Sandbox46/Tests/PixelFormats/PixelBlenderTests.cs index a9108692e..7efd3a6fc 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations.cs +++ b/tests/ImageSharp.Sandbox46/Tests/PixelFormats/PixelBlenderTests.cs @@ -15,7 +15,7 @@ namespace ImageSharp.Tests.PixelFormats public class PixelOperations { - public static TheoryData blenderMappings = new TheoryData() + public static TheoryData BlenderMappings = new TheoryData() { { new TestPixel(), typeof(DefaultNormalPixelBlender), PixelBlenderMode.Normal }, { new TestPixel(), typeof(DefaultScreenPixelBlender), PixelBlenderMode.Screen }, @@ -39,7 +39,7 @@ namespace ImageSharp.Tests.PixelFormats }; [Theory] - [MemberData(nameof(blenderMappings))] + [MemberData(nameof(BlenderMappings))] public void ReturnsCorrectBlender(TestPixel pixel, Type type, PixelBlenderMode mode) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 55b3c80e3..781e73f9e 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -7,7 +7,7 @@ True - + diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs new file mode 100644 index 000000000..371163163 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs @@ -0,0 +1,63 @@ +namespace ImageSharp.Tests +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class Bgr24Tests + { + public static readonly TheoryData ColorData = + new TheoryData() { { 1, 2, 3 }, { 4, 5, 6 }, { 0, 255, 42 } }; + + [Theory] + [MemberData(nameof(ColorData))] + public void Constructor(byte r, byte g, byte b) + { + var p = new Rgb24(r, g, b); + + Assert.Equal(r, p.R); + Assert.Equal(g, p.G); + Assert.Equal(b, p.B); + } + [Fact] + public unsafe void ByteLayoutIsSequentialBgr() + { + var color = new Bgr24(1, 2, 3); + byte* ptr = (byte*)&color; + + Assert.Equal(3, ptr[0]); + Assert.Equal(2, ptr[1]); + Assert.Equal(1, ptr[2]); + } + + public class Equality + { + public static TheoryData ColorData = Rgb24Tests.ColorData; + + [Theory] + [MemberData(nameof(ColorData))] + public void WhenTrue(byte r, byte g, byte b) + { + var x = new Rgb24(r, g, b); + var y = new Rgb24(r, g, b); + + Assert.True(x.Equals(y)); + Assert.True(x.Equals((object)y)); + Assert.Equal(x.GetHashCode(), y.GetHashCode()); + } + + [Theory] + [InlineData(1, 2, 3, 1, 2, 4)] + [InlineData(0, 255, 0, 0, 244, 0)] + [InlineData(1, 255, 0, 0, 255, 0)] + public void WhenFalse(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2) + { + var a = new Rgb24(1, 2, 3); + var b = new Rgb24(1, 2, 4); + + Assert.False(a.Equals(b)); + Assert.False(a.Equals((object)b)); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Colors/ColorConstructorTests.cs b/tests/ImageSharp.Tests/PixelFormats/ColorConstructorTests.cs similarity index 100% rename from tests/ImageSharp.Tests/Colors/ColorConstructorTests.cs rename to tests/ImageSharp.Tests/PixelFormats/ColorConstructorTests.cs diff --git a/tests/ImageSharp.Tests/Colors/ColorDefinitionTests.cs b/tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs similarity index 100% rename from tests/ImageSharp.Tests/Colors/ColorDefinitionTests.cs rename to tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs diff --git a/tests/ImageSharp.Tests/Colors/ColorEqualityTests.cs b/tests/ImageSharp.Tests/PixelFormats/ColorEqualityTests.cs similarity index 100% rename from tests/ImageSharp.Tests/Colors/ColorEqualityTests.cs rename to tests/ImageSharp.Tests/PixelFormats/ColorEqualityTests.cs diff --git a/tests/ImageSharp.Tests/Colors/ColorPackingTests.cs b/tests/ImageSharp.Tests/PixelFormats/ColorPackingTests.cs similarity index 100% rename from tests/ImageSharp.Tests/Colors/ColorPackingTests.cs rename to tests/ImageSharp.Tests/PixelFormats/ColorPackingTests.cs diff --git a/tests/ImageSharp.Tests/Colors/PackedPixelTests.cs b/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs similarity index 100% rename from tests/ImageSharp.Tests/Colors/PackedPixelTests.cs rename to tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs new file mode 100644 index 000000000..ce81499ed --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs @@ -0,0 +1,50 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.PixelFormats +{ + using System; + using System.Collections.Generic; + using System.Text; + using ImageSharp.PixelFormats; + using ImageSharp.PixelFormats.PixelBlenders; + using ImageSharp.Tests.TestUtilities; + using Xunit; + + public partial class PixelOperationsTests + { + public static TheoryData BlenderMappings = new TheoryData() + { + { new TestPixel(), typeof(DefaultNormalPixelBlender), PixelBlenderMode.Normal }, + { new TestPixel(), typeof(DefaultScreenPixelBlender), PixelBlenderMode.Screen }, + { new TestPixel(), typeof(DefaultHardLightPixelBlender), PixelBlenderMode.HardLight }, + { new TestPixel(), typeof(DefaultOverlayPixelBlender), PixelBlenderMode.Overlay }, + { new TestPixel(), typeof(DefaultDarkenPixelBlender), PixelBlenderMode.Darken }, + { new TestPixel(), typeof(DefaultLightenPixelBlender), PixelBlenderMode.Lighten }, + { new TestPixel(), typeof(DefaultAddPixelBlender), PixelBlenderMode.Add }, + { new TestPixel(), typeof(DefaultSubstractPixelBlender), PixelBlenderMode.Substract }, + { new TestPixel(), typeof(DefaultMultiplyPixelBlender), PixelBlenderMode.Multiply }, + + { new TestPixel(), typeof(DefaultNormalPixelBlender), PixelBlenderMode.Normal }, + { new TestPixel(), typeof(DefaultScreenPixelBlender), PixelBlenderMode.Screen }, + { new TestPixel(), typeof(DefaultHardLightPixelBlender), PixelBlenderMode.HardLight }, + { new TestPixel(), typeof(DefaultOverlayPixelBlender), PixelBlenderMode.Overlay }, + { new TestPixel(), typeof(DefaultDarkenPixelBlender), PixelBlenderMode.Darken }, + { new TestPixel(), typeof(DefaultLightenPixelBlender), PixelBlenderMode.Lighten }, + { new TestPixel(), typeof(DefaultAddPixelBlender), PixelBlenderMode.Add }, + { new TestPixel(), typeof(DefaultSubstractPixelBlender), PixelBlenderMode.Substract }, + { new TestPixel(), typeof(DefaultMultiplyPixelBlender), PixelBlenderMode.Multiply }, + }; + + [Theory] + [MemberData(nameof(BlenderMappings))] + public void ReturnsCorrectBlender(TestPixel pixel, Type type, PixelBlenderMode mode) + where TPixel : struct, IPixel + { + PixelBlender blender = PixelOperations.Instance.GetPixelBlender(mode); + Assert.IsType(type, blender); + } + } +} diff --git a/tests/ImageSharp.Tests/Colors/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs similarity index 99% rename from tests/ImageSharp.Tests/Colors/PixelOperationsTests.cs rename to tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs index c91218ccc..f387178e5 100644 --- a/tests/ImageSharp.Tests/Colors/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs @@ -1,6 +1,6 @@ // ReSharper disable InconsistentNaming // ReSharper disable AccessToDisposedClosure -namespace ImageSharp.Tests.Colors +namespace ImageSharp.Tests.PixelFormats { using System; using System.Numerics; @@ -11,8 +11,9 @@ namespace ImageSharp.Tests.Colors using Xunit; using Xunit.Abstractions; - public class PixelOperationsTests + public partial class PixelOperationsTests { + public class Color32 : PixelOperationsTests { public Color32(ITestOutputHelper output) diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs new file mode 100644 index 000000000..934d83bbb --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs @@ -0,0 +1,65 @@ +// ReSharper disable InconsistentNaming +namespace ImageSharp.Tests +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class Rgb24Tests + { + public static readonly TheoryData ColorData = + new TheoryData() { { 1, 2, 3 }, { 4, 5, 6 }, { 0, 255, 42 } }; + + [Theory] + [MemberData(nameof(ColorData))] + public void Constructor(byte r, byte g, byte b) + { + var p = new Rgb24(r, g, b); + + Assert.Equal(r, p.R); + Assert.Equal(g, p.G); + Assert.Equal(b, p.B); + } + + [Fact] + public unsafe void ByteLayoutIsSequentialRgb() + { + var color = new Rgb24(1, 2, 3); + byte* ptr = (byte*)&color; + + Assert.Equal(1, ptr[0]); + Assert.Equal(2, ptr[1]); + Assert.Equal(3, ptr[2]); + } + + public class Equality + { + public static TheoryData ColorData = Rgb24Tests.ColorData; + + [Theory] + [MemberData(nameof(ColorData))] + public void WhenTrue(byte r, byte g, byte b) + { + var x = new Rgb24(r, g, b); + var y = new Rgb24(r, g, b); + + Assert.True(x.Equals(y)); + Assert.True(x.Equals((object)y)); + Assert.Equal(x.GetHashCode(), y.GetHashCode()); + } + + [Theory] + [InlineData(1, 2, 3, 1, 2, 4)] + [InlineData(0, 255, 0, 0, 244, 0)] + [InlineData(1, 255, 0, 0, 255, 0)] + public void WhenFalse(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2) + { + var a = new Rgb24(1, 2, 3); + var b = new Rgb24(1, 2, 4); + + Assert.False(a.Equals(b)); + Assert.False(a.Equals((object)b)); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Colors/Rgba32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs similarity index 100% rename from tests/ImageSharp.Tests/Colors/Rgba32Tests.cs rename to tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs diff --git a/tests/ImageSharp.Tests/Colors/RgbaVectorTests.cs b/tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs similarity index 100% rename from tests/ImageSharp.Tests/Colors/RgbaVectorTests.cs rename to tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs diff --git a/tests/ImageSharp.Tests/Colors/UnPackedPixelTests.cs b/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs similarity index 100% rename from tests/ImageSharp.Tests/Colors/UnPackedPixelTests.cs rename to tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs From 597d8d2f7fd2133b8a19c875255005617c1e3387 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 16 May 2017 02:31:05 +0200 Subject: [PATCH 03/16] Bgra32 --- src/ImageSharp/PixelFormats/Bgr24.cs | 2 +- src/ImageSharp/PixelFormats/Bgra32.cs | 146 ++++++++++++++++++ src/ImageSharp/PixelFormats/IPixel.cs | 2 +- src/ImageSharp/PixelFormats/Rgb24.cs | 2 +- src/ImageSharp/PixelFormats/Rgba32.cs | 14 +- .../PixelFormats/Bgr24Tests.cs | 4 +- .../PixelFormats/Bgra32Tests.cs | 70 +++++++++ .../PixelFormats/Rgb24Tests.cs | 4 +- 8 files changed, 232 insertions(+), 12 deletions(-) create mode 100644 src/ImageSharp/PixelFormats/Bgra32.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs diff --git a/src/ImageSharp/PixelFormats/Bgr24.cs b/src/ImageSharp/PixelFormats/Bgr24.cs index 2555c13a4..386320495 100644 --- a/src/ImageSharp/PixelFormats/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/Bgr24.cs @@ -41,7 +41,7 @@ public override bool Equals(object obj) { - return obj.GetType() == typeof(Bgr24) && this.Equals((Bgr24)obj); + return obj?.GetType() == typeof(Bgr24) && this.Equals((Bgr24)obj); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/Bgra32.cs b/src/ImageSharp/PixelFormats/Bgra32.cs new file mode 100644 index 000000000..582a0cd92 --- /dev/null +++ b/src/ImageSharp/PixelFormats/Bgra32.cs @@ -0,0 +1,146 @@ +namespace ImageSharp +{ + using System; + using System.Numerics; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + + using ImageSharp.PixelFormats; + + [StructLayout(LayoutKind.Sequential)] + public struct Bgra32 : IPixel, IPackedVector + { + /// + /// Gets or sets the blue component. + /// + public byte B; + + /// + /// Gets or sets the green component. + /// + public byte G; + + /// + /// Gets or sets the red component. + /// + public byte R; + + /// + /// Gets or sets the alpha component. + /// + public byte A; + + /// + /// Initializes a new instance of the struct. + /// + /// The red component. + /// The green component. + /// The blue component. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Bgra32(byte r, byte g, byte b) + { + this.R = r; + this.G = g; + this.B = b; + this.A = 255; + } + + + /// + /// Initializes a new instance of the struct. + /// + /// The red component. + /// The green component. + /// The blue component. + /// The alpha component. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Bgra32(byte r, byte g, byte b, byte a) + { + this.R = r; + this.G = g; + this.B = b; + this.A = a; + } + + public PixelOperations CreatePixelOperations() => new PixelOperations(); + + public bool Equals(Bgra32 other) + { + return this.R == other.R && this.G == other.G && this.B == other.B && this.A == other.A; + } + + public override bool Equals(object obj) => obj?.GetType() == typeof(Bgra32) && this.Equals((Bgra32)obj); + + public override int GetHashCode() + { + unchecked + { + int hashCode = this.B; + hashCode = (hashCode * 397) ^ this.G; + hashCode = (hashCode * 397) ^ this.R; + hashCode = (hashCode * 397) ^ this.A; + return hashCode; + } + } + + public void PackFromVector4(Vector4 vector) + { + throw new NotImplementedException(); + } + + public Vector4 ToVector4() + { + throw new NotImplementedException(); + } + + public void PackFromBytes(byte x, byte y, byte z, byte w) + { + throw new NotImplementedException(); + } + + public void ToXyzBytes(Span bytes, int startIndex) + { + throw new NotImplementedException(); + } + + public void ToXyzwBytes(Span bytes, int startIndex) + { + throw new NotImplementedException(); + } + + public void ToZyxBytes(Span bytes, int startIndex) + { + throw new NotImplementedException(); + } + + public void ToZyxwBytes(Span bytes, int startIndex) + { + throw new NotImplementedException(); + } + + /// + /// Gets or sets the packed representation of the Bgra32 struct. + /// + public uint Bgra + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return Unsafe.As(ref this); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + Unsafe.As(ref this) = value; + } + } + + /// + public uint PackedValue + { + get => this.Bgra; + set => this.Bgra = value; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/IPixel.cs b/src/ImageSharp/PixelFormats/IPixel.cs index 4e777cadf..07b0e03e8 100644 --- a/src/ImageSharp/PixelFormats/IPixel.cs +++ b/src/ImageSharp/PixelFormats/IPixel.cs @@ -49,7 +49,7 @@ namespace ImageSharp.PixelFormats /// The z-component. /// The w-component. void PackFromBytes(byte x, byte y, byte z, byte w); - + /// /// Expands the packed representation into a given byte array. /// Output is expanded to X-> Y-> Z order. Equivalent to R-> G-> B in diff --git a/src/ImageSharp/PixelFormats/Rgb24.cs b/src/ImageSharp/PixelFormats/Rgb24.cs index ff2b237ad..d52c86892 100644 --- a/src/ImageSharp/PixelFormats/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/Rgb24.cs @@ -41,7 +41,7 @@ namespace ImageSharp.PixelFormats public override bool Equals(object obj) { - return obj.GetType() == typeof(Rgb24) && this.Equals((Rgb24)obj); + return obj?.GetType() == typeof(Rgb24) && this.Equals((Rgb24)obj); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs index ba46332fb..32df4de7e 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.cs @@ -179,7 +179,11 @@ namespace ImageSharp } /// - public uint PackedValue { get => this.Rgba; set => this.Rgba = value; } + public uint PackedValue + { + get => this.Rgba; + set => this.Rgba = value; + } /// /// Compares two objects for equality. @@ -330,10 +334,10 @@ namespace ImageSharp { unchecked { - int hashCode = this.R.GetHashCode(); - hashCode = (hashCode * 397) ^ this.G.GetHashCode(); - hashCode = (hashCode * 397) ^ this.B.GetHashCode(); - hashCode = (hashCode * 397) ^ this.A.GetHashCode(); + int hashCode = this.R; + hashCode = (hashCode * 397) ^ this.G; + hashCode = (hashCode * 397) ^ this.B; + hashCode = (hashCode * 397) ^ this.A; return hashCode; } } diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs index 371163163..dcb75245d 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs @@ -52,8 +52,8 @@ namespace ImageSharp.Tests [InlineData(1, 255, 0, 0, 255, 0)] public void WhenFalse(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2) { - var a = new Rgb24(1, 2, 3); - var b = new Rgb24(1, 2, 4); + var a = new Rgb24(r1, g1, b1); + var b = new Rgb24(r2, g2, b2); Assert.False(a.Equals(b)); Assert.False(a.Equals((object)b)); diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs new file mode 100644 index 000000000..82be9e810 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs @@ -0,0 +1,70 @@ +namespace ImageSharp.Tests +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class Bgra32Tests + { + public static readonly TheoryData ColorData = + new TheoryData() + { + { 1, 2, 3, 4 }, { 4, 5, 6, 7 }, { 0, 255, 42, 0 }, { 1, 2, 3, 255 } + }; + + [Theory] + [MemberData(nameof(ColorData))] + public void Constructor(byte b, byte g, byte r, byte a) + { + var p = new Bgra32(r, g, b, a); + + Assert.Equal(r, p.R); + Assert.Equal(g, p.G); + Assert.Equal(b, p.B); + Assert.Equal(a, p.A); + } + + [Fact] + public unsafe void ByteLayoutIsSequentialBgra() + { + var color = new Bgra32(1, 2, 3, 4); + byte* ptr = (byte*)&color; + + Assert.Equal(3, ptr[0]); + Assert.Equal(2, ptr[1]); + Assert.Equal(1, ptr[2]); + Assert.Equal(4, ptr[3]); + } + + public class Equality + { + public static TheoryData ColorData = Bgra32Tests.ColorData; + + [Theory] + [MemberData(nameof(ColorData))] + public void WhenTrue(byte b, byte g, byte r, byte a) + { + var x = new Bgra32(r, g, b, a); + var y = new Bgra32(r, g, b, a); + + Assert.True(x.Equals(y)); + Assert.True(x.Equals((object)y)); + Assert.Equal(x.GetHashCode(), y.GetHashCode()); + } + + [Theory] + [InlineData(1, 2, 3, 4, 1, 2, 3, 5)] + [InlineData(0, 0, 255, 0, 0, 0, 244, 0)] + [InlineData(0, 255, 0, 0, 0, 244, 0, 0)] + [InlineData(1, 255, 0, 0, 0, 255, 0, 0)] + public void WhenFalse(byte b1, byte g1, byte r1, byte a1, byte b2, byte g2, byte r2, byte a2) + { + var x = new Bgra32(r1, g1, b1, a1); + var y = new Bgra32(r2, g2, b2, a2); + + Assert.False(x.Equals(y)); + Assert.False(x.Equals((object)y)); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs index 934d83bbb..6118e4432 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs @@ -54,8 +54,8 @@ namespace ImageSharp.Tests [InlineData(1, 255, 0, 0, 255, 0)] public void WhenFalse(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2) { - var a = new Rgb24(1, 2, 3); - var b = new Rgb24(1, 2, 4); + var a = new Rgb24(r1, g1, b1); + var b = new Rgb24(r2, g2, b2); Assert.False(a.Equals(b)); Assert.False(a.Equals((object)b)); From 35b5ac6ad0330d79f0c7805c05f3d8c18344f0db Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 16 May 2017 04:01:55 +0200 Subject: [PATCH 04/16] cleanup & fix stuff --- src/ImageSharp/PixelFormats/Alpha8.cs | 32 ++++---- src/ImageSharp/PixelFormats/Argb32.cs | 36 ++++----- src/ImageSharp/PixelFormats/Bgr24.cs | 35 ++++++-- src/ImageSharp/PixelFormats/Bgr565.cs | 36 ++++----- src/ImageSharp/PixelFormats/Bgra32.cs | 74 ++++++++++------- src/ImageSharp/PixelFormats/Bgra4444.cs | 36 ++++----- src/ImageSharp/PixelFormats/Bgra5551.cs | 47 ++++++----- src/ImageSharp/PixelFormats/Byte4.cs | 36 ++++----- src/ImageSharp/PixelFormats/HalfSingle.cs | 70 ++++++++-------- src/ImageSharp/PixelFormats/HalfVector2.cs | 70 ++++++++-------- src/ImageSharp/PixelFormats/HalfVector4.cs | 70 ++++++++-------- src/ImageSharp/PixelFormats/IPixel.cs | 37 ++++----- .../PixelFormats/NormalizedByte2.cs | 80 ++++++++----------- .../PixelFormats/NormalizedByte4.cs | 80 ++++++++----------- .../PixelFormats/NormalizedShort2.cs | 80 ++++++++----------- .../PixelFormats/NormalizedShort4.cs | 80 ++++++++----------- .../PixelFormats/PixelConversionExtensions.cs | 76 ++++++++++++++++++ .../PixelFormats/PixelOperations{TPixel}.cs | 8 +- src/ImageSharp/PixelFormats/Rg32.cs | 51 ++++++------ src/ImageSharp/PixelFormats/Rgb24.cs | 35 ++++++-- src/ImageSharp/PixelFormats/Rgba1010102.cs | 40 +++++----- src/ImageSharp/PixelFormats/Rgba32.cs | 39 ++++----- src/ImageSharp/PixelFormats/Rgba64.cs | 40 +++++----- src/ImageSharp/PixelFormats/RgbaVector.cs | 59 +++++++------- src/ImageSharp/PixelFormats/Short2.cs | 80 ++++++++----------- src/ImageSharp/PixelFormats/Short4.cs | 80 ++++++++----------- src/Shared/stylecop.json | 6 +- 27 files changed, 715 insertions(+), 698 deletions(-) create mode 100644 src/ImageSharp/PixelFormats/PixelConversionExtensions.cs diff --git a/src/ImageSharp/PixelFormats/Alpha8.cs b/src/ImageSharp/PixelFormats/Alpha8.cs index 582c28c78..6a78f15db 100644 --- a/src/ImageSharp/PixelFormats/Alpha8.cs +++ b/src/ImageSharp/PixelFormats/Alpha8.cs @@ -87,40 +87,36 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - bytes[startIndex] = 0; - bytes[startIndex + 1] = 0; - bytes[startIndex + 2] = 0; + dest = default(Rgb24); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - bytes[startIndex] = 0; - bytes[startIndex + 1] = 0; - bytes[startIndex + 2] = 0; - bytes[startIndex + 3] = this.PackedValue; + dest.R = 0; + dest.G = 0; + dest.B = 0; + dest.A = this.PackedValue; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - bytes[startIndex] = 0; - bytes[startIndex + 1] = 0; - bytes[startIndex + 2] = 0; + dest = default(Bgr24); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - bytes[startIndex] = 0; - bytes[startIndex + 1] = 0; - bytes[startIndex + 2] = 0; - bytes[startIndex + 3] = this.PackedValue; + dest.R = 0; + dest.G = 0; + dest.B = 0; + dest.A = this.PackedValue; } /// diff --git a/src/ImageSharp/PixelFormats/Argb32.cs b/src/ImageSharp/PixelFormats/Argb32.cs index 2ca1183a3..56c33df33 100644 --- a/src/ImageSharp/PixelFormats/Argb32.cs +++ b/src/ImageSharp/PixelFormats/Argb32.cs @@ -255,40 +255,40 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - bytes[startIndex] = this.R; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.B; + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - bytes[startIndex] = this.R; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.B; - bytes[startIndex + 3] = this.A; + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; + dest.A = this.A; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - bytes[startIndex] = this.B; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.R; + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - bytes[startIndex] = this.B; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.R; - bytes[startIndex + 3] = this.A; + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; + dest.A = this.A; } /// diff --git a/src/ImageSharp/PixelFormats/Bgr24.cs b/src/ImageSharp/PixelFormats/Bgr24.cs index 386320495..7430e37ab 100644 --- a/src/ImageSharp/PixelFormats/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/Bgr24.cs @@ -5,24 +5,34 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + /// + /// Pixel type containing three 8-bit unsigned normalized values ranging from 0 to 255. + /// The color components are stored in blue, green, red order. + /// [StructLayout(LayoutKind.Sequential)] public struct Bgr24 : IPixel { /// - /// Gets or sets the blue component. + /// The blue component. /// public byte B; /// - /// Gets or sets the green component. + /// The green component. /// public byte G; /// - /// Gets or sets the red component. + /// The red component. /// public byte R; + /// + /// Initializes a new instance of the struct. + /// + /// The red component. + /// The green component. + /// The blue component. [MethodImpl(MethodImplOptions.AggressiveInlining)] public Bgr24(byte r, byte g, byte b) { @@ -31,19 +41,23 @@ this.B = b; } + /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(Bgr24 other) { return this.R == other.R && this.G == other.G && this.B == other.B; } + /// public override bool Equals(object obj) { return obj?.GetType() == typeof(Bgr24) && this.Equals((Bgr24)obj); } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() { @@ -56,37 +70,44 @@ } } + /// public void PackFromBytes(byte x, byte y, byte z, byte w) { throw new NotImplementedException(); } + /// public void PackFromVector4(Vector4 vector) { throw new NotImplementedException(); } + /// public Vector4 ToVector4() { throw new NotImplementedException(); } - public void ToXyzBytes(Span bytes, int startIndex) + /// + public void ToRgb24(ref Rgb24 dest) { throw new NotImplementedException(); } - public void ToXyzwBytes(Span bytes, int startIndex) + /// + public void ToRgba32(ref Rgba32 dest) { throw new NotImplementedException(); } - public void ToZyxBytes(Span bytes, int startIndex) + /// + public void ToBgr24(ref Bgr24 dest) { throw new NotImplementedException(); } - public void ToZyxwBytes(Span bytes, int startIndex) + /// + public void ToBgra32(ref Bgra32 dest) { throw new NotImplementedException(); } diff --git a/src/ImageSharp/PixelFormats/Bgr565.cs b/src/ImageSharp/PixelFormats/Bgr565.cs index 6a568eeb5..4f6b6aa20 100644 --- a/src/ImageSharp/PixelFormats/Bgr565.cs +++ b/src/ImageSharp/PixelFormats/Bgr565.cs @@ -110,44 +110,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { Vector4 vector = this.ToVector4() * 255F; - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.Z); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { Vector4 vector = this.ToVector4() * 255F; - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 3] = (byte)MathF.Round(vector.W); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { Vector4 vector = this.ToVector4() * 255F; - bytes[startIndex] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { Vector4 vector = this.ToVector4() * 255F; - bytes[startIndex] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); - bytes[startIndex + 3] = (byte)MathF.Round(vector.W); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// diff --git a/src/ImageSharp/PixelFormats/Bgra32.cs b/src/ImageSharp/PixelFormats/Bgra32.cs index 582a0cd92..3ad6bd336 100644 --- a/src/ImageSharp/PixelFormats/Bgra32.cs +++ b/src/ImageSharp/PixelFormats/Bgra32.cs @@ -7,6 +7,10 @@ using ImageSharp.PixelFormats; + /// + /// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255. + /// The color components are stored in blue, green, red, and alpha order. + /// [StructLayout(LayoutKind.Sequential)] public struct Bgra32 : IPixel, IPackedVector { @@ -45,7 +49,6 @@ this.A = 255; } - /// /// Initializes a new instance of the struct. /// @@ -62,15 +65,44 @@ this.A = a; } + /// + /// Gets or sets the packed representation of the Bgra32 struct. + /// + public uint Bgra + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return Unsafe.As(ref this); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + Unsafe.As(ref this) = value; + } + } + + /// + public uint PackedValue + { + get => this.Bgra; + set => this.Bgra = value; + } + + /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// public bool Equals(Bgra32 other) { return this.R == other.R && this.G == other.G && this.B == other.B && this.A == other.A; } + /// public override bool Equals(object obj) => obj?.GetType() == typeof(Bgra32) && this.Equals((Bgra32)obj); + /// public override int GetHashCode() { unchecked @@ -83,64 +115,46 @@ } } + /// public void PackFromVector4(Vector4 vector) { throw new NotImplementedException(); } + /// public Vector4 ToVector4() { throw new NotImplementedException(); } + /// public void PackFromBytes(byte x, byte y, byte z, byte w) { throw new NotImplementedException(); } - public void ToXyzBytes(Span bytes, int startIndex) - { - throw new NotImplementedException(); - } - - public void ToXyzwBytes(Span bytes, int startIndex) + /// + public void ToRgb24(ref Rgb24 dest) { throw new NotImplementedException(); } - public void ToZyxBytes(Span bytes, int startIndex) + /// + public void ToRgba32(ref Rgba32 dest) { throw new NotImplementedException(); } - public void ToZyxwBytes(Span bytes, int startIndex) + /// + public void ToBgr24(ref Bgr24 dest) { throw new NotImplementedException(); } - /// - /// Gets or sets the packed representation of the Bgra32 struct. - /// - public uint Bgra - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return Unsafe.As(ref this); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - set - { - Unsafe.As(ref this) = value; - } - } - /// - public uint PackedValue + public void ToBgra32(ref Bgra32 dest) { - get => this.Bgra; - set => this.Bgra = value; + throw new NotImplementedException(); } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Bgra4444.cs b/src/ImageSharp/PixelFormats/Bgra4444.cs index 2dafd0c98..2c60aa900 100644 --- a/src/ImageSharp/PixelFormats/Bgra4444.cs +++ b/src/ImageSharp/PixelFormats/Bgra4444.cs @@ -101,44 +101,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { Vector4 vector = this.ToVector4() * 255F; - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { Vector4 vector = this.ToVector4() * 255F; - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { Vector4 vector = this.ToVector4() * 255F; - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { Vector4 vector = this.ToVector4() * 255F; - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// diff --git a/src/ImageSharp/PixelFormats/Bgra5551.cs b/src/ImageSharp/PixelFormats/Bgra5551.cs index 67fb4e0ec..9812059a2 100644 --- a/src/ImageSharp/PixelFormats/Bgra5551.cs +++ b/src/ImageSharp/PixelFormats/Bgra5551.cs @@ -101,44 +101,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToVector4() * 255F; - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToVector4() * 255F; - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToVector4() * 255F; - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToVector4() * 255F; - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// @@ -190,5 +190,8 @@ namespace ImageSharp.PixelFormats (((int)Math.Round(z.Clamp(0, 1) * 31F) & 0x1F) << 0) | (((int)Math.Round(w.Clamp(0, 1)) & 0x1) << 15)); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Vector4 ToScaledVector4() => this.ToVector4() * 255f; } } diff --git a/src/ImageSharp/PixelFormats/Byte4.cs b/src/ImageSharp/PixelFormats/Byte4.cs index 2a0e6d75c..a5fcfe8bf 100644 --- a/src/ImageSharp/PixelFormats/Byte4.cs +++ b/src/ImageSharp/PixelFormats/Byte4.cs @@ -102,44 +102,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { Vector4 vector = this.ToVector4(); - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { Vector4 vector = this.ToVector4(); - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { Vector4 vector = this.ToVector4(); - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { Vector4 vector = this.ToVector4(); - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// diff --git a/src/ImageSharp/PixelFormats/HalfSingle.cs b/src/ImageSharp/PixelFormats/HalfSingle.cs index b6f93d059..441ee5417 100644 --- a/src/ImageSharp/PixelFormats/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/HalfSingle.cs @@ -111,60 +111,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToVector4(); - vector *= MaxBytes; - vector += Half; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToVector4(); - vector *= MaxBytes; - vector += Half; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToVector4(); - vector *= MaxBytes; - vector += Half; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToVector4(); - vector *= MaxBytes; - vector += Half; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// @@ -192,5 +176,15 @@ namespace ImageSharp.PixelFormats { return this.PackedValue.GetHashCode(); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Vector4 ToScaledVector4() + { + Vector4 vector = this.ToVector4(); + vector *= MaxBytes; + vector += Half; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + return vector; + } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/HalfVector2.cs b/src/ImageSharp/PixelFormats/HalfVector2.cs index e96c5c076..373b4f970 100644 --- a/src/ImageSharp/PixelFormats/HalfVector2.cs +++ b/src/ImageSharp/PixelFormats/HalfVector2.cs @@ -125,60 +125,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToVector4(); - vector *= MaxBytes; - vector += Half; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToVector4(); - vector *= MaxBytes; - vector += Half; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; + dest.A = 255; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToVector4(); - vector *= MaxBytes; - vector += Half; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToVector4(); - vector *= MaxBytes; - vector += Half; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; + dest.A = 255; } /// @@ -220,5 +204,15 @@ namespace ImageSharp.PixelFormats uint num = (uint)(HalfTypeHelper.Pack(y) << 0x10); return num2 | num; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Vector4 ToScaledVector4() + { + Vector4 vector = this.ToVector4(); + vector *= MaxBytes; + vector += Half; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + return vector; + } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/HalfVector4.cs b/src/ImageSharp/PixelFormats/HalfVector4.cs index d84a40198..cd079146e 100644 --- a/src/ImageSharp/PixelFormats/HalfVector4.cs +++ b/src/ImageSharp/PixelFormats/HalfVector4.cs @@ -118,60 +118,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToVector4(); - vector *= MaxBytes; - vector += Half; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToVector4(); - vector *= MaxBytes; - vector += Half; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToVector4(); - vector *= MaxBytes; - vector += Half; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToVector4(); - vector *= MaxBytes; - vector += Half; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// @@ -214,5 +198,15 @@ namespace ImageSharp.PixelFormats ulong num1 = (ulong)HalfTypeHelper.Pack(vector.W) << 0x30; return num4 | num3 | num2 | num1; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Vector4 ToScaledVector4() + { + Vector4 vector = this.ToVector4(); + vector *= MaxBytes; + vector += Half; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + return vector; + } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/IPixel.cs b/src/ImageSharp/PixelFormats/IPixel.cs index 07b0e03e8..9acaa4eba 100644 --- a/src/ImageSharp/PixelFormats/IPixel.cs +++ b/src/ImageSharp/PixelFormats/IPixel.cs @@ -44,42 +44,37 @@ namespace ImageSharp.PixelFormats /// /// Sets the packed representation from the given byte array. /// + /// + /// TODO: Consider defining multiple PackFrom***() methods instead. (Similar to the opposite direction API.) + /// /// The x-component. /// The y-component. /// The z-component. /// The w-component. void PackFromBytes(byte x, byte y, byte z, byte w); - + /// - /// Expands the packed representation into a given byte array. - /// Output is expanded to X-> Y-> Z order. Equivalent to R-> G-> B in + /// Converts the pixel to format. /// - /// The bytes to set the color in. - /// The starting index of the . - void ToXyzBytes(Span bytes, int startIndex); + /// The destination pixel to write to + void ToRgb24(ref Rgb24 dest); /// - /// Expands the packed representation into a given byte array. - /// Output is expanded to X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in + /// Converts the pixel to format. /// - /// The bytes to set the color in. - /// The starting index of the . - void ToXyzwBytes(Span bytes, int startIndex); + /// The destination pixel to write to + void ToRgba32(ref Rgba32 dest); /// - /// Expands the packed representation into a given byte array. - /// Output is expanded to Z-> Y-> X order. Equivalent to B-> G-> R in + /// Converts the pixel to format. /// - /// The bytes to set the color in. - /// The starting index of the . - void ToZyxBytes(Span bytes, int startIndex); + /// The destination pixel to write to + void ToBgr24(ref Bgr24 dest); /// - /// Expands the packed representation into a given byte array. - /// Output is expanded to Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in + /// Converts the pixel to format. /// - /// The bytes to set the color in. - /// The starting index of the . - void ToZyxwBytes(Span bytes, int startIndex); + /// The destination pixel to write to + void ToBgra32(ref Bgra32 dest); } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/NormalizedByte2.cs index d1193e9c1..44641710b 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte2.cs @@ -134,68 +134,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = 0; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = 0; - bytes[startIndex + 3] = 255; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; + dest.A = 255; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = 0; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = 0; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = 255; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; + dest.A = 255; } /// @@ -238,5 +214,17 @@ namespace ImageSharp.PixelFormats return (ushort)(byte2 | byte1); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Vector4 ToScaledVector4() + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + return vector; + } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/NormalizedByte4.cs index 565f26971..86f00ed84 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte4.cs @@ -127,68 +127,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// @@ -235,5 +211,17 @@ namespace ImageSharp.PixelFormats return byte4 | byte3 | byte2 | byte1; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Vector4 ToScaledVector4() + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + return vector; + } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/NormalizedShort2.cs b/src/ImageSharp/PixelFormats/NormalizedShort2.cs index 5b791eb25..fb11c16af 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort2.cs @@ -121,68 +121,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = 0; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = 0; - bytes[startIndex + 3] = 255; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; + dest.A = 255; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = 0; - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = 0; - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); - bytes[startIndex + 3] = 255; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; + dest.A = 255; } /// @@ -245,5 +221,17 @@ namespace ImageSharp.PixelFormats return word2 | word1; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Vector4 ToScaledVector4() + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + return vector; + } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/NormalizedShort4.cs index 047c6a250..0da68b65e 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort4.cs @@ -129,68 +129,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.Z); + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 3] = (byte)MathF.Round(vector.W); + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToVector4(); - vector *= Half; - vector += Round; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); - bytes[startIndex + 3] = (byte)MathF.Round(vector.W); + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// @@ -241,5 +217,17 @@ namespace ImageSharp.PixelFormats return word4 | word3 | word2 | word1; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Vector4 ToScaledVector4() + { + Vector4 vector = this.ToVector4(); + vector *= Half; + vector += Round; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + return vector; + } } } diff --git a/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs b/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs new file mode 100644 index 000000000..c75719dc6 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs @@ -0,0 +1,76 @@ +namespace ImageSharp.PixelFormats +{ + using System; + using System.Runtime.CompilerServices; + + /// + /// Extension methods for copying single pixel data into byte Spans. + /// TODO: This utility class exists for legacy reasons. Need to do a lot of chore work to remove it (mostly in test classes). + /// + internal static class PixelConversionExtensions + { + /// + /// Expands the packed representation into a given byte array. + /// Output is expanded to X-> Y-> Z order. Equivalent to R-> G-> B in + /// + /// The pixel type. + /// The pixel to copy the data from. + /// The bytes to set the color in. + /// The starting index of the . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ToXyzBytes(this TPixel pixel, Span bytes, int startIndex) + where TPixel : struct, IPixel + { + ref Rgb24 dest = ref Unsafe.As(ref bytes[startIndex]); + pixel.ToRgb24(ref dest); + } + + /// + /// Expands the packed representation into a given byte array. + /// Output is expanded to X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in + /// + /// The pixel type. + /// The pixel to copy the data from. + /// The bytes to set the color in. + /// The starting index of the . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ToXyzwBytes(this TPixel pixel, Span bytes, int startIndex) + where TPixel : struct, IPixel + { + ref Rgba32 dest = ref Unsafe.As(ref bytes[startIndex]); + pixel.ToRgba32(ref dest); + } + + /// + /// Expands the packed representation into a given byte array. + /// Output is expanded to Z-> Y-> X order. Equivalent to B-> G-> R in + /// + /// The pixel type. + /// The pixel to copy the data from. + /// The bytes to set the color in. + /// The starting index of the . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ToZyxBytes(this TPixel pixel, Span bytes, int startIndex) + where TPixel : struct, IPixel + { + ref Bgr24 dest = ref Unsafe.As(ref bytes[startIndex]); + pixel.ToBgr24(ref dest); + } + + /// + /// Expands the packed representation into a given byte array. + /// Output is expanded to Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in + /// + /// The pixel type. + /// The pixel to copy the data from. + /// The bytes to set the color in. + /// The starting index of the . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ToZyxwBytes(this TPixel pixel, Span bytes, int startIndex) + where TPixel : struct, IPixel + { + ref Bgra32 dest = ref Unsafe.As(ref bytes[startIndex]); + pixel.ToBgra32(ref dest); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 5c51b59f8..918662144 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -93,7 +93,7 @@ namespace ImageSharp.PixelFormats } /// - /// Bulk version of . + /// Bulk version of . /// /// The to the source colors. /// The to the destination bytes. @@ -139,7 +139,7 @@ namespace ImageSharp.PixelFormats } /// - /// Bulk version of + /// Bulk version of /// /// The to the source colors. /// The to the destination bytes. @@ -185,7 +185,7 @@ namespace ImageSharp.PixelFormats } /// - /// Bulk version of . + /// Bulk version of . /// /// The to the source colors. /// The to the destination bytes. @@ -231,7 +231,7 @@ namespace ImageSharp.PixelFormats } /// - /// Bulk version of . + /// Bulk version of . /// /// The to the source colors. /// The to the destination bytes. diff --git a/src/ImageSharp/PixelFormats/Rg32.cs b/src/ImageSharp/PixelFormats/Rg32.cs index 0faf2fe80..86b516ede 100644 --- a/src/ImageSharp/PixelFormats/Rg32.cs +++ b/src/ImageSharp/PixelFormats/Rg32.cs @@ -114,48 +114,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToVector4() * 255F; - - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToVector4() * 255F; - - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToVector4() * 255F; - - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToVector4() * 255F; - - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// @@ -197,5 +193,8 @@ namespace ImageSharp.PixelFormats ((int)Math.Round(x.Clamp(0, 1) * 65535F) & 0xFFFF) | (((int)Math.Round(y.Clamp(0, 1) * 65535F) & 0xFFFF) << 16)); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Vector4 ToScaledVector4() => this.ToVector4() * 255f; } } diff --git a/src/ImageSharp/PixelFormats/Rgb24.cs b/src/ImageSharp/PixelFormats/Rgb24.cs index d52c86892..196c02d7c 100644 --- a/src/ImageSharp/PixelFormats/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/Rgb24.cs @@ -5,24 +5,34 @@ namespace ImageSharp.PixelFormats using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + /// + /// Pixel type containing three 8-bit unsigned normalized values ranging from 0 to 255. + /// The color components are stored in red, green, blue order. + /// [StructLayout(LayoutKind.Sequential)] public struct Rgb24 : IPixel { /// - /// Gets or sets the red component. + /// The red component. /// public byte R; /// - /// Gets or sets the green component. + /// The green component. /// public byte G; /// - /// Gets or sets the blue component. + /// The blue component. /// public byte B; + /// + /// Initializes a new instance of the struct. + /// + /// The red component. + /// The green component. + /// The blue component. [MethodImpl(MethodImplOptions.AggressiveInlining)] public Rgb24(byte r, byte g, byte b) { @@ -31,19 +41,23 @@ namespace ImageSharp.PixelFormats this.B = b; } + /// public PixelOperations CreatePixelOperations() => new PixelOperations(); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(Rgb24 other) { return this.R == other.R && this.G == other.G && this.B == other.B; } + /// public override bool Equals(object obj) { return obj?.GetType() == typeof(Rgb24) && this.Equals((Rgb24)obj); } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() { @@ -56,37 +70,44 @@ namespace ImageSharp.PixelFormats } } + /// public void PackFromBytes(byte x, byte y, byte z, byte w) { throw new NotImplementedException(); } + /// public void PackFromVector4(Vector4 vector) { throw new NotImplementedException(); } + /// public Vector4 ToVector4() { throw new NotImplementedException(); } - public void ToXyzBytes(Span bytes, int startIndex) + /// + public void ToRgb24(ref Rgb24 dest) { throw new NotImplementedException(); } - public void ToXyzwBytes(Span bytes, int startIndex) + /// + public void ToRgba32(ref Rgba32 dest) { throw new NotImplementedException(); } - public void ToZyxBytes(Span bytes, int startIndex) + /// + public void ToBgr24(ref Bgr24 dest) { throw new NotImplementedException(); } - public void ToZyxwBytes(Span bytes, int startIndex) + /// + public void ToBgra32(ref Bgra32 dest) { throw new NotImplementedException(); } diff --git a/src/ImageSharp/PixelFormats/Rgba1010102.cs b/src/ImageSharp/PixelFormats/Rgba1010102.cs index 8eaf5f771..935f69795 100644 --- a/src/ImageSharp/PixelFormats/Rgba1010102.cs +++ b/src/ImageSharp/PixelFormats/Rgba1010102.cs @@ -108,48 +108,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { Vector4 vector = this.ToVector4() * 255F; - - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.Z); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { Vector4 vector = this.ToVector4() * 255F; - - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 3] = (byte)MathF.Round(vector.W); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { Vector4 vector = this.ToVector4() * 255F; - - bytes[startIndex] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { Vector4 vector = this.ToVector4() * 255F; - - bytes[startIndex] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); - bytes[startIndex + 3] = (byte)MathF.Round(vector.W); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs index 32df4de7e..840018792 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.cs @@ -255,42 +255,37 @@ namespace ImageSharp return hexOrder.ToString("X8"); } - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - bytes[startIndex] = this.R; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.B; + dest = Unsafe.As(ref this); } - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - bytes[startIndex] = this.R; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.B; - bytes[startIndex + 3] = this.A; + dest = this; } - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - bytes[startIndex] = this.B; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.R; + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; } - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - bytes[startIndex] = this.B; - bytes[startIndex + 1] = this.G; - bytes[startIndex + 2] = this.R; - bytes[startIndex + 3] = this.A; + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; + dest.A = this.A; } /// diff --git a/src/ImageSharp/PixelFormats/Rgba64.cs b/src/ImageSharp/PixelFormats/Rgba64.cs index 2101d4ba0..92a839ddf 100644 --- a/src/ImageSharp/PixelFormats/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/Rgba64.cs @@ -107,48 +107,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { Vector4 vector = this.ToVector4() * 255F; - - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.Z); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { Vector4 vector = this.ToVector4() * 255F; - - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 3] = (byte)MathF.Round(vector.W); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { Vector4 vector = this.ToVector4() * 255F; - - bytes[startIndex] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { Vector4 vector = this.ToVector4() * 255F; - - bytes[startIndex] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); - bytes[startIndex + 3] = (byte)MathF.Round(vector.W); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// diff --git a/src/ImageSharp/PixelFormats/RgbaVector.cs b/src/ImageSharp/PixelFormats/RgbaVector.cs index 314ac31e3..f3498705d 100644 --- a/src/ImageSharp/PixelFormats/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/RgbaVector.cs @@ -233,50 +233,46 @@ namespace ImageSharp.PixelFormats return hexOrder.ToString("X8"); } - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes; - vector += Half; - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes; - vector += Half; - bytes[startIndex] = (byte)vector.X; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.Z; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes; - vector += Half; - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes; - vector += Half; - bytes[startIndex] = (byte)vector.Z; - bytes[startIndex + 1] = (byte)vector.Y; - bytes[startIndex + 2] = (byte)vector.X; - bytes[startIndex + 3] = (byte)vector.W; + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// @@ -320,5 +316,8 @@ namespace ImageSharp.PixelFormats { return this.backingVector.GetHashCode(); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Vector4 ToScaledVector4() => Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes; } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Short2.cs b/src/ImageSharp/PixelFormats/Short2.cs index a6fe95b49..d369a6aae 100644 --- a/src/ImageSharp/PixelFormats/Short2.cs +++ b/src/ImageSharp/PixelFormats/Short2.cs @@ -119,68 +119,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - Vector2 vector = this.ToVector2(); - vector /= 65534; - vector *= 255; - vector += Half; - vector += Round; - vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes); - - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = 0; + Vector2 vector = this.ToScaledVector2(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - Vector2 vector = this.ToVector2(); - vector /= 65534; - vector *= 255; - vector += Half; - vector += Round; - vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes); - - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = 0; - bytes[startIndex + 3] = 255; + Vector2 vector = this.ToScaledVector2(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; + dest.A = 255; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - Vector2 vector = this.ToVector2(); - vector /= 65534; - vector *= 255; - vector += Half; - vector += Round; - vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes); - - bytes[startIndex] = 0; - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); + Vector2 vector = this.ToScaledVector2(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - Vector2 vector = this.ToVector2(); - vector /= 65534; - vector *= 255; - vector += Half; - vector += Round; - vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes); - - bytes[startIndex] = 0; - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); - bytes[startIndex + 3] = 255; + Vector2 vector = this.ToScaledVector2(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = 0; + dest.A = 255; } /// @@ -239,5 +215,17 @@ namespace ImageSharp.PixelFormats return word2 | word1; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Vector2 ToScaledVector2() + { + Vector2 vector = this.ToVector2(); + vector /= 65534; + vector *= 255; + vector += Half; + vector += Round; + vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes); + return vector; + } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Short4.cs b/src/ImageSharp/PixelFormats/Short4.cs index f254c7379..9f7a5d887 100644 --- a/src/ImageSharp/PixelFormats/Short4.cs +++ b/src/ImageSharp/PixelFormats/Short4.cs @@ -125,68 +125,44 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzBytes(Span bytes, int startIndex) + public void ToRgb24(ref Rgb24 dest) { - Vector4 vector = this.ToVector4(); - vector /= 65534; - vector *= 255; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.Z); + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToXyzwBytes(Span bytes, int startIndex) + public void ToRgba32(ref Rgba32 dest) { - Vector4 vector = this.ToVector4(); - vector /= 65534; - vector *= 255; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)MathF.Round(vector.X); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 3] = (byte)MathF.Round(vector.W); + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxBytes(Span bytes, int startIndex) + public void ToBgr24(ref Bgr24 dest) { - Vector4 vector = this.ToVector4(); - vector /= 65534; - vector *= 255; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ToZyxwBytes(Span bytes, int startIndex) + public void ToBgra32(ref Bgra32 dest) { - Vector4 vector = this.ToVector4(); - vector /= 65534; - vector *= 255; - vector += Half; - vector += Round; - vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - - bytes[startIndex] = (byte)MathF.Round(vector.Z); - bytes[startIndex + 1] = (byte)MathF.Round(vector.Y); - bytes[startIndex + 2] = (byte)MathF.Round(vector.X); - bytes[startIndex + 3] = (byte)MathF.Round(vector.W); + Vector4 vector = this.ToScaledVector4(); + dest.R = (byte)MathF.Round(vector.X); + dest.G = (byte)MathF.Round(vector.Y); + dest.B = (byte)MathF.Round(vector.Z); + dest.A = (byte)MathF.Round(vector.W); } /// @@ -246,5 +222,17 @@ namespace ImageSharp.PixelFormats return word4 | word3 | word2 | word1; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Vector4 ToScaledVector4() + { + Vector4 vector = this.ToVector4(); + vector /= 65534; + vector *= 255; + vector += Half; + vector += Round; + vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); + return vector; + } } } \ No newline at end of file diff --git a/src/Shared/stylecop.json b/src/Shared/stylecop.json index b74a0af91..df8f120a5 100644 --- a/src/Shared/stylecop.json +++ b/src/Shared/stylecop.json @@ -3,11 +3,7 @@ "settings": { "documentationRules": { "companyName": "James Jackson-South", - "copyrightText": "Copyright (c) James Jackson-South and contributors.\nLicensed under the Apache License, Version 2.0.", - - "documentInterfaces": false, - "documentInternalElements": false, - "documentExposedElements": false + "copyrightText": "Copyright (c) James Jackson-South and contributors.\nLicensed under the Apache License, Version 2.0." } } } \ No newline at end of file From 579f3b5d523a11932037a052bff6a09d0da5fd6d Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 16 May 2017 04:17:07 +0200 Subject: [PATCH 05/16] changed TODO text --- src/ImageSharp/PixelFormats/IPixel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/PixelFormats/IPixel.cs b/src/ImageSharp/PixelFormats/IPixel.cs index 9acaa4eba..8e0631b70 100644 --- a/src/ImageSharp/PixelFormats/IPixel.cs +++ b/src/ImageSharp/PixelFormats/IPixel.cs @@ -45,7 +45,7 @@ namespace ImageSharp.PixelFormats /// Sets the packed representation from the given byte array. /// /// - /// TODO: Consider defining multiple PackFrom***() methods instead. (Similar to the opposite direction API.) + /// TODO: Refactor this, defining multiple PackFromAsdf42(ref Asdf42 source) methods instead. Should be faster on many execution paths! /// /// The x-component. /// The y-component. From 8f41f1ae7dacfb83feceaf9fd0f1357cdc1b49f0 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 18 May 2017 04:16:02 +0200 Subject: [PATCH 06/16] more benchmarks + removed obsolete TODO note --- src/ImageSharp/PixelFormats/IPixel.cs | 3 - .../PixelConversion_ConvertFromRgba32.cs | 206 ++++++++++++++++++ .../PixelConversion_ConvertFromVector4.cs | 156 +++++++++++++ ....cs => PixelConversion_ConvertToRgba32.cs} | 22 +- 4 files changed, 373 insertions(+), 14 deletions(-) create mode 100644 tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromRgba32.cs create mode 100644 tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromVector4.cs rename tests/ImageSharp.Benchmarks/General/{PixelConversion.cs => PixelConversion_ConvertToRgba32.cs} (86%) diff --git a/src/ImageSharp/PixelFormats/IPixel.cs b/src/ImageSharp/PixelFormats/IPixel.cs index 8e0631b70..cc261e2eb 100644 --- a/src/ImageSharp/PixelFormats/IPixel.cs +++ b/src/ImageSharp/PixelFormats/IPixel.cs @@ -44,9 +44,6 @@ namespace ImageSharp.PixelFormats /// /// Sets the packed representation from the given byte array. /// - /// - /// TODO: Refactor this, defining multiple PackFromAsdf42(ref Asdf42 source) methods instead. Should be faster on many execution paths! - /// /// The x-component. /// The y-component. /// The z-component. diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromRgba32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromRgba32.cs new file mode 100644 index 000000000..e096fd828 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromRgba32.cs @@ -0,0 +1,206 @@ +// ReSharper disable InconsistentNaming +namespace ImageSharp.Benchmarks.General +{ + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + + using BenchmarkDotNet.Attributes; + + public class PixelConversion_ConvertFromRgba32 + { + interface ITestPixel + where T : struct, ITestPixel + { + void FromRgba32(Rgba32 source); + + void FromRgba32(ref Rgba32 source); + + void FromBytes(byte r, byte g, byte b, byte a); + } + + [StructLayout(LayoutKind.Sequential)] + struct TestArgb : ITestPixel + { + private byte a, r, g, b; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FromRgba32(Rgba32 p) + { + this.r = p.R; + this.g = p.G; + this.b = p.B; + this.a = p.A; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FromRgba32(ref Rgba32 p) + { + this.r = p.R; + this.g = p.G; + this.b = p.B; + this.a = p.A; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FromBytes(byte r, byte g, byte b, byte a) + { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + } + + [StructLayout(LayoutKind.Sequential)] + struct TestRgba : ITestPixel + { + private byte r, g, b, a; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FromRgba32(Rgba32 source) + { + this = Unsafe.As(ref source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FromRgba32(ref Rgba32 source) + { + this = Unsafe.As(ref source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FromBytes(byte r, byte g, byte b, byte a) + { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + } + + struct ConversionRunner + where T : struct, ITestPixel + { + private T[] dest; + + private Rgba32[] source; + + public ConversionRunner(int count) + { + this.dest = new T[count]; + this.source = new Rgba32[count]; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RunByRefConversion() + { + int count = this.dest.Length; + + ref T destBaseRef = ref this.dest[0]; + ref Rgba32 sourceBaseRef = ref this.source[0]; + + for (int i = 0; i < count; i++) + { + Unsafe.Add(ref destBaseRef, i).FromRgba32(ref Unsafe.Add(ref sourceBaseRef, i)); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RunByValConversion() + { + int count = this.dest.Length; + + ref T destBaseRef = ref this.dest[0]; + ref Rgba32 sourceBaseRef = ref this.source[0]; + + for (int i = 0; i < count; i++) + { + Unsafe.Add(ref destBaseRef, i).FromRgba32(Unsafe.Add(ref sourceBaseRef, i)); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RunFromBytesConversion() + { + int count = this.dest.Length; + + ref T destBaseRef = ref this.dest[0]; + ref Rgba32 sourceBaseRef = ref this.source[0]; + + for (int i = 0; i < count; i++) + { + ref Rgba32 s = ref Unsafe.Add(ref sourceBaseRef, i); + Unsafe.Add(ref destBaseRef, i).FromBytes(s.R, s.G, s.B, s.A); + } + } + } + + private ConversionRunner compatibleMemLayoutRunner; + + private ConversionRunner permutedRunner; + + [Params(32)] + public int Count { get; set; } + + [Setup] + public void Setup() + { + this.compatibleMemLayoutRunner = new ConversionRunner(this.Count); + this.permutedRunner = new ConversionRunner(this.Count); + } + + [Benchmark(Baseline = true)] + public void CompatibleByRef() + { + this.compatibleMemLayoutRunner.RunByRefConversion(); + } + + [Benchmark] + public void CompatibleByVal() + { + this.compatibleMemLayoutRunner.RunByValConversion(); + } + + [Benchmark] + public void CompatibleFromBytes() + { + this.compatibleMemLayoutRunner.RunFromBytesConversion(); + } + + + [Benchmark] + public void PermutedByRef() + { + this.permutedRunner.RunByRefConversion(); + } + + [Benchmark] + public void PermutedByVal() + { + this.permutedRunner.RunByValConversion(); + } + + [Benchmark] + public void PermutedFromBytes() + { + this.permutedRunner.RunFromBytesConversion(); + } + } + + /* + * Results: + * Method | Count | Mean | StdDev | Scaled | Scaled-StdDev | + * ------------------ |------ |----------- |---------- |------- |-------------- | + * CompatibleByRef | 32 | 20.6339 ns | 0.0742 ns | 1.00 | 0.00 | + * CompatibleByVal | 32 | 23.7425 ns | 0.0997 ns | 1.15 | 0.01 | + * CompatibleFromBytes | 32 | 38.7017 ns | 0.1103 ns | 1.88 | 0.01 | + * PermutedByRef | 32 | 39.2892 ns | 0.1366 ns | 1.90 | 0.01 | + * PermutedByVal | 32 | 38.5178 ns | 0.1946 ns | 1.87 | 0.01 | + * PermutedFromBytes | 32 | 38.6683 ns | 0.0801 ns | 1.87 | 0.01 | + * + * !!! Conclusion !!! + * All memory-incompatible (permuted) variants are equivalent with the the "FromBytes" solution. + * In memory compatible cases we should use the optimized Bulk-copying variant anyways, + * so there is no benefit introducing non-bulk API-s other than PackFromBytes() OR PackFromRgba32(). + */ +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromVector4.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromVector4.cs new file mode 100644 index 000000000..721ac121a --- /dev/null +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromVector4.cs @@ -0,0 +1,156 @@ +// ReSharper disable InconsistentNaming +namespace ImageSharp.Benchmarks.General +{ + using System.Numerics; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + + using BenchmarkDotNet.Attributes; + + public class PixelConversion_ConvertFromVector4 + { + interface ITestPixel + where T : struct, ITestPixel + { + void FromVector4(Vector4 source); + + void FromVector4(ref Vector4 source); + } + + [StructLayout(LayoutKind.Sequential)] + struct TestArgb : ITestPixel + { + private byte a, r, g, b; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FromVector4(Vector4 p) + { + this.r = (byte)p.X; + this.g = (byte)p.Y; + this.b = (byte)p.Z; + this.a = (byte)p.W; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FromVector4(ref Vector4 p) + { + this.r = (byte)p.X; + this.g = (byte)p.Y; + this.b = (byte)p.Z; + this.a = (byte)p.W; + } + } + + [StructLayout(LayoutKind.Sequential)] + struct TestRgbaVector : ITestPixel + { + private Vector4 v; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FromVector4(Vector4 p) + { + this.v = p; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FromVector4(ref Vector4 p) + { + this.v = p; + } + } + + struct ConversionRunner + where T : struct, ITestPixel + { + private T[] dest; + + private Vector4[] source; + + public ConversionRunner(int count) + { + this.dest = new T[count]; + this.source = new Vector4[count]; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RunByRefConversion() + { + int count = this.dest.Length; + + ref T destBaseRef = ref this.dest[0]; + ref Vector4 sourceBaseRef = ref this.source[0]; + + for (int i = 0; i < count; i++) + { + Unsafe.Add(ref destBaseRef, i).FromVector4(ref Unsafe.Add(ref sourceBaseRef, i)); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RunByValConversion() + { + int count = this.dest.Length; + + ref T destBaseRef = ref this.dest[0]; + ref Vector4 sourceBaseRef = ref this.source[0]; + + for (int i = 0; i < count; i++) + { + Unsafe.Add(ref destBaseRef, i).FromVector4(Unsafe.Add(ref sourceBaseRef, i)); + } + } + } + + private ConversionRunner nonVectorRunner; + + private ConversionRunner vectorRunner; + + [Params(32)] + public int Count { get; set; } + + [Setup] + public void Setup() + { + this.nonVectorRunner = new ConversionRunner(this.Count); + this.vectorRunner = new ConversionRunner(this.Count); + } + + [Benchmark(Baseline = true)] + public void VectorByRef() + { + this.vectorRunner.RunByRefConversion(); + } + + [Benchmark] + public void VectorByVal() + { + this.vectorRunner.RunByValConversion(); + } + + [Benchmark] + public void NonVectorByRef() + { + this.nonVectorRunner.RunByRefConversion(); + } + + [Benchmark] + public void NonVectorByVal() + { + this.nonVectorRunner.RunByValConversion(); + } + + } + + /* + * Results: + * Method | Count | Mean | StdDev | Scaled | Scaled-StdDev | + * --------------- |------ |----------- |---------- |------- |-------------- | + * VectorByRef | 32 | 23.6678 ns | 0.1141 ns | 1.00 | 0.00 | + * VectorByVal | 32 | 24.5347 ns | 0.0771 ns | 1.04 | 0.01 | + * NonVectorByRef | 32 | 59.0187 ns | 0.2114 ns | 2.49 | 0.01 | + * NonVectorByVal | 32 | 58.7529 ns | 0.2545 ns | 2.48 | 0.02 | + * + * !!! Conclusion !!! + * We do not need by-ref version of ConvertFromVector4() stuff + */ +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertToRgba32.cs similarity index 86% rename from tests/ImageSharp.Benchmarks/General/PixelConversion.cs rename to tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertToRgba32.cs index 77e728280..0c9a8af3f 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertToRgba32.cs @@ -1,4 +1,5 @@ -namespace ImageSharp.Benchmarks.General +// ReSharper disable InconsistentNaming +namespace ImageSharp.Benchmarks.General { using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -12,7 +13,7 @@ /// 2. void CopyToRgba32(ref Rgba32 dest); /// ? /// - public class PixelConversion + public class PixelConversion_ConvertToRgba32 { interface ITestPixel where T : struct, ITestPixel @@ -103,7 +104,7 @@ } } - private ConversionRunner inOrderRunner; + private ConversionRunner compatibleMemoryLayoutRunner; private ConversionRunner permutedRunner; @@ -113,20 +114,20 @@ [Setup] public void Setup() { - this.inOrderRunner = new ConversionRunner(this.Count); + this.compatibleMemoryLayoutRunner = new ConversionRunner(this.Count); this.permutedRunner = new ConversionRunner(this.Count); } [Benchmark(Baseline = true)] - public void InOrderRetval() + public void CompatibleRetval() { - this.inOrderRunner.RunRetvalConversion(); + this.compatibleMemoryLayoutRunner.RunRetvalConversion(); } [Benchmark] - public void InOrderCopyTo() + public void CompatibleCopyTo() { - this.inOrderRunner.RunCopyToConversion(); + this.compatibleMemoryLayoutRunner.RunCopyToConversion(); } [Benchmark] @@ -147,10 +148,9 @@ * * Method | Count | Mean | StdDev | Scaled | Scaled-StdDev | * --------------- |------ |------------ |---------- |------- |-------------- | - * InOrderRetval | 128 | 89.7358 ns | 2.2389 ns | 1.00 | 0.00 | - * InOrderCopyTo | 128 | 89.4112 ns | 2.2901 ns | 1.00 | 0.03 | + * CompatibleRetval | 128 | 89.7358 ns | 2.2389 ns | 1.00 | 0.00 | + * CompatibleCopyTo | 128 | 89.4112 ns | 2.2901 ns | 1.00 | 0.03 | * PermutedRetval | 128 | 845.4038 ns | 5.6154 ns | 9.43 | 0.23 | * PermutedCopyTo | 128 | 155.6004 ns | 3.8870 ns | 1.73 | 0.06 | - * */ } \ No newline at end of file From 4a9c8c80d79855d67ba7ac1e9449f93447c462cb Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 4 Jun 2017 04:22:50 +0200 Subject: [PATCH 07/16] almost done --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 29 ++++-- src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 6 +- .../Components/Decoder/YCbCrToRgbTables.cs | 2 +- .../Formats/Jpeg/JpegDecoderCore.cs | 70 ++++++------- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 71 +++++++------ src/ImageSharp/ImageSharp.csproj | 11 +++ src/ImageSharp/PixelFormats/Alpha8.cs | 4 +- src/ImageSharp/PixelFormats/Argb32.cs | 4 +- src/ImageSharp/PixelFormats/Bgr24.cs | 8 +- src/ImageSharp/PixelFormats/Bgr565.cs | 4 +- src/ImageSharp/PixelFormats/Bgra32.cs | 9 +- src/ImageSharp/PixelFormats/Bgra4444.cs | 4 +- src/ImageSharp/PixelFormats/Bgra5551.cs | 4 +- src/ImageSharp/PixelFormats/Byte4.cs | 4 +- .../PixelFormats/ColorBuilder{TPixel}.cs | 14 +-- src/ImageSharp/PixelFormats/HalfSingle.cs | 4 +- src/ImageSharp/PixelFormats/HalfVector2.cs | 4 +- src/ImageSharp/PixelFormats/HalfVector4.cs | 4 +- src/ImageSharp/PixelFormats/IPixel.cs | 9 +- .../PixelFormats/NormalizedByte2.cs | 4 +- .../PixelFormats/NormalizedByte4.cs | 4 +- .../PixelFormats/NormalizedShort2.cs | 4 +- .../PixelFormats/NormalizedShort4.cs | 4 +- .../PixelFormats/PixelConversionExtensions.cs | 2 +- .../PixelFormats/PixelOperations{TPixel}.cs | 99 ++++++++++--------- src/ImageSharp/PixelFormats/Rg32.cs | 4 +- src/ImageSharp/PixelFormats/Rgb24.cs | 20 +++- src/ImageSharp/PixelFormats/Rgba1010102.cs | 4 +- src/ImageSharp/PixelFormats/Rgba32.cs | 55 ++++++++++- src/ImageSharp/PixelFormats/Rgba64.cs | 4 +- src/ImageSharp/PixelFormats/RgbaVector.cs | 4 +- src/ImageSharp/PixelFormats/Short2.cs | 4 +- src/ImageSharp/PixelFormats/Short4.cs | 4 +- .../Quantizers/OctreeQuantizer{TPixel}.cs | 2 +- .../Quantizers/PaletteQuantizer{TPixel}.cs | 14 +-- src/Shared/stylecop.json | 8 +- .../Color/Bulk/PackFromXyzw.cs | 2 +- .../ImageSharp.Sandbox46.csproj | 2 +- tests/ImageSharp.Sandbox46/Program.cs | 1 + .../Formats/Jpg/YCbCrImageTests.cs | 4 +- .../ImageSharp.Tests/ImageSharp.Tests.csproj | 2 +- .../PixelFormats/PackedPixelTests.cs | 20 ++-- .../PixelFormats/PixelOperationsTests.cs | 8 +- .../ImageProviders/SolidProvider.cs | 4 +- 44 files changed, 322 insertions(+), 226 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index dd91aa11d..23eaa502c 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -6,7 +6,8 @@ namespace ImageSharp.Formats { using System; using System.IO; - + using System.Runtime.CompilerServices; + using ImageSharp.Memory; using ImageSharp.PixelFormats; /// @@ -243,13 +244,20 @@ namespace ImageSharp.Formats byte[] row = new byte[arrayWidth + padding]; TPixel color = default(TPixel); + Rgba32 rgba = default(Rgba32); + for (int y = 0; y < height; y++) { int newY = Invert(y, height, inverted); + // TODO: Could use PixelOperations here! + this.currentStream.Read(row, 0, row.Length); int offset = 0; + + Span pixelRow = pixels.GetRowSpan(y); + for (int x = 0; x < arrayWidth; x++) { int colOffset = x * ppb; @@ -260,8 +268,9 @@ namespace ImageSharp.Formats int newX = colOffset + shift; // Stored in b-> g-> r order. - color.PackFromBytes(colors[colorIndex + 2], colors[colorIndex + 1], colors[colorIndex], 255); - pixels[newX, newY] = color; + rgba.Bgr = Unsafe.As(ref colors[colorIndex]); + color.PackFromRgba32(rgba); + pixelRow[newX] = color; } offset++; @@ -286,6 +295,8 @@ namespace ImageSharp.Formats const int ComponentCount = 2; TPixel color = default(TPixel); + Rgba32 rgba = new Rgba32(0, 0, 0, 255); + using (PixelArea row = new PixelArea(width, ComponentOrder.Xyz)) { for (int y = 0; y < height; y++) @@ -294,17 +305,19 @@ namespace ImageSharp.Formats int newY = Invert(y, height, inverted); + Span pixelRow = pixels.GetRowSpan(newY); + int offset = 0; for (int x = 0; x < width; x++) { short temp = BitConverter.ToInt16(row.Bytes, offset); - byte r = (byte)(((temp & Rgb16RMask) >> 11) * ScaleR); - byte g = (byte)(((temp & Rgb16GMask) >> 5) * ScaleG); - byte b = (byte)((temp & Rgb16BMask) * ScaleR); + rgba.R = (byte)(((temp & Rgb16RMask) >> 11) * ScaleR); + rgba.G = (byte)(((temp & Rgb16GMask) >> 5) * ScaleG); + rgba.B = (byte)((temp & Rgb16BMask) * ScaleR); - color.PackFromBytes(r, g, b, 255); - pixels[x, newY] = color; + color.PackFromRgba32(rgba); + pixelRow[x] = color; offset += ComponentCount; } } diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 618d268f7..7092d2dd0 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -435,6 +435,8 @@ namespace ImageSharp.Formats Span rowSpan = image.GetRowSpan(writeY); + Rgba32 rgba = new Rgba32(0, 0, 0, 255); + for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++) { int index = indices[i]; @@ -446,7 +448,9 @@ namespace ImageSharp.Formats int indexOffset = index * 3; ref TPixel pixel = ref rowSpan[x]; - pixel.PackFromBytes(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2], 255); + rgba.Rgb = Rgb24.AsRgb24(colorTable, indexOffset); + + pixel.PackFromRgba32(rgba); } i++; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/YCbCrToRgbTables.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/YCbCrToRgbTables.cs index 27324b5f6..5c9e8f9fc 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/YCbCrToRgbTables.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/YCbCrToRgbTables.cs @@ -91,7 +91,7 @@ namespace ImageSharp.Formats.Jpg // float b = MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero); byte b = (byte)(y + tables->CbBTable[cb]).Clamp(0, 255); - packed.PackFromBytes(r, g, b, byte.MaxValue); + packed.PackFromRgba32(new Rgba32(r, g, b, 255)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index d65c095da..971684371 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -613,25 +613,23 @@ namespace ImageSharp.Formats private void ConvertFromGrayScale(Image image) where TPixel : struct, IPixel { - using (PixelAccessor pixels = image.Lock()) - { - Parallel.For( - 0, - image.Height, - image.Configuration.ParallelOptions, - y => + Parallel.For( + 0, + image.Height, + image.Configuration.ParallelOptions, + y => { + ref TPixel pixelRowBaseRef = ref image.GetPixelReference(0, y); + int yoff = this.grayImage.GetRowOffset(y); + for (int x = 0; x < image.Width; x++) { byte rgb = this.grayImage.Pixels[yoff + x]; - - TPixel packed = default(TPixel); - packed.PackFromBytes(rgb, rgb, rgb, 255); - pixels[x, y] = packed; + ref TPixel pixel = ref Unsafe.Add(ref pixelRowBaseRef, x); + pixel.PackFromRgba32(new Rgba32(rgb, rgb, rgb, 255)); } }); - } this.AssignResolution(image); } @@ -646,30 +644,29 @@ namespace ImageSharp.Formats { int scale = this.ComponentArray[0].HorizontalFactor / this.ComponentArray[1].HorizontalFactor; - using (PixelAccessor pixels = image.Lock()) - { - Parallel.For( - 0, - image.Height, - image.Configuration.ParallelOptions, - y => + Parallel.For( + 0, + image.Height, + image.Configuration.ParallelOptions, + y => { // TODO: Simplify + optimize + share duplicate code across converter methods int yo = this.ycbcrImage.GetRowYOffset(y); int co = this.ycbcrImage.GetRowCOffset(y); + ref TPixel pixelRowBaseRef = ref image.GetPixelReference(0, y); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); for (int x = 0; x < image.Width; x++) { - byte red = this.ycbcrImage.YChannel[yo + x]; - byte green = this.ycbcrImage.CbChannel[co + (x / scale)]; - byte blue = this.ycbcrImage.CrChannel[co + (x / scale)]; + rgba.R = this.ycbcrImage.YChannel[yo + x]; + rgba.G = this.ycbcrImage.CbChannel[co + (x / scale)]; + rgba.B = this.ycbcrImage.CrChannel[co + (x / scale)]; - TPixel packed = default(TPixel); - packed.PackFromBytes(red, green, blue, 255); - pixels[x, y] = packed; + ref TPixel pixel = ref Unsafe.Add(ref pixelRowBaseRef, x); + pixel.PackFromRgba32(rgba); } }); - } this.AssignResolution(image); } @@ -729,16 +726,15 @@ namespace ImageSharp.Formats { int scale = this.ComponentArray[0].HorizontalFactor / this.ComponentArray[1].HorizontalFactor; - using (PixelAccessor pixels = image.Lock()) - { - Parallel.For( - 0, - image.Height, - y => + Parallel.For( + 0, + image.Height, + y => { // TODO: Simplify + optimize + share duplicate code across converter methods int yo = this.ycbcrImage.GetRowYOffset(y); int co = this.ycbcrImage.GetRowCOffset(y); + ref TPixel pixelRowBaseRef = ref image.GetPixelReference(0, y); for (int x = 0; x < image.Width; x++) { @@ -746,12 +742,10 @@ namespace ImageSharp.Formats byte cb = this.ycbcrImage.CbChannel[co + (x / scale)]; byte cr = this.ycbcrImage.CrChannel[co + (x / scale)]; - TPixel packed = default(TPixel); - this.PackYcck(ref packed, yy, cb, cr, x, y); - pixels[x, y] = packed; + ref TPixel pixel = ref Unsafe.Add(ref pixelRowBaseRef, x); + this.PackYcck(ref pixel, yy, cb, cr, x, y); } }); - } this.AssignResolution(image); } @@ -860,7 +854,7 @@ namespace ImageSharp.Formats byte g = (byte)(((m / 255F) * (1F - keyline)).Clamp(0, 1) * 255); byte b = (byte)(((y / 255F) * (1F - keyline)).Clamp(0, 1) * 255); - packed.PackFromBytes(r, g, b, 255); + packed.PackFromRgba32(new Rgba32(r, g, b)); } /// @@ -904,7 +898,7 @@ namespace ImageSharp.Formats byte g = (byte)(((1 - magenta) * (1 - keyline)).Clamp(0, 1) * 255); byte b = (byte)(((1 - yellow) * (1 - keyline)).Clamp(0, 1) * 255); - packed.PackFromBytes(r, g, b, 255); + packed.PackFromRgba32(new Rgba32(r, g, b)); } /// diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index b18845aaa..12c7bb803 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -574,7 +574,7 @@ namespace ImageSharp.Formats for (int x = 0; x < this.header.Width; x++) { byte intensity = (byte)(newScanline1[x] * factor); - color.PackFromBytes(intensity, intensity, intensity, 255); + color.PackFromRgba32(new Rgba32(intensity, intensity, intensity)); rowSpan[x] = color; } @@ -589,7 +589,7 @@ namespace ImageSharp.Formats byte intensity = defilteredScanline[offset]; byte alpha = defilteredScanline[offset + this.bytesPerSample]; - color.PackFromBytes(intensity, intensity, intensity, alpha); + color.PackFromRgba32(new Rgba32(intensity, intensity, intensity)); rowSpan[x] = color; } @@ -628,6 +628,8 @@ namespace ImageSharp.Formats byte[] palette = this.palette; var color = default(TPixel); + Rgba32 rgba = default(Rgba32); + if (this.paletteAlpha != null && this.paletteAlpha.Length > 0) { // If the alpha palette is not null and has one or more entries, this means, that the image contains an alpha @@ -637,35 +639,33 @@ namespace ImageSharp.Formats int index = newScanline[x + 1]; int pixelOffset = index * 3; - byte a = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255; + rgba.A = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255; - if (a > 0) + if (rgba.A > 0) { - byte r = palette[pixelOffset]; - byte g = palette[pixelOffset + 1]; - byte b = palette[pixelOffset + 2]; - color.PackFromBytes(r, g, b, a); + rgba.Rgb = Rgb24.AsRgb24(palette, pixelOffset); } else { - color.PackFromBytes(0, 0, 0, 0); + rgba = default(Rgba32); } + color.PackFromRgba32(rgba); row[x] = color; } } else { + rgba.A = 255; + for (int x = 0; x < this.header.Width; x++) { int index = newScanline[x + 1]; int pixelOffset = index * 3; - byte r = palette[pixelOffset]; - byte g = palette[pixelOffset + 1]; - byte b = palette[pixelOffset + 2]; + rgba.Rgb = Rgb24.AsRgb24(palette, pixelOffset); - color.PackFromBytes(r, g, b, 255); + color.PackFromRgba32(rgba); row[x] = color; } } @@ -692,7 +692,7 @@ namespace ImageSharp.Formats for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o++) { byte intensity = (byte)(newScanline1[o] * factor); - color.PackFromBytes(intensity, intensity, intensity, 255); + color.PackFromRgba32(new Rgba32(intensity, intensity, intensity)); rowSpan[x] = color; } @@ -704,8 +704,7 @@ namespace ImageSharp.Formats { byte intensity = defilteredScanline[o]; byte alpha = defilteredScanline[o + this.bytesPerSample]; - - color.PackFromBytes(intensity, intensity, intensity, alpha); + color.PackFromRgba32(new Rgba32(intensity, intensity, intensity, alpha)); rowSpan[x] = color; } @@ -714,6 +713,7 @@ namespace ImageSharp.Formats case PngColorType.Palette: byte[] newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth); + Rgba32 rgba = default(Rgba32); if (this.paletteAlpha != null && this.paletteAlpha.Length > 0) { @@ -724,35 +724,33 @@ namespace ImageSharp.Formats int index = newScanline[o]; int offset = index * 3; - byte a = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255; + rgba.A = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255; - if (a > 0) + if (rgba.A > 0) { - byte r = this.palette[offset]; - byte g = this.palette[offset + 1]; - byte b = this.palette[offset + 2]; - color.PackFromBytes(r, g, b, a); + rgba.Rgb = Rgb24.AsRgb24(this.palette, offset); } else { - color.PackFromBytes(0, 0, 0, 0); + rgba = default(Rgba32); } + color.PackFromRgba32(rgba); rowSpan[x] = color; } } else { + rgba.A = 255; + for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o++) { int index = newScanline[o]; int offset = index * 3; - byte r = this.palette[offset]; - byte g = this.palette[offset + 1]; - byte b = this.palette[offset + 2]; + rgba.Rgb = Rgb24.AsRgb24(this.palette, offset); - color.PackFromBytes(r, g, b, 255); + color.PackFromRgba32(rgba); rowSpan[x] = color; } } @@ -761,13 +759,14 @@ namespace ImageSharp.Formats case PngColorType.Rgb: + rgba.A = 255; for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o += this.bytesPerPixel) { - byte r = defilteredScanline[o]; - byte g = defilteredScanline[o + this.bytesPerSample]; - byte b = defilteredScanline[o + (2 * this.bytesPerSample)]; + rgba.R = defilteredScanline[o]; + rgba.G = defilteredScanline[o + this.bytesPerSample]; + rgba.B = defilteredScanline[o + (2 * this.bytesPerSample)]; - color.PackFromBytes(r, g, b, 255); + color.PackFromRgba32(rgba); rowSpan[x] = color; } @@ -777,12 +776,12 @@ namespace ImageSharp.Formats for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o += this.bytesPerPixel) { - byte r = defilteredScanline[o]; - byte g = defilteredScanline[o + this.bytesPerSample]; - byte b = defilteredScanline[o + (2 * this.bytesPerSample)]; - byte a = defilteredScanline[o + (3 * this.bytesPerSample)]; + rgba.R = defilteredScanline[o]; + rgba.G = defilteredScanline[o + this.bytesPerSample]; + rgba.B = defilteredScanline[o + (2 * this.bytesPerSample)]; + rgba.A = defilteredScanline[o + (3 * this.bytesPerSample)]; - color.PackFromBytes(r, g, b, a); + color.PackFromRgba32(rgba); rowSpan[x] = color; } diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 6194be1bf..68a1571a3 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -53,6 +53,17 @@ TextTemplatingFileGenerator + Block8x8F.Generated.cs + + + + + + True + True + Block8x8F.Generated.tt + + \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Alpha8.cs b/src/ImageSharp/PixelFormats/Alpha8.cs index 6a78f15db..59934fdc6 100644 --- a/src/ImageSharp/PixelFormats/Alpha8.cs +++ b/src/ImageSharp/PixelFormats/Alpha8.cs @@ -80,9 +80,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.PackedValue = w; + this.PackedValue = source.A; } /// diff --git a/src/ImageSharp/PixelFormats/Argb32.cs b/src/ImageSharp/PixelFormats/Argb32.cs index 56c33df33..f389723dc 100644 --- a/src/ImageSharp/PixelFormats/Argb32.cs +++ b/src/ImageSharp/PixelFormats/Argb32.cs @@ -248,9 +248,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.PackedValue = Pack(x, y, z, w); + this.PackedValue = Pack(source.R, source.G, source.B, source.A); } /// diff --git a/src/ImageSharp/PixelFormats/Bgr24.cs b/src/ImageSharp/PixelFormats/Bgr24.cs index 7430e37ab..a3b3a907d 100644 --- a/src/ImageSharp/PixelFormats/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/Bgr24.cs @@ -71,7 +71,7 @@ } /// - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { throw new NotImplementedException(); } @@ -95,9 +95,13 @@ } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - throw new NotImplementedException(); + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; + dest.A = 255; } /// diff --git a/src/ImageSharp/PixelFormats/Bgr565.cs b/src/ImageSharp/PixelFormats/Bgr565.cs index 4f6b6aa20..af22b14a0 100644 --- a/src/ImageSharp/PixelFormats/Bgr565.cs +++ b/src/ImageSharp/PixelFormats/Bgr565.cs @@ -103,9 +103,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.PackFromVector4(new Vector4(x, y, z, w) / 255F); + this.PackFromVector4(source.ToVector4()); } /// diff --git a/src/ImageSharp/PixelFormats/Bgra32.cs b/src/ImageSharp/PixelFormats/Bgra32.cs index 3ad6bd336..e07e4c0e3 100644 --- a/src/ImageSharp/PixelFormats/Bgra32.cs +++ b/src/ImageSharp/PixelFormats/Bgra32.cs @@ -128,7 +128,7 @@ } /// - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { throw new NotImplementedException(); } @@ -156,5 +156,12 @@ { throw new NotImplementedException(); } + + /// + /// Converts the pixel to format. + /// + /// The RGBA value + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Rgba32 ToRgba32() => new Rgba32(this.R, this.G, this.B, this.A); } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Bgra4444.cs b/src/ImageSharp/PixelFormats/Bgra4444.cs index 2c60aa900..d10ea58c7 100644 --- a/src/ImageSharp/PixelFormats/Bgra4444.cs +++ b/src/ImageSharp/PixelFormats/Bgra4444.cs @@ -94,9 +94,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.PackFromVector4(new Vector4(x, y, z, w) / 255F); + this.PackFromVector4(source.ToVector4()); } /// diff --git a/src/ImageSharp/PixelFormats/Bgra5551.cs b/src/ImageSharp/PixelFormats/Bgra5551.cs index 9812059a2..198f91108 100644 --- a/src/ImageSharp/PixelFormats/Bgra5551.cs +++ b/src/ImageSharp/PixelFormats/Bgra5551.cs @@ -94,9 +94,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.PackFromVector4(new Vector4(x, y, z, w) / 255F); + this.PackFromVector4(source.ToVector4()); } /// diff --git a/src/ImageSharp/PixelFormats/Byte4.cs b/src/ImageSharp/PixelFormats/Byte4.cs index a5fcfe8bf..14053ba12 100644 --- a/src/ImageSharp/PixelFormats/Byte4.cs +++ b/src/ImageSharp/PixelFormats/Byte4.cs @@ -95,9 +95,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.PackFromVector4(new Vector4(x, y, z, w)); + this.PackFromVector4(source.ToUnscaledVector4()); } /// diff --git a/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs b/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs index 4b21130c0..92fb006ab 100644 --- a/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs @@ -35,12 +35,13 @@ namespace ImageSharp.PixelFormats } TPixel result = default(TPixel); - - result.PackFromBytes( + Rgba32 rgba = new Rgba32( (byte)(packedValue >> 24), (byte)(packedValue >> 16), (byte)(packedValue >> 8), (byte)(packedValue >> 0)); + + result.PackFromRgba32(rgba); return result; } @@ -51,12 +52,7 @@ namespace ImageSharp.PixelFormats /// The green intensity. /// The blue intensity. /// Returns a that represents the color defined by the provided RGB values with 100% opacity. - public static TPixel FromRGB(byte red, byte green, byte blue) - { - TPixel color = default(TPixel); - color.PackFromBytes(red, green, blue, 255); - return color; - } + public static TPixel FromRGB(byte red, byte green, byte blue) => FromRGBA(red, green, blue, 255); /// /// Creates a new representation from standard RGBA bytes. @@ -69,7 +65,7 @@ namespace ImageSharp.PixelFormats public static TPixel FromRGBA(byte red, byte green, byte blue, byte alpha) { TPixel color = default(TPixel); - color.PackFromBytes(red, green, blue, alpha); + color.PackFromRgba32(new Rgba32(red, green, blue, alpha)); return color; } diff --git a/src/ImageSharp/PixelFormats/HalfSingle.cs b/src/ImageSharp/PixelFormats/HalfSingle.cs index 441ee5417..1b564c87c 100644 --- a/src/ImageSharp/PixelFormats/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/HalfSingle.cs @@ -104,9 +104,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.PackFromVector4(new Vector4(x, y, z, w) / MaxBytes); + this.PackFromVector4(source.ToVector4()); } /// diff --git a/src/ImageSharp/PixelFormats/HalfVector2.cs b/src/ImageSharp/PixelFormats/HalfVector2.cs index 373b4f970..237e25981 100644 --- a/src/ImageSharp/PixelFormats/HalfVector2.cs +++ b/src/ImageSharp/PixelFormats/HalfVector2.cs @@ -118,9 +118,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.PackFromVector4(new Vector4(x, y, z, w) / MaxBytes); + this.PackFromVector4(source.ToVector4()); } /// diff --git a/src/ImageSharp/PixelFormats/HalfVector4.cs b/src/ImageSharp/PixelFormats/HalfVector4.cs index cd079146e..062287dbe 100644 --- a/src/ImageSharp/PixelFormats/HalfVector4.cs +++ b/src/ImageSharp/PixelFormats/HalfVector4.cs @@ -111,9 +111,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.PackFromVector4(new Vector4(x, y, z, w) / MaxBytes); + this.PackFromVector4(source.ToVector4()); } /// diff --git a/src/ImageSharp/PixelFormats/IPixel.cs b/src/ImageSharp/PixelFormats/IPixel.cs index cc261e2eb..9090e1210 100644 --- a/src/ImageSharp/PixelFormats/IPixel.cs +++ b/src/ImageSharp/PixelFormats/IPixel.cs @@ -42,13 +42,10 @@ namespace ImageSharp.PixelFormats Vector4 ToVector4(); /// - /// Sets the packed representation from the given byte array. + /// Packs the pixel from an value. /// - /// The x-component. - /// The y-component. - /// The z-component. - /// The w-component. - void PackFromBytes(byte x, byte y, byte z, byte w); + /// The value. + void PackFromRgba32(Rgba32 source); /// /// Converts the pixel to format. diff --git a/src/ImageSharp/PixelFormats/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/NormalizedByte2.cs index 44641710b..387cb6f41 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte2.cs @@ -122,9 +122,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - Vector4 vector = new Vector4(x, y, z, w); + Vector4 vector = source.ToUnscaledVector4(); vector -= Round; vector -= Half; vector -= Round; diff --git a/src/ImageSharp/PixelFormats/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/NormalizedByte4.cs index 86f00ed84..90657c3ac 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte4.cs @@ -115,9 +115,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - Vector4 vector = new Vector4(x, y, z, w); + Vector4 vector = source.ToUnscaledVector4(); vector -= Round; vector -= Half; vector -= Round; diff --git a/src/ImageSharp/PixelFormats/NormalizedShort2.cs b/src/ImageSharp/PixelFormats/NormalizedShort2.cs index fb11c16af..a0615563f 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort2.cs @@ -109,9 +109,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - Vector4 vector = new Vector4(x, y, z, w); + Vector4 vector = source.ToUnscaledVector4(); vector -= Round; vector -= Half; vector -= Round; diff --git a/src/ImageSharp/PixelFormats/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/NormalizedShort4.cs index 0da68b65e..f35fb6368 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort4.cs @@ -117,9 +117,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - Vector4 vector = new Vector4(x, y, z, w); + Vector4 vector = source.ToUnscaledVector4(); vector -= Round; vector -= Half; vector -= Round; diff --git a/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs b/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs index c75719dc6..98a2083a1 100644 --- a/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs +++ b/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs @@ -21,7 +21,7 @@ public static void ToXyzBytes(this TPixel pixel, Span bytes, int startIndex) where TPixel : struct, IPixel { - ref Rgb24 dest = ref Unsafe.As(ref bytes[startIndex]); + ref Rgb24 dest = ref Rgb24.AsRgb24(bytes, startIndex); pixel.ToRgb24(ref dest); } diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 918662144..39c1c0524 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -67,28 +67,31 @@ namespace ImageSharp.PixelFormats } /// - /// Bulk version of that converts data in . + /// Bulk version of that converts data in . /// /// The to the source bytes. /// The to the destination colors. /// The number of pixels to convert. internal virtual void PackFromXyzBytes(Span sourceBytes, Span destColors, int count) { - Guard.MustBeSizedAtLeast(sourceBytes, count * 3, nameof(sourceBytes)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + this.PackFromRgb24(sourceBytes.NonPortableCast(), destColors, count); + } - ref byte sourceRef = ref sourceBytes.DangerousGetPinnableReference(); - ref TPixel destRef = ref destColors.DangerousGetPinnableReference(); + internal virtual void PackFromRgb24(Span source, Span destPixels, int count) + { + Guard.MustBeSizedAtLeast(source, count, nameof(source)); + Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); + + ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); for (int i = 0; i < count; i++) { - int i3 = i * 3; ref TPixel dp = ref Unsafe.Add(ref destRef, i); - dp.PackFromBytes( - Unsafe.Add(ref sourceRef, i3), - Unsafe.Add(ref sourceRef, i3 + 1), - Unsafe.Add(ref sourceRef, i3 + 2), - 255); + rgba.Rgb = Unsafe.Add(ref sourceRef, i); + dp.PackFromRgba32(rgba); } } @@ -113,28 +116,31 @@ namespace ImageSharp.PixelFormats } /// - /// Bulk version of that converts data in . + /// Bulk version of that converts data in . /// /// The to the source bytes. /// The to the destination colors. /// The number of pixels to convert. internal virtual void PackFromXyzwBytes(Span sourceBytes, Span destColors, int count) { - Guard.MustBeSizedAtLeast(sourceBytes, count * 4, nameof(sourceBytes)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + this.PackFromRgba32(sourceBytes.NonPortableCast(), destColors, count); + } - ref byte sourceRef = ref sourceBytes.DangerousGetPinnableReference(); - ref TPixel destRef = ref destColors.DangerousGetPinnableReference(); + internal virtual void PackFromRgba32(Span source, Span destPixels, int count) + { + Guard.MustBeSizedAtLeast(source, count, nameof(source)); + Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); + + ref Rgba32 sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); for (int i = 0; i < count; i++) { - int i4 = i * 4; ref TPixel dp = ref Unsafe.Add(ref destRef, i); - dp.PackFromBytes( - Unsafe.Add(ref sourceRef, i4), - Unsafe.Add(ref sourceRef, i4 + 1), - Unsafe.Add(ref sourceRef, i4 + 2), - Unsafe.Add(ref sourceRef, i4 + 3)); + rgba = Unsafe.Add(ref sourceRef, i); + dp.PackFromRgba32(rgba); } } @@ -159,28 +165,31 @@ namespace ImageSharp.PixelFormats } /// - /// Bulk version of that converts data in . + /// Bulk version of that converts data in . /// /// The to the source bytes. /// The to the destination colors. /// The number of pixels to convert. internal virtual void PackFromZyxBytes(Span sourceBytes, Span destColors, int count) { - Guard.MustBeSizedAtLeast(sourceBytes, count * 3, nameof(sourceBytes)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + this.PackFromBgr24(sourceBytes.NonPortableCast(), destColors, count); + } - ref byte sourceRef = ref sourceBytes.DangerousGetPinnableReference(); - ref TPixel destRef = ref destColors.DangerousGetPinnableReference(); + internal virtual void PackFromBgr24(Span source, Span destPixels, int count) + { + Guard.MustBeSizedAtLeast(source, count, nameof(source)); + Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); + + ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); for (int i = 0; i < count; i++) { - int i3 = i * 3; ref TPixel dp = ref Unsafe.Add(ref destRef, i); - dp.PackFromBytes( - Unsafe.Add(ref sourceRef, i3 + 2), - Unsafe.Add(ref sourceRef, i3 + 1), - Unsafe.Add(ref sourceRef, i3), - 255); + rgba.Bgr = Unsafe.Add(ref sourceRef, i); + dp.PackFromRgba32(rgba); } } @@ -205,28 +214,30 @@ namespace ImageSharp.PixelFormats } /// - /// Bulk version of that converts data in . + /// Bulk version of that converts data in . /// /// The to the source bytes. /// The to the destination colors. /// The number of pixels to convert. internal virtual void PackFromZyxwBytes(Span sourceBytes, Span destColors, int count) { - Guard.MustBeSizedAtLeast(sourceBytes, count * 4, nameof(sourceBytes)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + this.PackFromBgra32(sourceBytes.NonPortableCast(), destColors, count); + } - ref byte sourceRef = ref sourceBytes.DangerousGetPinnableReference(); - ref TPixel destRef = ref destColors.DangerousGetPinnableReference(); + internal virtual void PackFromBgra32(Span source, Span destPixels, int count) + { + Guard.MustBeSizedAtLeast(source, count, nameof(source)); + Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); + + ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + Rgba32 rgba = new Rgba32(0, 0, 0, 255); for (int i = 0; i < count; i++) { - int i4 = i * 4; ref TPixel dp = ref Unsafe.Add(ref destRef, i); - dp.PackFromBytes( - Unsafe.Add(ref sourceRef, i4 + 2), - Unsafe.Add(ref sourceRef, i4 + 1), - Unsafe.Add(ref sourceRef, i4), - Unsafe.Add(ref sourceRef, i4 + 3)); + rgba = Unsafe.Add(ref sourceRef, i).ToRgba32(); + dp.PackFromRgba32(rgba); } } diff --git a/src/ImageSharp/PixelFormats/Rg32.cs b/src/ImageSharp/PixelFormats/Rg32.cs index 86b516ede..0575689a7 100644 --- a/src/ImageSharp/PixelFormats/Rg32.cs +++ b/src/ImageSharp/PixelFormats/Rg32.cs @@ -107,9 +107,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.PackFromVector4(new Vector4(x, y, z, w) / 255F); + this.PackFromVector4(source.ToVector4()); } /// diff --git a/src/ImageSharp/PixelFormats/Rgb24.cs b/src/ImageSharp/PixelFormats/Rgb24.cs index 196c02d7c..1c91635dc 100644 --- a/src/ImageSharp/PixelFormats/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/Rgb24.cs @@ -71,7 +71,7 @@ namespace ImageSharp.PixelFormats } /// - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { throw new NotImplementedException(); } @@ -111,5 +111,23 @@ namespace ImageSharp.PixelFormats { throw new NotImplementedException(); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref Rgb24 AsRgb24(byte[] bytes, int offset) + { + return ref Unsafe.As(ref bytes[offset]); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static ref Rgb24 AsRgb24(ref byte baseRef, int offset) + { + return ref Unsafe.As(ref Unsafe.Add(ref baseRef, offset)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref Rgb24 AsRgb24(Span bytes, int offset) + { + return ref Unsafe.As(ref bytes[offset]); + } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Rgba1010102.cs b/src/ImageSharp/PixelFormats/Rgba1010102.cs index 935f69795..e682aa477 100644 --- a/src/ImageSharp/PixelFormats/Rgba1010102.cs +++ b/src/ImageSharp/PixelFormats/Rgba1010102.cs @@ -101,9 +101,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.PackFromVector4(new Vector4(x, y, z, w) / 255F); + this.PackFromVector4(source.ToVector4()); } /// diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs index 840018792..240a1a296 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.cs @@ -178,6 +178,44 @@ namespace ImageSharp } } + /// + /// Gets or sets the RGB components of this struct as + /// + public Rgb24 Rgb + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return Unsafe.As(ref this); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + Unsafe.As(ref this) = value; + } + } + + /// + /// Gets or sets the RGB components of this struct as reverting the component order. + /// + public Bgr24 Bgr + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return new Bgr24(this.R, this.G, this.B); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { + this.R = value.R; + this.G = value.G; + this.B = value.B; + } + } + /// public uint PackedValue { @@ -237,12 +275,9 @@ namespace ImageSharp /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.R = x; - this.G = y; - this.B = z; - this.A = w; + this = source; } /// @@ -337,6 +372,16 @@ namespace ImageSharp } } + /// + /// Gets the representation without normalizing to [0, 1] + /// + /// A of values in [0, 255] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal Vector4 ToUnscaledVector4() + { + return new Vector4(this.R, this.G, this.B, this.A); + } + /// /// Packs the four floats into a . /// diff --git a/src/ImageSharp/PixelFormats/Rgba64.cs b/src/ImageSharp/PixelFormats/Rgba64.cs index 92a839ddf..bdcf13763 100644 --- a/src/ImageSharp/PixelFormats/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/Rgba64.cs @@ -100,9 +100,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.PackFromVector4(new Vector4(x, y, z, w) / 255F); + this.PackFromVector4(source.ToVector4()); } /// diff --git a/src/ImageSharp/PixelFormats/RgbaVector.cs b/src/ImageSharp/PixelFormats/RgbaVector.cs index f3498705d..c6eed1122 100644 --- a/src/ImageSharp/PixelFormats/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/RgbaVector.cs @@ -215,9 +215,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - this.backingVector = new Vector4(x, y, z, w) / MaxBytes; + this.backingVector = source.ToVector4(); } /// diff --git a/src/ImageSharp/PixelFormats/Short2.cs b/src/ImageSharp/PixelFormats/Short2.cs index d369a6aae..0b3f4be93 100644 --- a/src/ImageSharp/PixelFormats/Short2.cs +++ b/src/ImageSharp/PixelFormats/Short2.cs @@ -109,9 +109,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - Vector2 vector = new Vector2(x, y) / 255; + Vector2 vector = new Vector2(source.R, source.G) / 255; vector *= 65534; vector -= new Vector2(32767); this.PackedValue = Pack(vector.X, vector.Y); diff --git a/src/ImageSharp/PixelFormats/Short4.cs b/src/ImageSharp/PixelFormats/Short4.cs index 9f7a5d887..958300929 100644 --- a/src/ImageSharp/PixelFormats/Short4.cs +++ b/src/ImageSharp/PixelFormats/Short4.cs @@ -115,9 +115,9 @@ namespace ImageSharp.PixelFormats /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PackFromBytes(byte x, byte y, byte z, byte w) + public void PackFromRgba32(Rgba32 source) { - Vector4 vector = new Vector4(x, y, z, w) / 255; + Vector4 vector = source.ToVector4(); vector *= 65534; vector -= new Vector4(32767); this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); diff --git a/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs index e19df4cfa..8ebea8533 100644 --- a/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs @@ -499,7 +499,7 @@ namespace ImageSharp.Quantizers // And set the color of the palette entry var pixel = default(TPixel); - pixel.PackFromBytes(r, g, b, 255); + pixel.PackFromRgba32(new Rgba32(r, g, b, 255)); palette[index] = pixel; // Consume the next palette index diff --git a/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs index cf3ff94ee..e9d2841a1 100644 --- a/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs @@ -18,11 +18,6 @@ namespace ImageSharp.Quantizers public sealed class PaletteQuantizer : Quantizer where TPixel : struct, IPixel { - /// - /// The pixel buffer, used to reduce allocations. - /// - private readonly byte[] pixelBuffer = new byte[4]; - /// /// A lookup table for colors /// @@ -48,14 +43,9 @@ namespace ImageSharp.Quantizers Rgba32[] constants = ColorConstants.WebSafeColors; TPixel[] safe = new TPixel[constants.Length + 1]; - for (int i = 0; i < constants.Length; i++) - { - constants[i].ToXyzwBytes(this.pixelBuffer, 0); - var packed = default(TPixel); - packed.PackFromBytes(this.pixelBuffer[0], this.pixelBuffer[1], this.pixelBuffer[2], this.pixelBuffer[3]); - safe[i] = packed; - } + Span constantsBytes = constants.AsSpan().NonPortableCast(); + PixelOperations.Instance.PackFromXyzwBytes(constantsBytes, safe, constants.Length); this.colors = safe; } else diff --git a/src/Shared/stylecop.json b/src/Shared/stylecop.json index df8f120a5..5a95b6c49 100644 --- a/src/Shared/stylecop.json +++ b/src/Shared/stylecop.json @@ -3,7 +3,13 @@ "settings": { "documentationRules": { "companyName": "James Jackson-South", - "copyrightText": "Copyright (c) James Jackson-South and contributors.\nLicensed under the Apache License, Version 2.0." + "copyrightText": "Copyright (c) James Jackson-South and contributors.\nLicensed under the Apache License, Version 2.0.", + "documentInterfaces": false, + + "documentInternalElements": false, + "documentExposedElements": false, + "documentPrivateElements": false, + "documentPrivateFields": false } } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs index 501ae7949..807df50e8 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs @@ -40,7 +40,7 @@ namespace ImageSharp.Benchmarks.Color.Bulk { int i4 = i * 4; TPixel c = default(TPixel); - c.PackFromBytes(s[i4], s[i4 + 1], s[i4 + 2], s[i4 + 3]); + c.PackFromRgba32(new Rgba32(s[i4], s[i4 + 1], s[i4 + 2], s[i4 + 3])); d[i] = c; } } diff --git a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj index 53cdffaea..ae17f3698 100644 --- a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj +++ b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj @@ -17,8 +17,8 @@ - + diff --git a/tests/ImageSharp.Sandbox46/Program.cs b/tests/ImageSharp.Sandbox46/Program.cs index b882de0cc..6f93df16e 100644 --- a/tests/ImageSharp.Sandbox46/Program.cs +++ b/tests/ImageSharp.Sandbox46/Program.cs @@ -10,6 +10,7 @@ namespace ImageSharp.Sandbox46 using ImageSharp.Tests; using ImageSharp.Tests.Colors; + using ImageSharp.Tests.PixelFormats; using ImageSharp.Tests.Processing.Transforms; using Xunit.Abstractions; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/YCbCrImageTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/YCbCrImageTests.cs index ba55665ca..f207dc1d1 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/YCbCrImageTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/YCbCrImageTests.cs @@ -31,7 +31,7 @@ namespace ImageSharp.Tests [InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio422, 2, 1)] [InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio440, 1, 2)] [InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio444, 1, 1)] - public void CalculateChrominanceSize(int ratioValue, int expectedDivX, int expectedDivY) + internal void CalculateChrominanceSize(YCbCrImage.YCbCrSubsampleRatio ratioValue, int expectedDivX, int expectedDivY) { YCbCrImage.YCbCrSubsampleRatio ratio = (YCbCrImage.YCbCrSubsampleRatio)ratioValue; @@ -49,7 +49,7 @@ namespace ImageSharp.Tests [InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio422, 2)] [InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio440, 1)] [InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio444, 1)] - public void Create(int ratioValue, int expectedCStrideDiv) + internal void Create(YCbCrImage.YCbCrSubsampleRatio ratioValue, int expectedCStrideDiv) { YCbCrImage.YCbCrSubsampleRatio ratio = (YCbCrImage.YCbCrSubsampleRatio)ratioValue; diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index afde531b4..9f3beb9e8 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -11,8 +11,8 @@ - + diff --git a/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs b/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs index 5ec7c21bb..dad426c40 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs @@ -302,7 +302,7 @@ namespace ImageSharp.Tests.Colors Assert.Equal(bgra, new byte[] { 0, 0, 128, 0 }); Byte4 r = new Byte4(); - r.PackFromBytes(20, 38, 0, 255); + r.PackFromRgba32(new Rgba32(20, 38, 0, 255)); r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 }); } @@ -448,7 +448,7 @@ namespace ImageSharp.Tests.Colors float y = -0.3f; Assert.Equal(0xda0d, new NormalizedByte2(x, y).PackedValue); NormalizedByte2 n = new NormalizedByte2(); - n.PackFromBytes(141, 90, 0, 0); + n.PackFromRgba32(new Rgba32(141, 90, 0, 0)); Assert.Equal(0xda0d, n.PackedValue); byte[] rgb = new byte[3]; @@ -491,7 +491,7 @@ namespace ImageSharp.Tests.Colors float w = -0.7f; Assert.Equal(0xA740DA0D, new NormalizedByte4(x, y, z, w).PackedValue); NormalizedByte4 n = new NormalizedByte4(); - n.PackFromBytes(141, 90, 192, 39); + n.PackFromRgba32(new Rgba32(141, 90, 192, 39)); Assert.Equal(0xA740DA0D, n.PackedValue); Assert.Equal((uint)958796544, new NormalizedByte4(0.0008f, 0.15f, 0.30f, 0.45f).PackedValue); @@ -515,7 +515,7 @@ namespace ImageSharp.Tests.Colors // http://community.monogame.net/t/normalizedbyte4-texture2d-gives-different-results-from-xna/8012/8 NormalizedByte4 r = new NormalizedByte4(); - r.PackFromBytes(9, 115, 202, 127); + r.PackFromRgba32(new Rgba32(9, 115, 202, 127)); r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 }); @@ -554,7 +554,7 @@ namespace ImageSharp.Tests.Colors byte[] bgra = new byte[4]; NormalizedShort2 n = new NormalizedShort2(); - n.PackFromBytes(141, 90, 0, 0); + n.PackFromRgba32(new Rgba32(141, 90, 0, 0)); n.ToXyzBytes(rgb, 0); Assert.Equal(rgb, new byte[] { 141, 90, 0 }); @@ -615,7 +615,7 @@ namespace ImageSharp.Tests.Colors Assert.Equal(bgra, new byte[] { 192, 90, 141, 39 }); NormalizedShort4 r = new NormalizedShort4(); - r.PackFromBytes(9, 115, 202, 127); + r.PackFromRgba32(new Rgba32(9, 115, 202, 127)); r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 }); } @@ -708,7 +708,7 @@ namespace ImageSharp.Tests.Colors // Alpha component accuracy will be awful. Rgba1010102 r = new Rgba1010102(); - r.PackFromBytes(25, 0, 128, 0); + r.PackFromRgba32(new Rgba32(25, 0, 128, 0)); r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 25, 0, 128, 0 }); } @@ -801,7 +801,7 @@ namespace ImageSharp.Tests.Colors Assert.Equal(bgra, new byte[] { 76, 38, 20, 115 }); Rgba64 r = new Rgba64(); - r.PackFromBytes(20, 38, 76, 115); + r.PackFromRgba32(new Rgba32(20, 38, 76, 115)); r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 20, 38, 76, 115 }); } @@ -856,7 +856,7 @@ namespace ImageSharp.Tests.Colors Assert.Equal(bgra, new byte[] { 0, 127, 128, 255 }); Short2 r = new Short2(); - r.PackFromBytes(20, 38, 0, 255); + r.PackFromRgba32(new Rgba32(20, 38, 0, 255)); r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 }); } @@ -913,7 +913,7 @@ namespace ImageSharp.Tests.Colors Assert.Equal(bgra, new byte[] { 243, 177, 172, 128 }); Short4 r = new Short4(); - r.PackFromBytes(20, 38, 0, 255); + r.PackFromRgba32(new Rgba32(20, 38, 0, 255)); r.ToXyzwBytes(rgba, 0); Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 }); } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs index f387178e5..fa7d9d247 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs @@ -156,7 +156,7 @@ namespace ImageSharp.Tests.PixelFormats { int i3 = i * 3; - expected[i].PackFromBytes(source[i3 + 0], source[i3 + 1], source[i3 + 2], 255); + expected[i].PackFromRgba32(new Rgba32(source[i3 + 0], source[i3 + 1], source[i3 + 2], 255)); } TestOperation( @@ -197,7 +197,7 @@ namespace ImageSharp.Tests.PixelFormats { int i4 = i * 4; - expected[i].PackFromBytes(source[i4 + 0], source[i4 + 1], source[i4 + 2], source[i4 + 3]); + expected[i].PackFromRgba32(new Rgba32(source[i4 + 0], source[i4 + 1], source[i4 + 2], source[i4 + 3])); } TestOperation( @@ -238,7 +238,7 @@ namespace ImageSharp.Tests.PixelFormats { int i3 = i * 3; - expected[i].PackFromBytes(source[i3 + 2], source[i3 + 1], source[i3 + 0], 255); + expected[i].PackFromRgba32(new Rgba32(source[i3 + 2], source[i3 + 1], source[i3 + 0], 255)); } TestOperation( @@ -279,7 +279,7 @@ namespace ImageSharp.Tests.PixelFormats { int i4 = i * 4; - expected[i].PackFromBytes(source[i4 + 2], source[i4 + 1], source[i4 + 0], source[i4 + 3]); + expected[i].PackFromRgba32(new Rgba32(source[i4 + 2], source[i4 + 1], source[i4 + 0], source[i4 + 3])); } TestOperation( diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs index 65d55da55..0caded420 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs @@ -53,11 +53,11 @@ namespace ImageSharp.Tests { Image image = base.GetImage(); TPixel color = default(TPixel); - color.PackFromBytes(this.r, this.g, this.b, this.a); + color.PackFromRgba32(new Rgba32(this.r, this.g, this.b, this.a)); return image.Fill(color); } - + public override void Serialize(IXunitSerializationInfo info) { info.AddValue("red", this.r); From 9551118b279ab5967dcf1b449fd974c92f58d848 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 4 Jun 2017 04:29:42 +0200 Subject: [PATCH 08/16] fixed broken rounding --- src/ImageSharp/PixelFormats/HalfSingle.cs | 28 +++++++++++----------- src/ImageSharp/PixelFormats/HalfVector2.cs | 16 ++++++------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/ImageSharp/PixelFormats/HalfSingle.cs b/src/ImageSharp/PixelFormats/HalfSingle.cs index 1b564c87c..3bdfc9f1c 100644 --- a/src/ImageSharp/PixelFormats/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/HalfSingle.cs @@ -114,9 +114,9 @@ namespace ImageSharp.PixelFormats public void ToRgb24(ref Rgb24 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); - dest.B = (byte)MathF.Round(vector.Z); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// @@ -124,10 +124,10 @@ namespace ImageSharp.PixelFormats public void ToRgba32(ref Rgba32 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); - dest.B = (byte)MathF.Round(vector.Z); - dest.A = (byte)MathF.Round(vector.W); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// @@ -135,9 +135,9 @@ namespace ImageSharp.PixelFormats public void ToBgr24(ref Bgr24 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); - dest.B = (byte)MathF.Round(vector.Z); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// @@ -145,10 +145,10 @@ namespace ImageSharp.PixelFormats public void ToBgra32(ref Bgra32 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); - dest.B = (byte)MathF.Round(vector.Z); - dest.A = (byte)MathF.Round(vector.W); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// diff --git a/src/ImageSharp/PixelFormats/HalfVector2.cs b/src/ImageSharp/PixelFormats/HalfVector2.cs index 237e25981..7f1fe4ebd 100644 --- a/src/ImageSharp/PixelFormats/HalfVector2.cs +++ b/src/ImageSharp/PixelFormats/HalfVector2.cs @@ -128,8 +128,8 @@ namespace ImageSharp.PixelFormats public void ToRgb24(ref Rgb24 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; dest.B = 0; } @@ -138,8 +138,8 @@ namespace ImageSharp.PixelFormats public void ToRgba32(ref Rgba32 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; dest.B = 0; dest.A = 255; } @@ -149,8 +149,8 @@ namespace ImageSharp.PixelFormats public void ToBgr24(ref Bgr24 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; dest.B = 0; } @@ -159,8 +159,8 @@ namespace ImageSharp.PixelFormats public void ToBgra32(ref Bgra32 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; dest.B = 0; dest.A = 255; } From e27c4ca946d4b8f58d922461e8e17d86043f9866 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 4 Jun 2017 15:06:13 +0200 Subject: [PATCH 09/16] document and refactor GetRgb24() --- .../Common/Extensions/ByteExtensions.cs | 45 ++++++++++++++++++- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 6 +-- src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 2 +- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 8 ++-- .../PixelFormats/PixelConversionExtensions.cs | 2 +- src/ImageSharp/PixelFormats/Rgb24.cs | 18 -------- 6 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/ImageSharp/Common/Extensions/ByteExtensions.cs b/src/ImageSharp/Common/Extensions/ByteExtensions.cs index a6dc19ded..f1161eb6f 100644 --- a/src/ImageSharp/Common/Extensions/ByteExtensions.cs +++ b/src/ImageSharp/Common/Extensions/ByteExtensions.cs @@ -5,10 +5,13 @@ namespace ImageSharp { + using System; using System.Runtime.CompilerServices; + using ImageSharp.PixelFormats; + /// - /// Extension methods for the struct. + /// Extension methods for the struct buffers. /// internal static class ByteExtensions { @@ -44,5 +47,45 @@ namespace ImageSharp j--; } } + + /// + /// Returns a reference to the given position of the array unsafe casted to . + /// + /// The byte array. + /// The offset in bytes. + /// The reference at the given offset. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref Rgb24 GetRgb24(this byte[] bytes, int offset) + { + DebugGuard.MustBeLessThan(offset + 2, bytes.Length, nameof(offset)); + + return ref Unsafe.As(ref bytes[offset]); + } + + /// + /// Returns a reference to the given position of the span unsafe casted to . + /// + /// The byte span. + /// The offset in bytes. + /// The reference at the given offset. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref Rgb24 GetRgb24(this Span bytes, int offset) + { + DebugGuard.MustBeLessThan(offset + 2, bytes.Length, nameof(offset)); + + return ref Unsafe.As(ref bytes[offset]); + } + + /// + /// Returns a reference to the given position of the buffer pointed by `baseRef` unsafe casted to . + /// + /// A reference to the beginning of the buffer + /// The offset in bytes. + /// The reference at the given offset. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref Rgb24 GetRgb24(ref byte baseRef, int offset) + { + return ref Unsafe.As(ref Unsafe.Add(ref baseRef, offset)); + } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 23eaa502c..997a77d6c 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -249,15 +249,11 @@ namespace ImageSharp.Formats for (int y = 0; y < height; y++) { int newY = Invert(y, height, inverted); - - // TODO: Could use PixelOperations here! - this.currentStream.Read(row, 0, row.Length); - int offset = 0; - Span pixelRow = pixels.GetRowSpan(y); + // TODO: Could use PixelOperations here! for (int x = 0; x < arrayWidth; x++) { int colOffset = x * ppb; diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 7092d2dd0..5b56c4c02 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -448,7 +448,7 @@ namespace ImageSharp.Formats int indexOffset = index * 3; ref TPixel pixel = ref rowSpan[x]; - rgba.Rgb = Rgb24.AsRgb24(colorTable, indexOffset); + rgba.Rgb = colorTable.GetRgb24(indexOffset); pixel.PackFromRgba32(rgba); } diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 12c7bb803..d2b68978f 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -643,7 +643,7 @@ namespace ImageSharp.Formats if (rgba.A > 0) { - rgba.Rgb = Rgb24.AsRgb24(palette, pixelOffset); + rgba.Rgb = palette.GetRgb24(pixelOffset); } else { @@ -663,7 +663,7 @@ namespace ImageSharp.Formats int index = newScanline[x + 1]; int pixelOffset = index * 3; - rgba.Rgb = Rgb24.AsRgb24(palette, pixelOffset); + rgba.Rgb = palette.GetRgb24(pixelOffset); color.PackFromRgba32(rgba); row[x] = color; @@ -728,7 +728,7 @@ namespace ImageSharp.Formats if (rgba.A > 0) { - rgba.Rgb = Rgb24.AsRgb24(this.palette, offset); + rgba.Rgb = this.palette.GetRgb24(offset); } else { @@ -748,7 +748,7 @@ namespace ImageSharp.Formats int index = newScanline[o]; int offset = index * 3; - rgba.Rgb = Rgb24.AsRgb24(this.palette, offset); + rgba.Rgb = this.palette.GetRgb24(offset); color.PackFromRgba32(rgba); rowSpan[x] = color; diff --git a/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs b/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs index 98a2083a1..1ea262895 100644 --- a/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs +++ b/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs @@ -21,7 +21,7 @@ public static void ToXyzBytes(this TPixel pixel, Span bytes, int startIndex) where TPixel : struct, IPixel { - ref Rgb24 dest = ref Rgb24.AsRgb24(bytes, startIndex); + ref Rgb24 dest = ref bytes.GetRgb24(startIndex); pixel.ToRgb24(ref dest); } diff --git a/src/ImageSharp/PixelFormats/Rgb24.cs b/src/ImageSharp/PixelFormats/Rgb24.cs index 1c91635dc..13dcaff95 100644 --- a/src/ImageSharp/PixelFormats/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/Rgb24.cs @@ -111,23 +111,5 @@ namespace ImageSharp.PixelFormats { throw new NotImplementedException(); } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ref Rgb24 AsRgb24(byte[] bytes, int offset) - { - return ref Unsafe.As(ref bytes[offset]); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ref Rgb24 AsRgb24(ref byte baseRef, int offset) - { - return ref Unsafe.As(ref Unsafe.Add(ref baseRef, offset)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ref Rgb24 AsRgb24(Span bytes, int offset) - { - return ref Unsafe.As(ref bytes[offset]); - } } } \ No newline at end of file From abd4c19bed4dfbc51fc4e6a3ec7481f23b8c8daf Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 4 Jun 2017 15:52:24 +0200 Subject: [PATCH 10/16] test clenup (xUnit analyzer warnings mostly) --- tests/ImageSharp.Tests/Common/BufferTests.cs | 2 +- .../ImageSharp.Tests/Common/ConstantsTests.cs | 2 +- .../Drawing/Text/TextGraphicsOptionsTests.cs | 4 +- .../Formats/Jpg/JpegProfilingBenchmarks.cs | 10 ++-- .../Formats/Jpg/YCbCrImageTests.cs | 18 ++++--- .../IO/BigEndianBitConverter.ToTypeTests.cs | 12 ++--- .../LittleEndianBitConverter.ToTypeTests.cs | 8 +-- .../MetaData/ImagePropertyTests.cs | 6 +-- .../MetaData/Profiles/Exif/ExifValueTests.cs | 2 +- .../Numerics/RectangleFTests.cs | 1 + .../PixelFormats/Bgr24Tests.cs | 51 +++++++++---------- .../PixelFormats/Bgra32Tests.cs | 46 ++++++++--------- .../PixelFormats/PackedPixelTests.cs | 8 +-- .../PixelFormats/PixelOperationsTests.cs | 3 ++ .../Processing/Transforms/PadTest.cs | 2 +- .../Transforms/ResizeProfilingBenchmarks.cs | 4 +- .../Tests/TestImageProviderTests.cs | 14 ++--- .../Tests/TestUtilityExtensionsTests.cs | 2 +- 18 files changed, 97 insertions(+), 98 deletions(-) diff --git a/tests/ImageSharp.Tests/Common/BufferTests.cs b/tests/ImageSharp.Tests/Common/BufferTests.cs index 010bf40b3..25ef173d4 100644 --- a/tests/ImageSharp.Tests/Common/BufferTests.cs +++ b/tests/ImageSharp.Tests/Common/BufferTests.cs @@ -163,7 +163,7 @@ namespace ImageSharp.Tests.Common // Assert.Equal(buffer.Array, span.ToArray()); // Assert.Equal(0, span.Start); Assert.SpanPointsTo(span, buffer); - Assert.Equal(span.Length, 42); + Assert.Equal(42, span.Length); } } diff --git a/tests/ImageSharp.Tests/Common/ConstantsTests.cs b/tests/ImageSharp.Tests/Common/ConstantsTests.cs index 0adda0c0f..be4addf91 100644 --- a/tests/ImageSharp.Tests/Common/ConstantsTests.cs +++ b/tests/ImageSharp.Tests/Common/ConstantsTests.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Common [Fact] public void Epsilon() { - Assert.Equal(Constants.Epsilon, 0.001f); + Assert.Equal(0.001f, Constants.Epsilon); } } } diff --git a/tests/ImageSharp.Tests/Drawing/Text/TextGraphicsOptionsTests.cs b/tests/ImageSharp.Tests/Drawing/Text/TextGraphicsOptionsTests.cs index a291a7d18..1a26bcfed 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/TextGraphicsOptionsTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/TextGraphicsOptionsTests.cs @@ -22,7 +22,7 @@ namespace ImageSharp.Tests.Drawing.Text TextGraphicsOptions textOptions = opt; - Assert.Equal(false, textOptions.Antialias); + Assert.False(textOptions.Antialias); Assert.Equal(99, textOptions.AntialiasSubpixelDepth); } @@ -36,7 +36,7 @@ namespace ImageSharp.Tests.Drawing.Text GraphicsOptions opt = (GraphicsOptions)textOptions; - Assert.Equal(false, opt.Antialias); + Assert.False(opt.Antialias); Assert.Equal(99, opt.AntialiasSubpixelDepth); } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs index aac3f4611..f3412e45e 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs @@ -34,7 +34,7 @@ namespace ImageSharp.Tests }; // [Theory] // Benchmark, enable manually - [MemberData(nameof(DecodeJpegData))] + // [MemberData(nameof(DecodeJpegData))] public void DecodeJpeg(string fileName) { const int ExecutionCount = 30; @@ -60,10 +60,10 @@ namespace ImageSharp.Tests // Benchmark, enable manually! // [Theory] - [InlineData(1, 75, JpegSubsample.Ratio420)] - [InlineData(30, 75, JpegSubsample.Ratio420)] - [InlineData(30, 75, JpegSubsample.Ratio444)] - [InlineData(30, 100, JpegSubsample.Ratio444)] + // [InlineData(1, 75, JpegSubsample.Ratio420)] + // [InlineData(30, 75, JpegSubsample.Ratio420)] + // [InlineData(30, 75, JpegSubsample.Ratio444)] + // [InlineData(30, 100, JpegSubsample.Ratio444)] public void EncodeJpeg(int executionCount, int quality, JpegSubsample subsample) { string[] testFiles = TestImages.Bmp.All diff --git a/tests/ImageSharp.Tests/Formats/Jpg/YCbCrImageTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/YCbCrImageTests.cs index f207dc1d1..b7cd281cd 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/YCbCrImageTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/YCbCrImageTests.cs @@ -19,11 +19,6 @@ namespace ImageSharp.Tests private ITestOutputHelper Output { get; } - private void PrintChannel(string name, JpegPixelArea channel) - { - this.Output.WriteLine($"{name}: Stride={channel.Stride}"); - } - [Theory] [InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio410, 4, 2)] [InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio411, 4, 1)] @@ -31,7 +26,10 @@ namespace ImageSharp.Tests [InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio422, 2, 1)] [InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio440, 1, 2)] [InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio444, 1, 1)] - internal void CalculateChrominanceSize(YCbCrImage.YCbCrSubsampleRatio ratioValue, int expectedDivX, int expectedDivY) + internal void CalculateChrominanceSize( + YCbCrImage.YCbCrSubsampleRatio ratioValue, + int expectedDivX, + int expectedDivY) { YCbCrImage.YCbCrSubsampleRatio ratio = (YCbCrImage.YCbCrSubsampleRatio)ratioValue; @@ -39,7 +37,7 @@ namespace ImageSharp.Tests Size size = YCbCrImage.CalculateChrominanceSize(400, 400, ratio); //this.Output.WriteLine($"Ch Size: {size}"); - Assert.Equal(new Size(400/expectedDivX, 400/expectedDivY), size); + Assert.Equal(new Size(400 / expectedDivX, 400 / expectedDivY), size); } [Theory] @@ -61,10 +59,14 @@ namespace ImageSharp.Tests //this.PrintChannel("Cb", img.CbChannel); //this.PrintChannel("Cr", img.CrChannel); - Assert.Equal(img.YChannel.Width, 400); + Assert.Equal(400, img.YChannel.Width); Assert.Equal(img.CbChannel.Width, 400 / expectedCStrideDiv); Assert.Equal(img.CrChannel.Width, 400 / expectedCStrideDiv); } + private void PrintChannel(string name, JpegPixelArea channel) + { + this.Output.WriteLine($"{name}: Stride={channel.Stride}"); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs b/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs index 50a86d3cc..a69727d45 100644 --- a/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs +++ b/tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs @@ -56,13 +56,13 @@ namespace ImageSharp.Tests.IO [Fact] public void ToBoolean() { - Assert.Equal(false, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0 }, 0)); - Assert.Equal(true, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1 }, 0)); - Assert.Equal(true, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 42 }, 0)); + Assert.False(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0 }, 0)); + Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1 }, 0)); + Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 42 }, 0)); - Assert.Equal(false, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1)); - Assert.Equal(true, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1)); - Assert.Equal(true, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 42 }, 1)); + Assert.False(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1)); + Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1)); + Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 42 }, 1)); } /// diff --git a/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs b/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs index fa8b2a1a2..c46c011a1 100644 --- a/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs +++ b/tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs @@ -56,11 +56,11 @@ namespace ImageSharp.Tests.IO [Fact] public void ToBoolean() { - Assert.Equal(false, EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0 }, 0)); - Assert.Equal(true, EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1 }, 0)); + Assert.False(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0 }, 0)); + Assert.True(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1 }, 0)); - Assert.Equal(false, EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1)); - Assert.Equal(true, EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1)); + Assert.False(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1)); + Assert.True(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1)); } /// diff --git a/tests/ImageSharp.Tests/MetaData/ImagePropertyTests.cs b/tests/ImageSharp.Tests/MetaData/ImagePropertyTests.cs index 8b4c6ea10..3b224014d 100644 --- a/tests/ImageSharp.Tests/MetaData/ImagePropertyTests.cs +++ b/tests/ImageSharp.Tests/MetaData/ImagePropertyTests.cs @@ -25,7 +25,7 @@ namespace ImageSharp.Tests Assert.Equal(property1, property2); Assert.True(property1 == property2); - Assert.Equal(property3, null); + Assert.Null(property3); } /// @@ -41,7 +41,7 @@ namespace ImageSharp.Tests Assert.False(property1.Equals("Foo")); - Assert.NotEqual(property1, null); + Assert.NotNull(property1); Assert.NotEqual(property1, property2); Assert.True(property1 != property2); @@ -69,7 +69,7 @@ namespace ImageSharp.Tests { ImageProperty property = new ImageProperty("Foo", null); Assert.Equal("Foo", property.Name); - Assert.Equal(null, property.Value); + Assert.Null(property.Value); property = new ImageProperty("Foo", string.Empty); Assert.Equal(string.Empty, property.Value); diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs index a91eb310d..473af7712 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs @@ -44,7 +44,7 @@ namespace ImageSharp.Tests Assert.Equal(ExifDataType.Ascii, value.DataType); Assert.Equal(ExifTag.GPSDOP, value.Tag); - Assert.Equal(false, value.IsArray); + Assert.False(value.IsArray); Assert.Equal("Windows Photo Editor 10.0.10011.16384", value.ToString()); Assert.Equal("Windows Photo Editor 10.0.10011.16384", value.Value); } diff --git a/tests/ImageSharp.Tests/Numerics/RectangleFTests.cs b/tests/ImageSharp.Tests/Numerics/RectangleFTests.cs index b20b660dd..78fbc68f6 100644 --- a/tests/ImageSharp.Tests/Numerics/RectangleFTests.cs +++ b/tests/ImageSharp.Tests/Numerics/RectangleFTests.cs @@ -256,6 +256,7 @@ namespace ImageSharp.Tests Assert.Equal(string.Format(CultureInfo.CurrentCulture, "RectangleF [ X={0}, Y={1}, Width={2}, Height={3} ]", r.X, r.Y, r.Width, r.Height), r.ToString()); } + [Theory] [InlineData(0, 0, 0, 0)] [InlineData(5, -5, 0.2, -1.3)] public void ToStringTestEmpty(float x, float y, float width, float height) diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs index dcb75245d..13f67fc27 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs @@ -1,3 +1,4 @@ +// ReSharper disable InconsistentNaming namespace ImageSharp.Tests { using ImageSharp.PixelFormats; @@ -19,6 +20,7 @@ namespace ImageSharp.Tests Assert.Equal(g, p.G); Assert.Equal(b, p.B); } + [Fact] public unsafe void ByteLayoutIsSequentialBgr() { @@ -30,34 +32,29 @@ namespace ImageSharp.Tests Assert.Equal(1, ptr[2]); } - public class Equality + [Theory] + [MemberData(nameof(ColorData))] + public void Equals_WhenTrue(byte r, byte g, byte b) { - public static TheoryData ColorData = Rgb24Tests.ColorData; - - [Theory] - [MemberData(nameof(ColorData))] - public void WhenTrue(byte r, byte g, byte b) - { - var x = new Rgb24(r, g, b); - var y = new Rgb24(r, g, b); - - Assert.True(x.Equals(y)); - Assert.True(x.Equals((object)y)); - Assert.Equal(x.GetHashCode(), y.GetHashCode()); - } - - [Theory] - [InlineData(1, 2, 3, 1, 2, 4)] - [InlineData(0, 255, 0, 0, 244, 0)] - [InlineData(1, 255, 0, 0, 255, 0)] - public void WhenFalse(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2) - { - var a = new Rgb24(r1, g1, b1); - var b = new Rgb24(r2, g2, b2); - - Assert.False(a.Equals(b)); - Assert.False(a.Equals((object)b)); - } + var x = new Rgb24(r, g, b); + var y = new Rgb24(r, g, b); + + Assert.True(x.Equals(y)); + Assert.True(x.Equals((object)y)); + Assert.Equal(x.GetHashCode(), y.GetHashCode()); + } + + [Theory] + [InlineData(1, 2, 3, 1, 2, 4)] + [InlineData(0, 255, 0, 0, 244, 0)] + [InlineData(1, 255, 0, 0, 255, 0)] + public void Equals_WhenFalse(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2) + { + var a = new Rgb24(r1, g1, b1); + var b = new Rgb24(r2, g2, b2); + + Assert.False(a.Equals(b)); + Assert.False(a.Equals((object)b)); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs index 82be9e810..1ff91a2b1 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs @@ -1,3 +1,4 @@ +// ReSharper disable InconsistentNaming namespace ImageSharp.Tests { using ImageSharp.PixelFormats; @@ -36,35 +37,30 @@ namespace ImageSharp.Tests Assert.Equal(4, ptr[3]); } - public class Equality + [Theory] + [MemberData(nameof(ColorData))] + public void Equality_WhenTrue(byte b, byte g, byte r, byte a) { - public static TheoryData ColorData = Bgra32Tests.ColorData; - - [Theory] - [MemberData(nameof(ColorData))] - public void WhenTrue(byte b, byte g, byte r, byte a) - { - var x = new Bgra32(r, g, b, a); - var y = new Bgra32(r, g, b, a); + var x = new Bgra32(r, g, b, a); + var y = new Bgra32(r, g, b, a); - Assert.True(x.Equals(y)); - Assert.True(x.Equals((object)y)); - Assert.Equal(x.GetHashCode(), y.GetHashCode()); - } + Assert.True(x.Equals(y)); + Assert.True(x.Equals((object)y)); + Assert.Equal(x.GetHashCode(), y.GetHashCode()); + } - [Theory] - [InlineData(1, 2, 3, 4, 1, 2, 3, 5)] - [InlineData(0, 0, 255, 0, 0, 0, 244, 0)] - [InlineData(0, 255, 0, 0, 0, 244, 0, 0)] - [InlineData(1, 255, 0, 0, 0, 255, 0, 0)] - public void WhenFalse(byte b1, byte g1, byte r1, byte a1, byte b2, byte g2, byte r2, byte a2) - { - var x = new Bgra32(r1, g1, b1, a1); - var y = new Bgra32(r2, g2, b2, a2); + [Theory] + [InlineData(1, 2, 3, 4, 1, 2, 3, 5)] + [InlineData(0, 0, 255, 0, 0, 0, 244, 0)] + [InlineData(0, 255, 0, 0, 0, 244, 0, 0)] + [InlineData(1, 255, 0, 0, 0, 255, 0, 0)] + public void Equality_WhenFalse(byte b1, byte g1, byte r1, byte a1, byte b2, byte g2, byte r2, byte a2) + { + var x = new Bgra32(r1, g1, b1, a1); + var y = new Bgra32(r2, g2, b2, a2); - Assert.False(x.Equals(y)); - Assert.False(x.Equals((object)y)); - } + Assert.False(x.Equals(y)); + Assert.False(x.Equals((object)y)); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs b/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs index dad426c40..773bfa513 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs @@ -40,10 +40,10 @@ namespace ImageSharp.Tests.Colors // Test ordering Vector4 vector = new Alpha8(.5F).ToVector4(); - Assert.Equal(vector.X, 0); - Assert.Equal(vector.Y, 0); - Assert.Equal(vector.Z, 0); - Assert.Equal(vector.W, .5F, 2); + Assert.Equal(0, vector.X); + Assert.Equal(0, vector.Y); + Assert.Equal(0, vector.Z); + Assert.Equal(.5F, vector.W, 2); byte[] rgb = new byte[3]; byte[] rgba = new byte[4]; diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs index fa7d9d247..76475388d 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs @@ -43,8 +43,11 @@ namespace ImageSharp.Tests.PixelFormats ); } + // [Fact] // Profiling benchmark - enable manually! +#pragma warning disable xUnit1013 // Public method should be marked as test public void Benchmark_ToVector4() +#pragma warning restore xUnit1013 // Public method should be marked as test { int times = 200000; int count = 1024; diff --git a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs index 666f3df78..7caa1e7c0 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs @@ -26,7 +26,7 @@ namespace ImageSharp.Tests.Processing.Transforms { for (int x = 0; x < 25; x++) { - Assert.Equal(image[x, y], default(TPixel)); + Assert.Equal(default(TPixel), image[x, y]); } } } diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs b/tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs index 8b57586f4..a300672e8 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs @@ -25,8 +25,8 @@ namespace ImageSharp.Tests.Processing.Transforms public int ExecutionCount { get; set; } = 50; // [Theory] // Benchmark, enable manually! - [InlineData(100, 100)] - [InlineData(2000, 2000)] + // [InlineData(100, 100)] + // [InlineData(2000, 2000)] public void ResizeBicubic(int width, int height) { this.Measure(this.ExecutionCount, diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs index 6bd5b392d..c01babb63 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -103,8 +103,8 @@ namespace ImageSharp.Tests where TPixel : struct, IPixel { Image img = provider.GetImage(); - Assert.Equal(img.Width, 10); - Assert.Equal(img.Height, 20); + Assert.Equal(10, img.Width); + Assert.Equal(20, img.Height); byte[] colors = new byte[4]; @@ -116,10 +116,10 @@ namespace ImageSharp.Tests { pixels[x, y].ToXyzwBytes(colors, 0); - Assert.Equal(colors[0], 255); - Assert.Equal(colors[1], 100); - Assert.Equal(colors[2], 50); - Assert.Equal(colors[3], 200); + Assert.Equal(255, colors[0]); + Assert.Equal(100, colors[1]); + Assert.Equal(50, colors[2]); + Assert.Equal(200, colors[3]); } } } @@ -143,7 +143,7 @@ namespace ImageSharp.Tests where TPixel : struct, IPixel { Image img = provider.GetImage(); - Assert.Equal(img.Width, 3); + Assert.Equal(3, img.Width); if (provider.PixelType == PixelTypes.Rgba32) { Assert.IsType>(img); diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs index a35c73aef..437c295b9 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs @@ -118,7 +118,7 @@ namespace ImageSharp.Tests IEnumerable> expanded = pixelTypes.ExpandAllTypes(); - Assert.Equal(expanded.Count(), 4); + Assert.Equal(4, expanded.Count()); AssertContainsPixelType(PixelTypes.Alpha8, expanded); AssertContainsPixelType(PixelTypes.Bgr565, expanded); From f745a14dfd5f725c8f888fe8b2b04af3a135e34c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 4 Jun 2017 16:45:03 +0200 Subject: [PATCH 11/16] refactor some of the PixelOperations. Ready to T4 the rest --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 4 +- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 2 +- src/ImageSharp/Image/PixelAccessor{TPixel}.cs | 6 +- .../PixelFormats/PixelOperations{TPixel}.cs | 54 +++-- .../PixelFormats/Rgba32.PixelOperations.cs | 32 ++- .../Quantizers/PaletteQuantizer{TPixel}.cs | 2 +- src/Shared/stylecop.json | 4 +- .../Color/Bulk/PackFromXyzw.cs | 4 +- .../ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs | 4 +- .../IccDataReader.TagDataEntryTests.cs | 202 ++++++++++++------ .../PixelFormats/PixelOperationsTests.cs | 6 +- 11 files changed, 201 insertions(+), 119 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index d2b68978f..e0bd153e6 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -603,13 +603,13 @@ namespace ImageSharp.Formats case PngColorType.Rgb: - PixelOperations.Instance.PackFromXyzBytes(scanlineBuffer, rowSpan, this.header.Width); + PixelOperations.Instance.PackFromRgb24Bytes(scanlineBuffer, rowSpan, this.header.Width); break; case PngColorType.RgbWithAlpha: - PixelOperations.Instance.PackFromXyzwBytes(scanlineBuffer, rowSpan, this.header.Width); + PixelOperations.Instance.PackFromRgba32Bytes(scanlineBuffer, rowSpan, this.header.Width); break; } diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 3fcf1fc81..a0be82bb0 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -342,7 +342,7 @@ namespace ImageSharp.Formats } else { - PixelOperations.Instance.ToXyzBytes(rowSpan, this.rawScanline, this.width); + PixelOperations.Instance.ToRgb24Bytes(rowSpan, this.rawScanline, this.width); } } diff --git a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs index 4baae8615..719c48a8d 100644 --- a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs +++ b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs @@ -315,7 +315,7 @@ namespace ImageSharp Span source = area.GetRowSpan(y); Span destination = this.GetRowSpan(targetX, targetY + y); - Operations.PackFromXyzBytes(source, destination, width); + Operations.PackFromRgb24Bytes(source, destination, width); } } @@ -334,7 +334,7 @@ namespace ImageSharp { Span source = area.GetRowSpan(y); Span destination = this.GetRowSpan(targetX, targetY + y); - Operations.PackFromXyzwBytes(source, destination, width); + Operations.PackFromRgba32Bytes(source, destination, width); } } @@ -391,7 +391,7 @@ namespace ImageSharp { Span source = this.GetRowSpan(sourceX, sourceY + y); Span destination = area.GetRowSpan(y); - Operations.ToXyzBytes(source, destination, width); + Operations.ToRgb24Bytes(source, destination, width); } } diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 39c1c0524..8eb44d00b 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -65,18 +65,13 @@ namespace ImageSharp.PixelFormats dp = sp.ToVector4(); } } - + /// - /// Bulk version of that converts data in . + /// Converts 'count' elements in 'source` span of data to a span of -s. /// - /// The to the source bytes. - /// The to the destination colors. + /// The source span of data. + /// The to the destination pixels. /// The number of pixels to convert. - internal virtual void PackFromXyzBytes(Span sourceBytes, Span destColors, int count) - { - this.PackFromRgb24(sourceBytes.NonPortableCast(), destColors, count); - } - internal virtual void PackFromRgb24(Span source, Span destPixels, int count) { Guard.MustBeSizedAtLeast(source, count, nameof(source)); @@ -96,32 +91,53 @@ namespace ImageSharp.PixelFormats } /// - /// Bulk version of . + /// A version of that expects a byte span to be converted to + /// Bulk version of + /// that converts bytes expected in R->G->B order compatible to layout. /// - /// The to the source colors. - /// The to the destination bytes. + /// The to the source bytes. + /// The to the destination pixels. /// The number of pixels to convert. - internal virtual void ToXyzBytes(Span sourceColors, Span destBytes, int count) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PackFromRgb24Bytes(Span sourceBytes, Span destPixels, int count) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 3, nameof(destBytes)); + this.PackFromRgb24(sourceBytes.NonPortableCast(), destPixels, count); + } - ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference(); + internal virtual void ToRgb24(Span sourcePixels, Span dest, int count) + { + Guard.MustBeSizedAtLeast(sourcePixels, count, nameof(sourcePixels)); + Guard.MustBeSizedAtLeast(dest, count, nameof(dest)); + + ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Rgb24 destBaseRef = ref dest.DangerousGetPinnableReference(); for (int i = 0; i < count; i++) { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - sp.ToXyzBytes(destBytes, i * 3); + ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref Rgb24 dp = ref Unsafe.Add(ref destBaseRef, i); + sp.ToRgb24(ref dp); } } + /// + /// Bulk version of . + /// + /// The to the source colors. + /// The to the destination bytes. + /// The number of pixels to convert. + internal void ToRgb24Bytes(Span sourceColors, Span destBytes, int count) + { + this.ToRgb24(sourceColors, destBytes.NonPortableCast(), count); + } + /// /// Bulk version of that converts data in . /// /// The to the source bytes. /// The to the destination colors. /// The number of pixels to convert. - internal virtual void PackFromXyzwBytes(Span sourceBytes, Span destColors, int count) + internal virtual void PackFromRgba32Bytes(Span sourceBytes, Span destColors, int count) { this.PackFromRgba32(sourceBytes.NonPortableCast(), destColors, count); } diff --git a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs index 2ba663603..0b0663cb5 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs @@ -120,45 +120,43 @@ namespace ImageSharp } } - /// - internal override void PackFromXyzBytes(Span sourceBytes, Span destColors, int count) + internal override void PackFromRgb24(Span source, Span destPixels, int count) { - Guard.MustBeSizedAtLeast(sourceBytes, count * 3, nameof(sourceBytes)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + Guard.MustBeSizedAtLeast(source, count, nameof(source)); + Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); - ref RGB24 sourceRef = ref Unsafe.As(ref sourceBytes.DangerousGetPinnableReference()); - ref Rgba32 destRef = ref destColors.DangerousGetPinnableReference(); + ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference(); + ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); for (int i = 0; i < count; i++) { - ref RGB24 sp = ref Unsafe.Add(ref sourceRef, i); + ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i); ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); - Unsafe.As(ref dp) = sp; + Unsafe.As(ref dp) = sp; dp.A = 255; } } - /// - internal override void ToXyzBytes(Span sourceColors, Span destBytes, int count) + internal override void ToRgb24(Span sourcePixels, Span dest, int count) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 3, nameof(destBytes)); + Guard.MustBeSizedAtLeast(sourcePixels, count, nameof(sourcePixels)); + Guard.MustBeSizedAtLeast(dest, count, nameof(dest)); - ref Rgba32 sourceRef = ref sourceColors.DangerousGetPinnableReference(); - ref RGB24 destRef = ref Unsafe.As(ref destBytes.DangerousGetPinnableReference()); + ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Rgb24 destRef = ref dest.DangerousGetPinnableReference(); for (int i = 0; i < count; i++) { ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); - ref RGB24 dp = ref Unsafe.Add(ref destRef, i); + ref Rgb24 dp = ref Unsafe.Add(ref destRef, i); - dp = Unsafe.As(ref sp); + dp = Unsafe.As(ref sp); } } /// - internal override unsafe void PackFromXyzwBytes(Span sourceBytes, Span destColors, int count) + internal override unsafe void PackFromRgba32Bytes(Span sourceBytes, Span destColors, int count) { Guard.MustBeSizedAtLeast(sourceBytes, count * 4, nameof(sourceBytes)); Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); diff --git a/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs index e9d2841a1..d121dc6ae 100644 --- a/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs @@ -45,7 +45,7 @@ namespace ImageSharp.Quantizers Span constantsBytes = constants.AsSpan().NonPortableCast(); - PixelOperations.Instance.PackFromXyzwBytes(constantsBytes, safe, constants.Length); + PixelOperations.Instance.PackFromRgba32Bytes(constantsBytes, safe, constants.Length); this.colors = safe; } else diff --git a/src/Shared/stylecop.json b/src/Shared/stylecop.json index 5a95b6c49..11ac49a40 100644 --- a/src/Shared/stylecop.json +++ b/src/Shared/stylecop.json @@ -3,9 +3,9 @@ "settings": { "documentationRules": { "companyName": "James Jackson-South", - "copyrightText": "Copyright (c) James Jackson-South and contributors.\nLicensed under the Apache License, Version 2.0.", + "copyrightText": "Copyright (c) James Jackson-South and contributors.\nLicensed under the Apache License, Version 2.0." + , "documentInterfaces": false, - "documentInternalElements": false, "documentExposedElements": false, "documentPrivateElements": false, diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs index 807df50e8..be94393a6 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs @@ -48,13 +48,13 @@ namespace ImageSharp.Benchmarks.Color.Bulk [Benchmark] public void CommonBulk() { - new PixelOperations().PackFromXyzwBytes(this.source, this.destination, this.Count); + new PixelOperations().PackFromRgba32Bytes(this.source, this.destination, this.Count); } [Benchmark] public void OptimizedBulk() { - PixelOperations.Instance.PackFromXyzwBytes(this.source, this.destination, this.Count); + PixelOperations.Instance.PackFromRgba32Bytes(this.source, this.destination, this.Count); } } diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs index 3c75fc2d1..57fc8bddf 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs @@ -46,13 +46,13 @@ namespace ImageSharp.Benchmarks.Color.Bulk [Benchmark] public void CommonBulk() { - new PixelOperations().ToXyzBytes(this.source, this.destination, this.Count); + new PixelOperations().ToRgb24Bytes(this.source, this.destination, this.Count); } [Benchmark] public void OptimizedBulk() { - PixelOperations.Instance.ToXyzBytes(this.source, this.destination, this.Count); + PixelOperations.Instance.ToRgb24Bytes(this.source, this.destination, this.Count); } } diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs index 9a2455f0e..6f003cc4d 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs @@ -10,10 +10,12 @@ namespace ImageSharp.Tests.Icc public class IccDataReaderTagDataEntryTests { [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.UnknownTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.UnknownTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadUnknownTagDataEntry(byte[] data, IccUnknownTagDataEntry expected, uint size) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccUnknownTagDataEntry output = reader.ReadUnknownTagDataEntry(size); @@ -21,10 +23,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.ChromaticityTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.ChromaticityTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadChromaticityTagDataEntry(byte[] data, IccChromaticityTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccChromaticityTagDataEntry output = reader.ReadChromaticityTagDataEntry(); @@ -32,10 +36,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.ColorantOrderTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.ColorantOrderTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadColorantOrderTagDataEntry(byte[] data, IccColorantOrderTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccColorantOrderTagDataEntry output = reader.ReadColorantOrderTagDataEntry(); @@ -43,10 +49,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.ColorantTableTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.ColorantTableTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadColorantTableTagDataEntry(byte[] data, IccColorantTableTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccColorantTableTagDataEntry output = reader.ReadColorantTableTagDataEntry(); @@ -54,10 +62,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.CurveTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.CurveTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadCurveTagDataEntry(byte[] data, IccCurveTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccCurveTagDataEntry output = reader.ReadCurveTagDataEntry(); @@ -65,10 +75,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.DataTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.DataTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadDataTagDataEntry(byte[] data, IccDataTagDataEntry expected, uint size) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccDataTagDataEntry output = reader.ReadDataTagDataEntry(size); @@ -76,10 +88,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.DateTimeTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.DateTimeTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadDateTimeTagDataEntry(byte[] data, IccDateTimeTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccDateTimeTagDataEntry output = reader.ReadDateTimeTagDataEntry(); @@ -87,10 +101,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.Lut16TagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.Lut16TagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadLut16TagDataEntry(byte[] data, IccLut16TagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccLut16TagDataEntry output = reader.ReadLut16TagDataEntry(); @@ -98,10 +114,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.Lut8TagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.Lut8TagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadLut8TagDataEntry(byte[] data, IccLut8TagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccLut8TagDataEntry output = reader.ReadLut8TagDataEntry(); @@ -109,10 +127,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.LutAToBTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.LutAToBTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadLutAToBTagDataEntry(byte[] data, IccLutAToBTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccLutAToBTagDataEntry output = reader.ReadLutAtoBTagDataEntry(); @@ -120,10 +140,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.LutBToATagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.LutBToATagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadLutBToATagDataEntry(byte[] data, IccLutBToATagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccLutBToATagDataEntry output = reader.ReadLutBtoATagDataEntry(); @@ -131,10 +153,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.MeasurementTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.MeasurementTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadMeasurementTagDataEntry(byte[] data, IccMeasurementTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccMeasurementTagDataEntry output = reader.ReadMeasurementTagDataEntry(); @@ -142,10 +166,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadMultiLocalizedUnicodeTagDataEntry(byte[] data, IccMultiLocalizedUnicodeTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccMultiLocalizedUnicodeTagDataEntry output = reader.ReadMultiLocalizedUnicodeTagDataEntry(); @@ -153,10 +179,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.MultiProcessElementsTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.MultiProcessElementsTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadMultiProcessElementsTagDataEntry(byte[] data, IccMultiProcessElementsTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccMultiProcessElementsTagDataEntry output = reader.ReadMultiProcessElementsTagDataEntry(); @@ -164,10 +192,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.NamedColor2TagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.NamedColor2TagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadNamedColor2TagDataEntry(byte[] data, IccNamedColor2TagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccNamedColor2TagDataEntry output = reader.ReadNamedColor2TagDataEntry(); @@ -175,10 +205,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.ParametricCurveTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.ParametricCurveTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadParametricCurveTagDataEntry(byte[] data, IccParametricCurveTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccParametricCurveTagDataEntry output = reader.ReadParametricCurveTagDataEntry(); @@ -186,10 +218,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.ProfileSequenceDescTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.ProfileSequenceDescTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadProfileSequenceDescTagDataEntry(byte[] data, IccProfileSequenceDescTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccProfileSequenceDescTagDataEntry output = reader.ReadProfileSequenceDescTagDataEntry(); @@ -197,10 +231,14 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.ProfileSequenceIdentifierTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] - internal void ReadProfileSequenceIdentifierTagDataEntry(byte[] data, IccProfileSequenceIdentifierTagDataEntry expected) + [MemberData( + nameof(IccTestDataTagDataEntry.ProfileSequenceIdentifierTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] + internal void ReadProfileSequenceIdentifierTagDataEntry( + byte[] data, + IccProfileSequenceIdentifierTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccProfileSequenceIdentifierTagDataEntry output = reader.ReadProfileSequenceIdentifierTagDataEntry(); @@ -208,10 +246,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.ResponseCurveSet16TagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.ResponseCurveSet16TagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadResponseCurveSet16TagDataEntry(byte[] data, IccResponseCurveSet16TagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccResponseCurveSet16TagDataEntry output = reader.ReadResponseCurveSet16TagDataEntry(); @@ -219,10 +259,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.Fix16ArrayTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.Fix16ArrayTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadFix16ArrayTagDataEntry(byte[] data, IccFix16ArrayTagDataEntry expected, uint size) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccFix16ArrayTagDataEntry output = reader.ReadFix16ArrayTagDataEntry(size); @@ -230,10 +272,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.SignatureTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.SignatureTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadSignatureTagDataEntry(byte[] data, IccSignatureTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccSignatureTagDataEntry output = reader.ReadSignatureTagDataEntry(); @@ -241,10 +285,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.TextTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.TextTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadTextTagDataEntry(byte[] data, IccTextTagDataEntry expected, uint size) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccTextTagDataEntry output = reader.ReadTextTagDataEntry(size); @@ -252,10 +298,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.UFix16ArrayTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.UFix16ArrayTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadUFix16ArrayTagDataEntry(byte[] data, IccUFix16ArrayTagDataEntry expected, uint size) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccUFix16ArrayTagDataEntry output = reader.ReadUFix16ArrayTagDataEntry(size); @@ -263,10 +311,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.UInt16ArrayTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.UInt16ArrayTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadUInt16ArrayTagDataEntry(byte[] data, IccUInt16ArrayTagDataEntry expected, uint size) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccUInt16ArrayTagDataEntry output = reader.ReadUInt16ArrayTagDataEntry(size); @@ -274,10 +324,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.UInt32ArrayTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.UInt32ArrayTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadUInt32ArrayTagDataEntry(byte[] data, IccUInt32ArrayTagDataEntry expected, uint size) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccUInt32ArrayTagDataEntry output = reader.ReadUInt32ArrayTagDataEntry(size); @@ -285,10 +337,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.UInt64ArrayTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.UInt64ArrayTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadUInt64ArrayTagDataEntry(byte[] data, IccUInt64ArrayTagDataEntry expected, uint size) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccUInt64ArrayTagDataEntry output = reader.ReadUInt64ArrayTagDataEntry(size); @@ -296,10 +350,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.UInt8ArrayTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.UInt8ArrayTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadUInt8ArrayTagDataEntry(byte[] data, IccUInt8ArrayTagDataEntry expected, uint size) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccUInt8ArrayTagDataEntry output = reader.ReadUInt8ArrayTagDataEntry(size); @@ -307,10 +363,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.ViewingConditionsTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.ViewingConditionsTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadViewingConditionsTagDataEntry(byte[] data, IccViewingConditionsTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccViewingConditionsTagDataEntry output = reader.ReadViewingConditionsTagDataEntry(); @@ -318,10 +376,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.XYZTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.XYZTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadXyzTagDataEntry(byte[] data, IccXyzTagDataEntry expected, uint size) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccXyzTagDataEntry output = reader.ReadXyzTagDataEntry(size); @@ -329,10 +389,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.TextDescriptionTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.TextDescriptionTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadTextDescriptionTagDataEntry(byte[] data, IccTextDescriptionTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccTextDescriptionTagDataEntry output = reader.ReadTextDescriptionTagDataEntry(); @@ -340,10 +402,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.CrdInfoTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.CrdInfoTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadCrdInfoTagDataEntry(byte[] data, IccCrdInfoTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccCrdInfoTagDataEntry output = reader.ReadCrdInfoTagDataEntry(); @@ -351,10 +415,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.ScreeningTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.ScreeningTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadScreeningTagDataEntry(byte[] data, IccScreeningTagDataEntry expected) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccScreeningTagDataEntry output = reader.ReadScreeningTagDataEntry(); @@ -362,10 +428,12 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataTagDataEntry.UcrBgTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] + [MemberData( + nameof(IccTestDataTagDataEntry.UcrBgTagDataEntryTestData), + MemberType = typeof(IccTestDataTagDataEntry))] internal void ReadUcrBgTagDataEntry(byte[] data, IccUcrBgTagDataEntry expected, uint size) { - IccDataReader reader = CreateReader(data); + IccDataReader reader = this.CreateReader(data); IccUcrBgTagDataEntry output = reader.ReadUcrBgTagDataEntry(size); diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs index 76475388d..ad5b05546 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs @@ -165,7 +165,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.PackFromXyzBytes(s, d, count) + (s, d) => Operations.PackFromRgb24Bytes(s, d, count) ); } @@ -185,7 +185,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToXyzBytes(s, d, count) + (s, d) => Operations.ToRgb24Bytes(s, d, count) ); } @@ -206,7 +206,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.PackFromXyzwBytes(s, d, count) + (s, d) => Operations.PackFromRgba32Bytes(s, d, count) ); } From 02f5be68b1e059d86d3d2c5786ff130584048f18 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 5 Jun 2017 03:44:50 +0200 Subject: [PATCH 12/16] T4 all the PixelOperations! --- src/ImageSharp/Common/Helpers/Guard.cs | 1 - src/ImageSharp/Formats/Png/PngEncoderCore.cs | 2 +- src/ImageSharp/Image/PixelAccessor{TPixel}.cs | 10 +- src/ImageSharp/ImageSharp.csproj | 9 + .../PixelOperations{TPixel}.Generated.cs | 297 ++++++++++++++++++ .../PixelOperations{TPixel}.Generated.tt | 120 +++++++ .../PixelFormats/PixelOperations{TPixel}.cs | 229 ++------------ .../PixelFormats/Rgba32.PixelOperations.cs | 107 ++----- src/ImageSharp/PixelFormats/Rgba32.cs | 11 + .../RgbaVector.PixelOperations.cs | 5 +- src/Shared/stylecop.json | 12 +- .../Color/Bulk/ToXyzw.cs | 4 +- .../PixelFormats/PixelOperationsTests.cs | 10 +- 13 files changed, 510 insertions(+), 307 deletions(-) create mode 100644 src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs create mode 100644 src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt diff --git a/src/ImageSharp/Common/Helpers/Guard.cs b/src/ImageSharp/Common/Helpers/Guard.cs index a4b392fcf..8e55c18af 100644 --- a/src/ImageSharp/Common/Helpers/Guard.cs +++ b/src/ImageSharp/Common/Helpers/Guard.cs @@ -242,7 +242,6 @@ namespace ImageSharp /// is true /// public static void MustBeSizedAtLeast(Span target, int minLength, string parameterName) - where T : struct { if (target.Length < minLength) { diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index a0be82bb0..645df0548 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -338,7 +338,7 @@ namespace ImageSharp.Formats { if (this.bytesPerPixel == 4) { - PixelOperations.Instance.ToXyzwBytes(rowSpan, this.rawScanline, this.width); + PixelOperations.Instance.ToRgba32Bytes(rowSpan, this.rawScanline, this.width); } else { diff --git a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs index 719c48a8d..3902ba425 100644 --- a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs +++ b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs @@ -275,7 +275,7 @@ namespace ImageSharp Span source = area.GetRowSpan(y); Span destination = this.GetRowSpan(targetX, targetY + y); - Operations.PackFromZyxBytes(source, destination, width); + Operations.PackFromBgr24Bytes(source, destination, width); } } @@ -295,7 +295,7 @@ namespace ImageSharp Span source = area.GetRowSpan(y); Span destination = this.GetRowSpan(targetX, targetY + y); - Operations.PackFromZyxwBytes(source, destination, width); + Operations.PackFromBgra32Bytes(source, destination, width); } } @@ -353,7 +353,7 @@ namespace ImageSharp { Span source = this.GetRowSpan(sourceX, sourceY + y); Span destination = area.GetRowSpan(y); - Operations.ToZyxBytes(source, destination, width); + Operations.ToBgr24Bytes(source, destination, width); } } @@ -372,7 +372,7 @@ namespace ImageSharp { Span source = this.GetRowSpan(sourceX, sourceY + y); Span destination = area.GetRowSpan(y); - Operations.ToZyxwBytes(source, destination, width); + Operations.ToBgra32Bytes(source, destination, width); } } @@ -410,7 +410,7 @@ namespace ImageSharp { Span source = this.GetRowSpan(sourceX, sourceY + y); Span destination = area.GetRowSpan(y); - Operations.ToXyzwBytes(source, destination, width); + Operations.ToRgba32Bytes(source, destination, width); } } diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 68a1571a3..60f88a79c 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -55,6 +55,10 @@ TextTemplatingFileGenerator Block8x8F.Generated.cs + + TextTemplatingFileGenerator + PixelOperations{TPixel}.Generated.cs + @@ -65,5 +69,10 @@ True Block8x8F.Generated.tt + + True + True + PixelOperations{TPixel}.Generated.tt + \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs new file mode 100644 index 000000000..6ae52351e --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs @@ -0,0 +1,297 @@ +// + +namespace ImageSharp.PixelFormats +{ + using System; + using System.Numerics; + using System.Runtime.CompilerServices; + + public partial class PixelOperations + { + + /// + /// Converts 'count' elements in 'source` span of data to a span of -s. + /// + /// The source of data. + /// The to the destination pixels. + /// The number of pixels to convert. + internal virtual void PackFromRgba32(Span source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref Rgba32 sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); + + for (int i = 0; i < count; i++) + { + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + rgba = Unsafe.Add(ref sourceRef, i); + dp.PackFromRgba32(rgba); + } + } + + /// + /// A helper for that expects a byte span. + /// The layout of the data in 'sourceBytes' must be compatible with layout. + /// + /// The to the source bytes. + /// The to the destination pixels. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PackFromRgba32Bytes(Span sourceBytes, Span destPixels, int count) + { + this.PackFromRgba32(sourceBytes.NonPortableCast(), destPixels, count); + } + + /// + /// Converts 'count' pixels in 'sourcePixels` span to a span of -s. + /// Bulk version of . + /// + /// The span of source pixels + /// The destination span of data. + /// The number of pixels to convert. + internal virtual void ToRgba32(Span sourcePixels, Span dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Rgba32 destBaseRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref Rgba32 dp = ref Unsafe.Add(ref destBaseRef, i); + sp.ToRgba32(ref dp); + } + } + + /// + /// A helper for that expects a byte span as destination. + /// The layout of the data in 'destBytes' must be compatible with layout. + /// + /// The to the source colors. + /// The to the destination bytes. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void ToRgba32Bytes(Span sourceColors, Span destBytes, int count) + { + this.ToRgba32(sourceColors, destBytes.NonPortableCast(), count); + } + + /// + /// Converts 'count' elements in 'source` span of data to a span of -s. + /// + /// The source of data. + /// The to the destination pixels. + /// The number of pixels to convert. + internal virtual void PackFromBgra32(Span source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); + + for (int i = 0; i < count; i++) + { + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + rgba = Unsafe.Add(ref sourceRef, i).ToRgba32(); + dp.PackFromRgba32(rgba); + } + } + + /// + /// A helper for that expects a byte span. + /// The layout of the data in 'sourceBytes' must be compatible with layout. + /// + /// The to the source bytes. + /// The to the destination pixels. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PackFromBgra32Bytes(Span sourceBytes, Span destPixels, int count) + { + this.PackFromBgra32(sourceBytes.NonPortableCast(), destPixels, count); + } + + /// + /// Converts 'count' pixels in 'sourcePixels` span to a span of -s. + /// Bulk version of . + /// + /// The span of source pixels + /// The destination span of data. + /// The number of pixels to convert. + internal virtual void ToBgra32(Span sourcePixels, Span dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Bgra32 destBaseRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref Bgra32 dp = ref Unsafe.Add(ref destBaseRef, i); + sp.ToBgra32(ref dp); + } + } + + /// + /// A helper for that expects a byte span as destination. + /// The layout of the data in 'destBytes' must be compatible with layout. + /// + /// The to the source colors. + /// The to the destination bytes. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void ToBgra32Bytes(Span sourceColors, Span destBytes, int count) + { + this.ToBgra32(sourceColors, destBytes.NonPortableCast(), count); + } + + /// + /// Converts 'count' elements in 'source` span of data to a span of -s. + /// + /// The source of data. + /// The to the destination pixels. + /// The number of pixels to convert. + internal virtual void PackFromRgb24(Span source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); + + for (int i = 0; i < count; i++) + { + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + rgba.Rgb = Unsafe.Add(ref sourceRef, i); + dp.PackFromRgba32(rgba); + } + } + + /// + /// A helper for that expects a byte span. + /// The layout of the data in 'sourceBytes' must be compatible with layout. + /// + /// The to the source bytes. + /// The to the destination pixels. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PackFromRgb24Bytes(Span sourceBytes, Span destPixels, int count) + { + this.PackFromRgb24(sourceBytes.NonPortableCast(), destPixels, count); + } + + /// + /// Converts 'count' pixels in 'sourcePixels` span to a span of -s. + /// Bulk version of . + /// + /// The span of source pixels + /// The destination span of data. + /// The number of pixels to convert. + internal virtual void ToRgb24(Span sourcePixels, Span dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Rgb24 destBaseRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref Rgb24 dp = ref Unsafe.Add(ref destBaseRef, i); + sp.ToRgb24(ref dp); + } + } + + /// + /// A helper for that expects a byte span as destination. + /// The layout of the data in 'destBytes' must be compatible with layout. + /// + /// The to the source colors. + /// The to the destination bytes. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void ToRgb24Bytes(Span sourceColors, Span destBytes, int count) + { + this.ToRgb24(sourceColors, destBytes.NonPortableCast(), count); + } + + /// + /// Converts 'count' elements in 'source` span of data to a span of -s. + /// + /// The source of data. + /// The to the destination pixels. + /// The number of pixels to convert. + internal virtual void PackFromBgr24(Span source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); + + for (int i = 0; i < count; i++) + { + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + rgba.Bgr = Unsafe.Add(ref sourceRef, i); + dp.PackFromRgba32(rgba); + } + } + + /// + /// A helper for that expects a byte span. + /// The layout of the data in 'sourceBytes' must be compatible with layout. + /// + /// The to the source bytes. + /// The to the destination pixels. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PackFromBgr24Bytes(Span sourceBytes, Span destPixels, int count) + { + this.PackFromBgr24(sourceBytes.NonPortableCast(), destPixels, count); + } + + /// + /// Converts 'count' pixels in 'sourcePixels` span to a span of -s. + /// Bulk version of . + /// + /// The span of source pixels + /// The destination span of data. + /// The number of pixels to convert. + internal virtual void ToBgr24(Span sourcePixels, Span dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Bgr24 destBaseRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref Bgr24 dp = ref Unsafe.Add(ref destBaseRef, i); + sp.ToBgr24(ref dp); + } + } + + /// + /// A helper for that expects a byte span as destination. + /// The layout of the data in 'destBytes' must be compatible with layout. + /// + /// The to the source colors. + /// The to the destination bytes. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void ToBgr24Bytes(Span sourceColors, Span destBytes, int count) + { + this.ToBgr24(sourceColors, destBytes.NonPortableCast(), count); + } + + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt new file mode 100644 index 000000000..edb74bb0c --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt @@ -0,0 +1,120 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +<# + + void GenerateToDestFormatMethods(string pixelType) + { + #> + + /// + /// Converts 'count' pixels in 'sourcePixels` span to a span of -s. + /// Bulk version of . + /// + /// The span of source pixels + /// The destination span of data. + /// The number of pixels to convert. + internal virtual void To<#=pixelType#>(Span sourcePixels, Span<<#=pixelType#>> dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); + ref <#=pixelType#> destBaseRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref <#=pixelType#> dp = ref Unsafe.Add(ref destBaseRef, i); + sp.To<#=pixelType#>(ref dp); + } + } + + /// + /// A helper for that expects a byte span as destination. + /// The layout of the data in 'destBytes' must be compatible with layout. + /// + /// The to the source colors. + /// The to the destination bytes. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void To<#=pixelType#>Bytes(Span sourceColors, Span destBytes, int count) + { + this.To<#=pixelType#>(sourceColors, destBytes.NonPortableCast>(), count); + } + <# + } + + void GeneratePackFromMethodUsingPackFromRgba32(string pixelType, string rgbaOperationCode) + { + #> + + /// + /// Converts 'count' elements in 'source` span of data to a span of -s. + /// + /// The source of data. + /// The to the destination pixels. + /// The number of pixels to convert. + internal virtual void PackFrom<#=pixelType#>(Span<<#=pixelType#>> source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref <#=pixelType#> sourceRef = ref source.DangerousGetPinnableReference(); + ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + + Rgba32 rgba = new Rgba32(0, 0, 0, 255); + + for (int i = 0; i < count; i++) + { + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + <#=rgbaOperationCode#> + dp.PackFromRgba32(rgba); + } + } + + /// + /// A helper for that expects a byte span. + /// The layout of the data in 'sourceBytes' must be compatible with layout. + /// + /// The to the source bytes. + /// The to the destination pixels. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PackFrom<#=pixelType#>Bytes(Span sourceBytes, Span destPixels, int count) + { + this.PackFrom<#=pixelType#>(sourceBytes.NonPortableCast>(), destPixels, count); + } + <# + } + +#> +// + +namespace ImageSharp.PixelFormats +{ + using System; + using System.Numerics; + using System.Runtime.CompilerServices; + + public partial class PixelOperations + { + <# + + GeneratePackFromMethodUsingPackFromRgba32("Rgba32", "rgba = Unsafe.Add(ref sourceRef, i);"); + GenerateToDestFormatMethods("Rgba32"); + + GeneratePackFromMethodUsingPackFromRgba32("Bgra32", "rgba = Unsafe.Add(ref sourceRef, i).ToRgba32();"); + GenerateToDestFormatMethods("Bgra32"); + + GeneratePackFromMethodUsingPackFromRgba32("Rgb24", "rgba.Rgb = Unsafe.Add(ref sourceRef, i);"); + GenerateToDestFormatMethods("Rgb24"); + + GeneratePackFromMethodUsingPackFromRgba32("Bgr24", "rgba.Bgr = Unsafe.Add(ref sourceRef, i);"); + GenerateToDestFormatMethods("Bgr24"); + + #> + + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 8eb44d00b..a62d14527 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -30,8 +30,7 @@ namespace ImageSharp.PixelFormats /// The number of pixels to convert. internal virtual void PackFromVector4(Span sourceVectors, Span destColors, int count) { - Guard.MustBeSizedAtLeast(sourceVectors, count, nameof(sourceVectors)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + GuardSpans(sourceVectors, nameof(sourceVectors), destColors, nameof(destColors), count); ref Vector4 sourceRef = ref sourceVectors.DangerousGetPinnableReference(); ref TPixel destRef = ref destColors.DangerousGetPinnableReference(); @@ -52,8 +51,7 @@ namespace ImageSharp.PixelFormats /// The number of pixels to convert. internal virtual void ToVector4(Span sourceColors, Span destVectors, int count) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destVectors, count, nameof(destVectors)); + GuardSpans(sourceColors, nameof(sourceColors), destVectors, nameof(destVectors), count); ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference(); ref Vector4 destRef = ref destVectors.DangerousGetPinnableReference(); @@ -65,216 +63,27 @@ namespace ImageSharp.PixelFormats dp = sp.ToVector4(); } } - - /// - /// Converts 'count' elements in 'source` span of data to a span of -s. - /// - /// The source span of data. - /// The to the destination pixels. - /// The number of pixels to convert. - internal virtual void PackFromRgb24(Span source, Span destPixels, int count) - { - Guard.MustBeSizedAtLeast(source, count, nameof(source)); - Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); - - ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); - - Rgba32 rgba = new Rgba32(0, 0, 0, 255); - - for (int i = 0; i < count; i++) - { - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - rgba.Rgb = Unsafe.Add(ref sourceRef, i); - dp.PackFromRgba32(rgba); - } - } - - /// - /// A version of that expects a byte span to be converted to - /// Bulk version of - /// that converts bytes expected in R->G->B order compatible to layout. - /// - /// The to the source bytes. - /// The to the destination pixels. - /// The number of pixels to convert. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void PackFromRgb24Bytes(Span sourceBytes, Span destPixels, int count) - { - this.PackFromRgb24(sourceBytes.NonPortableCast(), destPixels, count); - } - - internal virtual void ToRgb24(Span sourcePixels, Span dest, int count) - { - Guard.MustBeSizedAtLeast(sourcePixels, count, nameof(sourcePixels)); - Guard.MustBeSizedAtLeast(dest, count, nameof(dest)); - - ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); - ref Rgb24 destBaseRef = ref dest.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); - ref Rgb24 dp = ref Unsafe.Add(ref destBaseRef, i); - sp.ToRgb24(ref dp); - } - } - - /// - /// Bulk version of . - /// - /// The to the source colors. - /// The to the destination bytes. - /// The number of pixels to convert. - internal void ToRgb24Bytes(Span sourceColors, Span destBytes, int count) - { - this.ToRgb24(sourceColors, destBytes.NonPortableCast(), count); - } - - /// - /// Bulk version of that converts data in . - /// - /// The to the source bytes. - /// The to the destination colors. - /// The number of pixels to convert. - internal virtual void PackFromRgba32Bytes(Span sourceBytes, Span destColors, int count) - { - this.PackFromRgba32(sourceBytes.NonPortableCast(), destColors, count); - } - - internal virtual void PackFromRgba32(Span source, Span destPixels, int count) - { - Guard.MustBeSizedAtLeast(source, count, nameof(source)); - Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); - - ref Rgba32 sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); - - Rgba32 rgba = new Rgba32(0, 0, 0, 255); - - for (int i = 0; i < count; i++) - { - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - rgba = Unsafe.Add(ref sourceRef, i); - dp.PackFromRgba32(rgba); - } - } - - /// - /// Bulk version of - /// - /// The to the source colors. - /// The to the destination bytes. - /// The number of pixels to convert. - internal virtual void ToXyzwBytes(Span sourceColors, Span destBytes, int count) - { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 4, nameof(destBytes)); - - ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - sp.ToXyzwBytes(destBytes, i * 4); - } - } - - /// - /// Bulk version of that converts data in . - /// - /// The to the source bytes. - /// The to the destination colors. - /// The number of pixels to convert. - internal virtual void PackFromZyxBytes(Span sourceBytes, Span destColors, int count) - { - this.PackFromBgr24(sourceBytes.NonPortableCast(), destColors, count); - } - - internal virtual void PackFromBgr24(Span source, Span destPixels, int count) - { - Guard.MustBeSizedAtLeast(source, count, nameof(source)); - Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); - - ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); - - Rgba32 rgba = new Rgba32(0, 0, 0, 255); - - for (int i = 0; i < count; i++) - { - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - rgba.Bgr = Unsafe.Add(ref sourceRef, i); - dp.PackFromRgba32(rgba); - } - } - - /// - /// Bulk version of . - /// - /// The to the source colors. - /// The to the destination bytes. - /// The number of pixels to convert. - internal virtual void ToZyxBytes(Span sourceColors, Span destBytes, int count) - { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 3, nameof(destBytes)); - - ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - sp.ToZyxBytes(destBytes, i * 3); - } - } - - /// - /// Bulk version of that converts data in . - /// - /// The to the source bytes. - /// The to the destination colors. - /// The number of pixels to convert. - internal virtual void PackFromZyxwBytes(Span sourceBytes, Span destColors, int count) - { - this.PackFromBgra32(sourceBytes.NonPortableCast(), destColors, count); - } - - internal virtual void PackFromBgra32(Span source, Span destPixels, int count) - { - Guard.MustBeSizedAtLeast(source, count, nameof(source)); - Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); - - ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); - Rgba32 rgba = new Rgba32(0, 0, 0, 255); - - for (int i = 0; i < count; i++) - { - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - rgba = Unsafe.Add(ref sourceRef, i).ToRgba32(); - dp.PackFromRgba32(rgba); - } - } /// - /// Bulk version of . + /// Verifies that the given 'source' and 'dest' spans are at least of 'minLength' size. + /// Throwing an if the condition is not met. /// - /// The to the source colors. - /// The to the destination bytes. - /// The number of pixels to convert. - internal virtual void ToZyxwBytes(Span sourceColors, Span destBytes, int count) + /// The source element type + /// The destination element type + /// The source span + /// The source parameter name + /// The destination span + /// The destination parameter name + /// The minimum length + protected internal static void GuardSpans( + Span source, + string sourceParamName, + Span dest, + string destParamName, + int minLength) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 4, nameof(destBytes)); - - ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - sp.ToZyxwBytes(destBytes, i * 4); - } + Guard.MustBeSizedAtLeast(source, minLength, sourceParamName); + Guard.MustBeSizedAtLeast(dest, minLength, destParamName); } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs index 0b0663cb5..f10f0ba27 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs @@ -120,6 +120,7 @@ namespace ImageSharp } } + /// internal override void PackFromRgb24(Span source, Span destPixels, int count) { Guard.MustBeSizedAtLeast(source, count, nameof(source)); @@ -138,6 +139,7 @@ namespace ImageSharp } } + /// internal override void ToRgb24(Span sourcePixels, Span dest, int count) { Guard.MustBeSizedAtLeast(sourcePixels, count, nameof(sourcePixels)); @@ -156,129 +158,86 @@ namespace ImageSharp } /// - internal override unsafe void PackFromRgba32Bytes(Span sourceBytes, Span destColors, int count) + internal override void PackFromRgba32(Span source, Span destPixels, int count) { - Guard.MustBeSizedAtLeast(sourceBytes, count * 4, nameof(sourceBytes)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - SpanHelper.Copy(sourceBytes, destColors.AsBytes(), count * sizeof(Rgba32)); + SpanHelper.Copy(source, destPixels, count); } /// - internal override unsafe void ToXyzwBytes(Span sourceColors, Span destBytes, int count) + internal override void ToRgba32(Span sourcePixels, Span dest, int count) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 4, nameof(destBytes)); + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - SpanHelper.Copy(sourceColors.AsBytes(), destBytes, count * sizeof(Rgba32)); + SpanHelper.Copy(sourcePixels, dest, count); } /// - internal override void PackFromZyxBytes(Span sourceBytes, Span destColors, int count) + internal override void PackFromBgr24(Span source, Span destPixels, int count) { - Guard.MustBeSizedAtLeast(sourceBytes, count * 3, nameof(sourceBytes)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref RGB24 sourceRef = ref Unsafe.As(ref sourceBytes.DangerousGetPinnableReference()); - ref Rgba32 destRef = ref destColors.DangerousGetPinnableReference(); + ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); + ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); for (int i = 0; i < count; i++) { - ref RGB24 sp = ref Unsafe.Add(ref sourceRef, i); + ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); - - Unsafe.As(ref dp) = sp.ToZyx(); + dp.Bgr = sp; dp.A = 255; } } /// - internal override void ToZyxBytes(Span sourceColors, Span destBytes, int count) + internal override void ToBgr24(Span sourcePixels, Span dest, int count) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 3, nameof(destBytes)); + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref Rgba32 sourceRef = ref sourceColors.DangerousGetPinnableReference(); - ref RGB24 destRef = ref Unsafe.As(ref destBytes.DangerousGetPinnableReference()); + ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Bgr24 destRef = ref dest.DangerousGetPinnableReference(); for (int i = 0; i < count; i++) { ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); - ref RGB24 dp = ref Unsafe.Add(ref destRef, i); - - dp = Unsafe.As(ref sp).ToZyx(); + ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); + dp = sp.Bgr; } } /// - internal override void PackFromZyxwBytes(Span sourceBytes, Span destColors, int count) + internal override void PackFromBgra32(Span source, Span destPixels, int count) { - Guard.MustBeSizedAtLeast(sourceBytes, count * 4, nameof(sourceBytes)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref RGBA32 sourceRef = ref Unsafe.As(ref sourceBytes.DangerousGetPinnableReference()); - ref Rgba32 destRef = ref destColors.DangerousGetPinnableReference(); + ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); + ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); for (int i = 0; i < count; i++) { - ref RGBA32 sp = ref Unsafe.Add(ref sourceRef, i); + ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i); ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); - RGBA32 zyxw = sp.ToZyxw(); - dp = Unsafe.As(ref zyxw); + dp = sp.ToRgba32(); } } /// - internal override void ToZyxwBytes(Span sourceColors, Span destBytes, int count) + internal override void ToBgra32(Span sourcePixels, Span dest, int count) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destBytes, count * 4, nameof(destBytes)); + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref Rgba32 sourceRef = ref sourceColors.DangerousGetPinnableReference(); - ref RGBA32 destRef = ref Unsafe.As(ref destBytes.DangerousGetPinnableReference()); + ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Bgra32 destRef = ref dest.DangerousGetPinnableReference(); for (int i = 0; i < count; i++) { - ref RGBA32 sp = ref Unsafe.As(ref Unsafe.Add(ref sourceRef, i)); - ref RGBA32 dp = ref Unsafe.Add(ref destRef, i); - dp = sp.ToZyxw(); + ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); + ref Bgra32 dp = ref Unsafe.Add(ref destRef, i); + dp = sp.ToBgra32(); } } - /// - /// Helper struct to manipulate 3-byte RGB data. - /// - [StructLayout(LayoutKind.Sequential)] - private struct RGB24 - { - private byte x; - - private byte y; - - private byte z; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RGB24 ToZyx() => new RGB24 { x = this.z, y = this.y, z = this.x }; - } - - /// - /// Helper struct to manipulate 4-byte RGBA data. - /// - [StructLayout(LayoutKind.Sequential)] - private struct RGBA32 - { - private byte x; - - private byte y; - - private byte z; - - private byte w; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RGBA32 ToZyxw() => new RGBA32 { x = this.z, y = this.y, z = this.x, w = this.w }; - } - /// /// Value type to store -s unpacked into multiple -s. /// diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs index 240a1a296..85322c7c5 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.cs @@ -337,6 +337,17 @@ namespace ImageSharp return new Vector4(this.R, this.G, this.B, this.A) / MaxBytes; } + /// + /// Gets the value of this struct as . + /// Useful for changing the component order. + /// + /// A value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Bgra32 ToBgra32() + { + return new Bgra32(this.R, this.G, this.B, this.A); + } + /// public override bool Equals(object obj) { diff --git a/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs index ac25b7f14..00b746166 100644 --- a/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs @@ -23,10 +23,9 @@ namespace ImageSharp.PixelFormats /// internal override unsafe void ToVector4(Span sourceColors, Span destVectors, int count) { - Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors)); - Guard.MustBeSizedAtLeast(destVectors, count, nameof(destVectors)); + GuardSpans(sourceColors, nameof(sourceColors), destVectors, nameof(destVectors), count); - SpanHelper.Copy(sourceColors.AsBytes(), destVectors.AsBytes(), count * sizeof(Vector4)); + SpanHelper.Copy(sourceColors.NonPortableCast(), destVectors, count); } } } diff --git a/src/Shared/stylecop.json b/src/Shared/stylecop.json index 11ac49a40..4f8205d06 100644 --- a/src/Shared/stylecop.json +++ b/src/Shared/stylecop.json @@ -4,12 +4,12 @@ "documentationRules": { "companyName": "James Jackson-South", "copyrightText": "Copyright (c) James Jackson-South and contributors.\nLicensed under the Apache License, Version 2.0." - , - "documentInterfaces": false, - "documentInternalElements": false, - "documentExposedElements": false, - "documentPrivateElements": false, - "documentPrivateFields": false + //, + //"documentInterfaces": false, + //"documentInternalElements": false, + //"documentExposedElements": false, + //"documentPrivateElements": false, + //"documentPrivateFields": false } } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs index f64bf561b..a702e8385 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs @@ -51,13 +51,13 @@ namespace ImageSharp.Benchmarks.Color.Bulk [Benchmark] public void CommonBulk() { - new PixelOperations().ToXyzwBytes(this.source, this.destination, this.Count); + new PixelOperations().ToRgba32Bytes(this.source, this.destination, this.Count); } [Benchmark] public void OptimizedBulk() { - PixelOperations.Instance.ToXyzwBytes(this.source, this.destination, this.Count); + PixelOperations.Instance.ToRgba32Bytes(this.source, this.destination, this.Count); } } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs index ad5b05546..0a121cfce 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs @@ -226,7 +226,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToXyzwBytes(s, d, count) + (s, d) => Operations.ToRgba32Bytes(s, d, count) ); } @@ -247,7 +247,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.PackFromZyxBytes(s, d, count) + (s, d) => Operations.PackFromBgr24Bytes(s, d, count) ); } @@ -267,7 +267,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToZyxBytes(s, d, count) + (s, d) => Operations.ToBgr24Bytes(s, d, count) ); } @@ -288,7 +288,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.PackFromZyxwBytes(s, d, count) + (s, d) => Operations.PackFromBgra32Bytes(s, d, count) ); } @@ -308,7 +308,7 @@ namespace ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToZyxwBytes(s, d, count) + (s, d) => Operations.ToBgra32Bytes(s, d, count) ); } From daad823932d986d3b6d2b044c9426915526fe639 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 5 Jun 2017 04:20:37 +0200 Subject: [PATCH 13/16] implemented the rest of pixel conversion methods --- src/ImageSharp/PixelFormats/Bgr24.cs | 23 ++- src/ImageSharp/PixelFormats/Bgra32.cs | 35 +++-- src/ImageSharp/PixelFormats/Rgb24.cs | 26 +++- .../PixelFormats/Bgr24Tests.cs | 91 +++++++++++- .../PixelFormats/Bgra32Tests.cs | 84 +++++++++++ .../PixelFormats/Rgb24Tests.cs | 132 ++++++++++++++---- .../TestUtilities/PixelTypes.cs | 6 + 7 files changed, 343 insertions(+), 54 deletions(-) diff --git a/src/ImageSharp/PixelFormats/Bgr24.cs b/src/ImageSharp/PixelFormats/Bgr24.cs index a3b3a907d..cc7720044 100644 --- a/src/ImageSharp/PixelFormats/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/Bgr24.cs @@ -71,27 +71,35 @@ } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgba32(Rgba32 source) { - throw new NotImplementedException(); + this = source.Bgr; } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) { - throw new NotImplementedException(); + var rgba = default(Rgba32); + rgba.PackFromVector4(vector); + this.PackFromRgba32(rgba); } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ToVector4() { - throw new NotImplementedException(); + return new Rgba32(this.R, this.G, this.B, 255).ToVector4(); } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - throw new NotImplementedException(); + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; } /// @@ -107,13 +115,16 @@ /// public void ToBgr24(ref Bgr24 dest) { - throw new NotImplementedException(); + dest = this; } /// public void ToBgra32(ref Bgra32 dest) { - throw new NotImplementedException(); + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; + dest.A = 255; } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Bgra32.cs b/src/ImageSharp/PixelFormats/Bgra32.cs index e07e4c0e3..8146321b9 100644 --- a/src/ImageSharp/PixelFormats/Bgra32.cs +++ b/src/ImageSharp/PixelFormats/Bgra32.cs @@ -1,12 +1,10 @@ -namespace ImageSharp +namespace ImageSharp.PixelFormats { using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - using ImageSharp.PixelFormats; - /// /// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255. /// The color components are stored in blue, green, red, and alpha order. @@ -116,45 +114,62 @@ } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) { - throw new NotImplementedException(); + var rgba = default(Rgba32); + rgba.PackFromVector4(vector); + this.PackFromRgba32(rgba); } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ToVector4() { - throw new NotImplementedException(); + return this.ToRgba32().ToVector4(); } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgba32(Rgba32 source) { - throw new NotImplementedException(); + this.R = source.R; + this.G = source.G; + this.B = source.B; + this.A = source.A; } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - throw new NotImplementedException(); + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgba32(ref Rgba32 dest) { - throw new NotImplementedException(); + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; + dest.A = this.A; } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgr24(ref Bgr24 dest) { - throw new NotImplementedException(); + dest = Unsafe.As(ref this); } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToBgra32(ref Bgra32 dest) { - throw new NotImplementedException(); + dest = this; } /// diff --git a/src/ImageSharp/PixelFormats/Rgb24.cs b/src/ImageSharp/PixelFormats/Rgb24.cs index 13dcaff95..47dd96055 100644 --- a/src/ImageSharp/PixelFormats/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/Rgb24.cs @@ -71,45 +71,57 @@ namespace ImageSharp.PixelFormats } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromRgba32(Rgba32 source) { - throw new NotImplementedException(); + this = Unsafe.As(ref source); } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PackFromVector4(Vector4 vector) { - throw new NotImplementedException(); + var rgba = default(Rgba32); + rgba.PackFromVector4(vector); + this.PackFromRgba32(rgba); } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ToVector4() { - throw new NotImplementedException(); + return new Rgba32(this.R, this.G, this.B, 255).ToVector4(); } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ToRgb24(ref Rgb24 dest) { - throw new NotImplementedException(); + dest = this; } /// public void ToRgba32(ref Rgba32 dest) { - throw new NotImplementedException(); + dest.Rgb = this; + dest.A = 255; } /// public void ToBgr24(ref Bgr24 dest) { - throw new NotImplementedException(); + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; } /// public void ToBgra32(ref Bgra32 dest) { - throw new NotImplementedException(); + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; + dest.A = 255; } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs index 13f67fc27..76001ed3a 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs @@ -1,6 +1,8 @@ // ReSharper disable InconsistentNaming namespace ImageSharp.Tests { + using System.Numerics; + using ImageSharp.PixelFormats; using Xunit; @@ -36,8 +38,8 @@ namespace ImageSharp.Tests [MemberData(nameof(ColorData))] public void Equals_WhenTrue(byte r, byte g, byte b) { - var x = new Rgb24(r, g, b); - var y = new Rgb24(r, g, b); + var x = new Bgr24(r, g, b); + var y = new Bgr24(r, g, b); Assert.True(x.Equals(y)); Assert.True(x.Equals((object)y)); @@ -50,11 +52,92 @@ namespace ImageSharp.Tests [InlineData(1, 255, 0, 0, 255, 0)] public void Equals_WhenFalse(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2) { - var a = new Rgb24(r1, g1, b1); - var b = new Rgb24(r2, g2, b2); + var a = new Bgr24(r1, g1, b1); + var b = new Bgr24(r2, g2, b2); Assert.False(a.Equals(b)); Assert.False(a.Equals((object)b)); } + + + [Fact] + public void PackFromRgba32() + { + var rgb = default(Bgr24); + rgb.PackFromRgba32(new Rgba32(1, 2, 3, 4)); + + Assert.Equal(1, rgb.R); + Assert.Equal(2, rgb.G); + Assert.Equal(3, rgb.B); + } + + private static Vector4 Vec(byte r, byte g, byte b, byte a = 255) => new Vector4( + r / 255f, + g / 255f, + b / 255f, + a / 255f); + + [Fact] + public void PackFromVector4() + { + var rgb = default(Bgr24); + rgb.PackFromVector4(Vec(1, 2, 3, 4)); + + Assert.Equal(1, rgb.R); + Assert.Equal(2, rgb.G); + Assert.Equal(3, rgb.B); + } + + [Fact] + public void ToVector4() + { + var rgb = new Bgr24(1, 2, 3); + + Assert.Equal(Vec(1, 2, 3), rgb.ToVector4()); + } + + [Fact] + public void ToRgb24() + { + var rgb = new Bgr24(1, 2, 3); + var dest = default(Rgb24); + + rgb.ToRgb24(ref dest); + + Assert.Equal(new Rgb24(1, 2, 3), dest); + } + + [Fact] + public void ToRgba32() + { + var rgb = new Bgr24(1, 2, 3); + var rgba = default(Rgba32); + + rgb.ToRgba32(ref rgba); + + Assert.Equal(new Rgba32(1, 2, 3, 255), rgba); + } + + [Fact] + public void ToBgr24() + { + var rgb = new Bgr24(1, 2, 3); + var bgr = default(Bgr24); + + rgb.ToBgr24(ref bgr); + + Assert.Equal(new Bgr24(1, 2, 3), bgr); + } + + [Fact] + public void ToBgra32() + { + var rgb = new Bgr24(1, 2, 3); + var bgra = default(Bgra32); + + rgb.ToBgra32(ref bgra); + + Assert.Equal(new Bgra32(1, 2, 3, 255), bgra); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs index 1ff91a2b1..1928d51f6 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs @@ -1,6 +1,8 @@ // ReSharper disable InconsistentNaming namespace ImageSharp.Tests { + using System.Numerics; + using ImageSharp.PixelFormats; using Xunit; @@ -62,5 +64,87 @@ namespace ImageSharp.Tests Assert.False(x.Equals(y)); Assert.False(x.Equals((object)y)); } + + + [Fact] + public void PackFromRgba32() + { + var rgb = default(Rgb24); + rgb.PackFromRgba32(new Rgba32(1, 2, 3, 4)); + + Assert.Equal(1, rgb.R); + Assert.Equal(2, rgb.G); + Assert.Equal(3, rgb.B); + } + + private static Vector4 Vec(byte r, byte g, byte b, byte a = 255) => new Vector4( + r / 255f, + g / 255f, + b / 255f, + a / 255f); + + [Fact] + public void PackFromVector4() + { + var c = default(Bgra32); + c.PackFromVector4(Vec(1, 2, 3, 4)); + + Assert.Equal(1, c.R); + Assert.Equal(2, c.G); + Assert.Equal(3, c.B); + Assert.Equal(4, c.A); + } + + [Fact] + public void ToVector4() + { + var rgb = new Bgra32(1, 2, 3, 4); + + Assert.Equal(Vec(1, 2, 3, 4), rgb.ToVector4()); + } + + [Fact] + public void ToRgb24() + { + var c = new Bgra32(1, 2, 3, 4); + var dest = default(Rgb24); + + c.ToRgb24(ref dest); + + Assert.Equal(new Rgb24(1, 2, 3), dest); + } + + [Fact] + public void ToRgba32() + { + var c = new Bgra32(1, 2, 3, 4); + var rgba = default(Rgba32); + + c.ToRgba32(ref rgba); + + Assert.Equal(new Rgba32(1, 2, 3, 4), rgba); + } + + [Fact] + public void ToBgr24() + { + var rgb = new Bgra32(1, 2, 3, 4); + var bgr = default(Bgr24); + + rgb.ToBgr24(ref bgr); + + Assert.Equal(new Bgr24(1, 2, 3), bgr); + } + + [Fact] + public void ToBgra32() + { + var rgb = new Bgra32(1, 2, 3, 4); + var bgra = default(Bgra32); + + rgb.ToBgra32(ref bgra); + + Assert.Equal(new Bgra32(1, 2, 3, 4), bgra); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs index 6118e4432..1d0d024fb 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs @@ -1,6 +1,9 @@ // ReSharper disable InconsistentNaming namespace ImageSharp.Tests { + using System; + using System.Numerics; + using ImageSharp.PixelFormats; using Xunit; @@ -32,34 +35,109 @@ namespace ImageSharp.Tests Assert.Equal(3, ptr[2]); } - public class Equality + [Theory] + [MemberData(nameof(ColorData))] + public void Equals_WhenTrue(byte r, byte g, byte b) + { + var x = new Rgb24(r, g, b); + var y = new Rgb24(r, g, b); + + Assert.True(x.Equals(y)); + Assert.True(x.Equals((object)y)); + Assert.Equal(x.GetHashCode(), y.GetHashCode()); + } + + [Theory] + [InlineData(1, 2, 3, 1, 2, 4)] + [InlineData(0, 255, 0, 0, 244, 0)] + [InlineData(1, 255, 0, 0, 255, 0)] + public void Equals_WhenFalse(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2) + { + var a = new Rgb24(r1, g1, b1); + var b = new Rgb24(r2, g2, b2); + + Assert.False(a.Equals(b)); + Assert.False(a.Equals((object)b)); + } + + [Fact] + public void PackFromRgba32() + { + var rgb = default(Rgb24); + rgb.PackFromRgba32(new Rgba32(1, 2, 3, 4)); + + Assert.Equal(1, rgb.R); + Assert.Equal(2, rgb.G); + Assert.Equal(3, rgb.B); + } + + private static Vector4 Vec(byte r, byte g, byte b, byte a = 255) => new Vector4( + r / 255f, + g / 255f, + b / 255f, + a / 255f); + + [Fact] + public void PackFromVector4() + { + var rgb = default(Rgb24); + rgb.PackFromVector4(Vec(1, 2, 3, 4)); + + Assert.Equal(1, rgb.R); + Assert.Equal(2, rgb.G); + Assert.Equal(3, rgb.B); + } + + [Fact] + public void ToVector4() + { + var rgb = new Rgb24(1, 2, 3); + + Assert.Equal(Vec(1, 2, 3), rgb.ToVector4()); + } + + [Fact] + public void ToRgb24() + { + var rgb = new Rgb24(1, 2, 3); + var dest = default(Rgb24); + + rgb.ToRgb24(ref dest); + + Assert.Equal(rgb, dest); + } + + [Fact] + public void ToRgba32() + { + var rgb = new Rgb24(1, 2, 3); + var rgba = default(Rgba32); + + rgb.ToRgba32(ref rgba); + + Assert.Equal(new Rgba32(1, 2, 3, 255), rgba); + } + + [Fact] + public void ToBgr24() + { + var rgb = new Rgb24(1, 2, 3); + var bgr = default(Bgr24); + + rgb.ToBgr24(ref bgr); + + Assert.Equal(new Bgr24(1, 2, 3), bgr); + } + + [Fact] + public void ToBgra32() { - public static TheoryData ColorData = Rgb24Tests.ColorData; - - [Theory] - [MemberData(nameof(ColorData))] - public void WhenTrue(byte r, byte g, byte b) - { - var x = new Rgb24(r, g, b); - var y = new Rgb24(r, g, b); - - Assert.True(x.Equals(y)); - Assert.True(x.Equals((object)y)); - Assert.Equal(x.GetHashCode(), y.GetHashCode()); - } - - [Theory] - [InlineData(1, 2, 3, 1, 2, 4)] - [InlineData(0, 255, 0, 0, 244, 0)] - [InlineData(1, 255, 0, 0, 255, 0)] - public void WhenFalse(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2) - { - var a = new Rgb24(r1, g1, b1); - var b = new Rgb24(r2, g2, b2); - - Assert.False(a.Equals(b)); - Assert.False(a.Equals((object)b)); - } + var rgb = new Rgb24(1, 2, 3); + var bgra = default(Bgra32); + + rgb.ToBgra32(ref bgra); + + Assert.Equal(new Bgra32(1, 2, 3, 255), bgra); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs b/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs index 5c676d07c..645a4dc59 100644 --- a/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs +++ b/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs @@ -52,6 +52,12 @@ namespace ImageSharp.Tests Short4 = 1 << 17, + Rgb24 = 18, + + Bgr24 = 19, + + Bgra32 = 20, + // TODO: Add multi-flag entries by rules defined in PackedPixelConverterHelper // "All" is handled as a separate, individual case instead of using bitwise OR From a362e7dfec25ac120f8699afbb5a3b6203a323b8 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 5 Jun 2017 04:57:25 +0200 Subject: [PATCH 14/16] removed unnecessary warnings, added source headers --- src/ImageSharp/PixelFormats/Bgr24.cs | 7 +++- src/ImageSharp/PixelFormats/Bgra32.cs | 7 +++- src/ImageSharp/PixelFormats/Bgra4444.cs | 42 +++++++++---------- .../PixelFormats/NormalizedByte2.cs | 16 +++---- .../PixelFormats/NormalizedByte4.cs | 28 ++++++------- src/ImageSharp/PixelFormats/Rgb24.cs | 5 +++ src/Shared/stylecop.json | 6 --- 7 files changed, 60 insertions(+), 51 deletions(-) diff --git a/src/ImageSharp/PixelFormats/Bgr24.cs b/src/ImageSharp/PixelFormats/Bgr24.cs index cc7720044..aaed5c385 100644 --- a/src/ImageSharp/PixelFormats/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/Bgr24.cs @@ -1,4 +1,9 @@ -namespace ImageSharp.PixelFormats +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.PixelFormats { using System; using System.Numerics; diff --git a/src/ImageSharp/PixelFormats/Bgra32.cs b/src/ImageSharp/PixelFormats/Bgra32.cs index 8146321b9..f1ac20b56 100644 --- a/src/ImageSharp/PixelFormats/Bgra32.cs +++ b/src/ImageSharp/PixelFormats/Bgra32.cs @@ -1,4 +1,9 @@ -namespace ImageSharp.PixelFormats +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.PixelFormats { using System; using System.Numerics; diff --git a/src/ImageSharp/PixelFormats/Bgra4444.cs b/src/ImageSharp/PixelFormats/Bgra4444.cs index d10ea58c7..746e1062b 100644 --- a/src/ImageSharp/PixelFormats/Bgra4444.cs +++ b/src/ImageSharp/PixelFormats/Bgra4444.cs @@ -79,10 +79,10 @@ namespace ImageSharp.PixelFormats const float Max = 1 / 15F; return new Vector4( - ((this.PackedValue >> 8) & 0x0F) * Max, - ((this.PackedValue >> 4) & 0x0F) * Max, - (this.PackedValue & 0x0F) * Max, - ((this.PackedValue >> 12) & 0x0F) * Max); + ((this.PackedValue >> 8) & 0x0F) * Max, + ((this.PackedValue >> 4) & 0x0F) * Max, + (this.PackedValue & 0x0F) * Max, + ((this.PackedValue >> 12) & 0x0F) * Max); } /// @@ -104,9 +104,9 @@ namespace ImageSharp.PixelFormats public void ToRgb24(ref Rgb24 dest) { Vector4 vector = this.ToVector4() * 255F; - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); - dest.B = (byte)MathF.Round(vector.Z); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// @@ -114,10 +114,10 @@ namespace ImageSharp.PixelFormats public void ToRgba32(ref Rgba32 dest) { Vector4 vector = this.ToVector4() * 255F; - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); - dest.B = (byte)MathF.Round(vector.Z); - dest.A = (byte)MathF.Round(vector.W); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// @@ -125,9 +125,9 @@ namespace ImageSharp.PixelFormats public void ToBgr24(ref Bgr24 dest) { Vector4 vector = this.ToVector4() * 255F; - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); - dest.B = (byte)MathF.Round(vector.Z); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// @@ -135,10 +135,10 @@ namespace ImageSharp.PixelFormats public void ToBgra32(ref Bgra32 dest) { Vector4 vector = this.ToVector4() * 255F; - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); - dest.B = (byte)MathF.Round(vector.Z); - dest.A = (byte)MathF.Round(vector.W); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// @@ -179,9 +179,9 @@ namespace ImageSharp.PixelFormats private static ushort Pack(float x, float y, float z, float w) { return (ushort)((((int)Math.Round(w.Clamp(0, 1) * 15F) & 0x0F) << 12) | - (((int)Math.Round(x.Clamp(0, 1) * 15F) & 0x0F) << 8) | - (((int)Math.Round(y.Clamp(0, 1) * 15F) & 0x0F) << 4) | - ((int)Math.Round(z.Clamp(0, 1) * 15F) & 0x0F)); + (((int)Math.Round(x.Clamp(0, 1) * 15F) & 0x0F) << 8) | + (((int)Math.Round(y.Clamp(0, 1) * 15F) & 0x0F) << 4) | + ((int)Math.Round(z.Clamp(0, 1) * 15F) & 0x0F)); } } } diff --git a/src/ImageSharp/PixelFormats/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/NormalizedByte2.cs index 387cb6f41..992986f92 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte2.cs @@ -137,8 +137,8 @@ namespace ImageSharp.PixelFormats public void ToRgb24(ref Rgb24 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; dest.B = 0; } @@ -147,8 +147,8 @@ namespace ImageSharp.PixelFormats public void ToRgba32(ref Rgba32 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; dest.B = 0; dest.A = 255; } @@ -158,8 +158,8 @@ namespace ImageSharp.PixelFormats public void ToBgr24(ref Bgr24 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; dest.B = 0; } @@ -168,8 +168,8 @@ namespace ImageSharp.PixelFormats public void ToBgra32(ref Bgra32 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; dest.B = 0; dest.A = 255; } diff --git a/src/ImageSharp/PixelFormats/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/NormalizedByte4.cs index 90657c3ac..99f603f69 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte4.cs @@ -130,9 +130,9 @@ namespace ImageSharp.PixelFormats public void ToRgb24(ref Rgb24 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); - dest.B = (byte)MathF.Round(vector.Z); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// @@ -140,10 +140,10 @@ namespace ImageSharp.PixelFormats public void ToRgba32(ref Rgba32 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); - dest.B = (byte)MathF.Round(vector.Z); - dest.A = (byte)MathF.Round(vector.W); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// @@ -151,9 +151,9 @@ namespace ImageSharp.PixelFormats public void ToBgr24(ref Bgr24 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); - dest.B = (byte)MathF.Round(vector.Z); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; } /// @@ -161,10 +161,10 @@ namespace ImageSharp.PixelFormats public void ToBgra32(ref Bgra32 dest) { Vector4 vector = this.ToScaledVector4(); - dest.R = (byte)MathF.Round(vector.X); - dest.G = (byte)MathF.Round(vector.Y); - dest.B = (byte)MathF.Round(vector.Z); - dest.A = (byte)MathF.Round(vector.W); + dest.R = (byte)vector.X; + dest.G = (byte)vector.Y; + dest.B = (byte)vector.Z; + dest.A = (byte)vector.W; } /// diff --git a/src/ImageSharp/PixelFormats/Rgb24.cs b/src/ImageSharp/PixelFormats/Rgb24.cs index 47dd96055..b8cc8dc24 100644 --- a/src/ImageSharp/PixelFormats/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/Rgb24.cs @@ -1,3 +1,8 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + namespace ImageSharp.PixelFormats { using System; diff --git a/src/Shared/stylecop.json b/src/Shared/stylecop.json index 4f8205d06..df8f120a5 100644 --- a/src/Shared/stylecop.json +++ b/src/Shared/stylecop.json @@ -4,12 +4,6 @@ "documentationRules": { "companyName": "James Jackson-South", "copyrightText": "Copyright (c) James Jackson-South and contributors.\nLicensed under the Apache License, Version 2.0." - //, - //"documentInterfaces": false, - //"documentInternalElements": false, - //"documentExposedElements": false, - //"documentPrivateElements": false, - //"documentPrivateFields": false } } } \ No newline at end of file From e15ad961c07feb78e84159ffcb9e6aeb4d2eb55a Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 5 Jun 2017 05:00:13 +0200 Subject: [PATCH 15/16] headers in T4 and generated .cs --- .../PixelOperations{TPixel}.Generated.cs | 5 +++++ .../PixelOperations{TPixel}.Generated.tt | 13 ++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs index 6ae52351e..c042d7678 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs @@ -1,5 +1,10 @@ // +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + namespace ImageSharp.PixelFormats { using System; diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt index edb74bb0c..9cff31936 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt @@ -1,4 +1,10 @@ -<#@ template debug="false" hostspecific="false" language="C#" #> +<# +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// +#> +<#@ template debug="false" hostspecific="false" language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> @@ -92,6 +98,11 @@ #> // +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + namespace ImageSharp.PixelFormats { using System; From 2cf4b328ab17a6ce0bea5f46eec1a4a86df9e693 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 5 Jun 2017 23:46:49 +0200 Subject: [PATCH 16/16] T4 Rgba32.PixelOperations --- src/ImageSharp/ImageSharp.csproj | 13 +- .../PixelOperations{TPixel}.Generated.cs | 0 .../PixelOperations{TPixel}.Generated.tt | 3 +- .../Rgba32.PixelOperations.Generated.cs | 130 ++++++++++++++++++ .../Rgba32.PixelOperations.Generated.tt | 99 +++++++++++++ .../PixelFormats/Rgba32.PixelOperations.cs | 104 +------------- 6 files changed, 242 insertions(+), 107 deletions(-) rename src/ImageSharp/PixelFormats/{ => Generated}/PixelOperations{TPixel}.Generated.cs (100%) rename src/ImageSharp/PixelFormats/{ => Generated}/PixelOperations{TPixel}.Generated.tt (99%) create mode 100644 src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs create mode 100644 src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 60f88a79c..17f7bf58f 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -55,10 +55,14 @@ TextTemplatingFileGenerator Block8x8F.Generated.cs - + TextTemplatingFileGenerator PixelOperations{TPixel}.Generated.cs + + TextTemplatingFileGenerator + Rgba32.PixelOperations.Generated.cs + @@ -69,10 +73,15 @@ True Block8x8F.Generated.tt - + True True PixelOperations{TPixel}.Generated.tt + + True + True + Rgba32.PixelOperations.Generated.tt + \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs similarity index 100% rename from src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs rename to src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt similarity index 99% rename from src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt rename to src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt index 9cff31936..16292489f 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt +++ b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt @@ -10,8 +10,7 @@ <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ output extension=".cs" #> -<# - +<# void GenerateToDestFormatMethods(string pixelType) { #> diff --git a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs new file mode 100644 index 000000000..e42c575d8 --- /dev/null +++ b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs @@ -0,0 +1,130 @@ +// + +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System; + using System.Numerics; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + + using ImageSharp.Memory; + using ImageSharp.PixelFormats; + + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Rgba32 + { + internal partial class PixelOperations : PixelOperations + { + + /// + internal override void PackFromRgb24(Span source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference(); + ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i); + ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); + Unsafe.As(ref dp) = sp; dp.A = 255; + } + } + + + /// + internal override void ToRgb24(Span sourcePixels, Span dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Rgb24 destRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); + ref Rgb24 dp = ref Unsafe.Add(ref destRef, i); + dp = Unsafe.As(ref sp); + } + } + + + /// + internal override void PackFromBgr24(Span source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); + ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); + ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); + dp.Bgr = sp; dp.A = 255; + } + } + + + /// + internal override void ToBgr24(Span sourcePixels, Span dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Bgr24 destRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); + ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); + dp = sp.Bgr; + } + } + + + /// + internal override void PackFromBgra32(Span source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); + ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i); + ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); + dp = sp.ToRgba32(); + } + } + + + /// + internal override void ToBgra32(Span sourcePixels, Span dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); + ref Bgra32 destRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); + ref Bgra32 dp = ref Unsafe.Add(ref destRef, i); + dp = sp.ToBgra32(); + } + } + + + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt new file mode 100644 index 000000000..9c01fa915 --- /dev/null +++ b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt @@ -0,0 +1,99 @@ +<# +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// +#> +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +<# + + void GeneratePackFromMethod(string pixelType, string converterCode) + { + #> + + /// + internal override void PackFrom<#=pixelType#>(Span<<#=pixelType#>> source, Span destPixels, int count) + { + GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); + + ref <#=pixelType#> sourceRef = ref source.DangerousGetPinnableReference(); + ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref <#=pixelType#> sp = ref Unsafe.Add(ref sourceRef, i); + ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); + <#=converterCode#> + } + } + + <# + } + + void GenerateConvertToMethod(string pixelType, string converterCode) + { + #> + + /// + internal override void To<#=pixelType#>(Span sourcePixels, Span<<#=pixelType#>> dest, int count) + { + GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); + + ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); + ref <#=pixelType#> destRef = ref dest.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); + ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i); + <#=converterCode#> + } + } + + <# + } + +#> +// + +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System; + using System.Numerics; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + + using ImageSharp.Memory; + using ImageSharp.PixelFormats; + + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Rgba32 + { + internal partial class PixelOperations : PixelOperations + { + <# + GeneratePackFromMethod("Rgb24", "Unsafe.As(ref dp) = sp; dp.A = 255;"); + GenerateConvertToMethod("Rgb24", "dp = Unsafe.As(ref sp);"); + + GeneratePackFromMethod("Bgr24", "dp.Bgr = sp; dp.A = 255;"); + GenerateConvertToMethod("Bgr24", "dp = sp.Bgr;"); + + GeneratePackFromMethod("Bgra32", "dp = sp.ToRgba32();"); + GenerateConvertToMethod("Bgra32", "dp = sp.ToBgra32();"); + #> + + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs index f10f0ba27..63e40e9cf 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs @@ -21,7 +21,7 @@ namespace ImageSharp /// /// implementation optimized for . /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { /// /// SIMD optimized bulk implementation of @@ -120,43 +120,6 @@ namespace ImageSharp } } - /// - internal override void PackFromRgb24(Span source, Span destPixels, int count) - { - Guard.MustBeSizedAtLeast(source, count, nameof(source)); - Guard.MustBeSizedAtLeast(destPixels, count, nameof(destPixels)); - - ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference(); - ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); - - Unsafe.As(ref dp) = sp; - dp.A = 255; - } - } - - /// - internal override void ToRgb24(Span sourcePixels, Span dest, int count) - { - Guard.MustBeSizedAtLeast(sourcePixels, count, nameof(sourcePixels)); - Guard.MustBeSizedAtLeast(dest, count, nameof(dest)); - - ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); - ref Rgb24 destRef = ref dest.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgb24 dp = ref Unsafe.Add(ref destRef, i); - - dp = Unsafe.As(ref sp); - } - } - /// internal override void PackFromRgba32(Span source, Span destPixels, int count) { @@ -173,71 +136,6 @@ namespace ImageSharp SpanHelper.Copy(sourcePixels, dest, count); } - /// - internal override void PackFromBgr24(Span source, Span destPixels, int count) - { - GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - - ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); - ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); - dp.Bgr = sp; - dp.A = 255; - } - } - - /// - internal override void ToBgr24(Span sourcePixels, Span dest, int count) - { - GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - - ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); - ref Bgr24 destRef = ref dest.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); - dp = sp.Bgr; - } - } - - /// - internal override void PackFromBgra32(Span source, Span destPixels, int count) - { - GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - - ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); - ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); - dp = sp.ToRgba32(); - } - } - - /// - internal override void ToBgra32(Span sourcePixels, Span dest, int count) - { - GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - - ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); - ref Bgra32 destRef = ref dest.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Bgra32 dp = ref Unsafe.Add(ref destRef, i); - dp = sp.ToBgra32(); - } - } - /// /// Value type to store -s unpacked into multiple -s. ///