diff --git a/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs b/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs index 2336dbee74..55a94fc81e 100644 --- a/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs +++ b/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs @@ -12,7 +12,9 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils /// /// Implementations are based on ideas in: /// https://github.com/dotnet/coreclr/blob/master/src/System.Private.CoreLib/shared/System/Buffers/Binary/Reader.cs#L84 - /// The JIT should be able to detect and optimize ROL and ROR patterns. + /// The JIT can detect and optimize rotation idioms ROTL (Rotate Left) + /// and ROTR (Rotate Right) emitting efficient CPU instructions: + /// https://github.com/dotnet/coreclr/pull/1830 /// internal static class PixelConverter { @@ -25,7 +27,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils public static uint ToArgb32(uint packedRgba) { // packedRgba = [aa bb gg rr] - // ROL(8, packedRgba) = [bb gg rr aa] + // ROTL(8, packedRgba) = [bb gg rr aa] return (packedRgba << 8) | (packedRgba >> 24); } @@ -38,7 +40,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils // packedRgba = [aa bb gg rr] // tmp1 = [aa 00 gg 00] // tmp2 = [00 bb 00 rr] - // tmp3=ROL(16, tmp2) = [00 rr 00 bb] + // tmp3=ROTL(16, tmp2) = [00 rr 00 bb] // tmp1 + tmp3 = [aa rr gg bb] uint tmp1 = packedRgba & 0xFF00FF00; uint tmp2 = packedRgba & 0x00FF00FF; @@ -56,7 +58,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils public static uint ToRgba32(uint packedArgb) { // packedArgb = [bb gg rr aa] - // ROR(8, packedArgb) = [aa bb gg rr] + // ROTR(8, packedArgb) = [aa bb gg rr] return (packedArgb >> 8) | (packedArgb << 24); } @@ -94,7 +96,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils // packedRgba = [aa rr gg bb] // tmp1 = [aa 00 gg 00] // tmp2 = [00 rr 00 bb] - // tmp3=ROL(16, tmp2) = [00 bb 00 rr] + // tmp3=ROTL(16, tmp2) = [00 bb 00 rr] // tmp1 + tmp3 = [aa bb gg rr] uint tmp1 = packedBgra & 0xFF00FF00; uint tmp2 = packedBgra & 0x00FF00FF; diff --git a/src/ImageSharp/PixelFormats/Utils/PixelExtensions.cs b/src/ImageSharp/PixelFormats/Utils/PixelExtensions.cs deleted file mode 100644 index 2284b8fc27..0000000000 --- a/src/ImageSharp/PixelFormats/Utils/PixelExtensions.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.PixelFormats.Utils -{ - /// - /// Low-performance extension methods to help conversion syntax, suitable for testing purposes. - /// - internal static class PixelExtensions - { - /// - /// Returns the result of as a new instance. - /// - public static Rgba32 ToRgba32(this TPixel pixel) - where TPixel : struct, IPixel - { - Rgba32 result = default; - pixel.ToRgba32(ref result); - return result; - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs index 9121649f48..556ec9c9ca 100644 --- a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs @@ -328,7 +328,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing TPixel color = colors[stopColorCodes[i % colors.Length]]; float position = stopPositions[i]; colorStops[i] = new ColorStop(position, color); - coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", color.ToRgba32().ToHex(), position); + Rgba32 rgba = default; + color.ToRgba32(ref rgba); + coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", rgba.ToHex(), position); } FormattableString variant = $"({startX},{startY})_TO_({endX},{endY})__[{coloringVariant}]"; diff --git a/tests/ImageSharp.Tests/PixelFormats/Alpha8Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Alpha8Tests.cs index 148b928fac..8f68c9d03f 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Alpha8Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Alpha8Tests.cs @@ -90,7 +90,8 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats var input = new Alpha8(128); var expected = new Rgba32(0, 0, 0, 128); - var actual = input.ToRgba32(); + Rgba32 actual = default; + input.ToRgba32(ref actual); Assert.Equal(expected, actual); } } diff --git a/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs index 220ca2899a..cb19c031d0 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs @@ -117,7 +117,8 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats var gray = new Gray16(input); // Act - var actual = gray.ToRgba32(); + Rgba32 actual = default; + gray.ToRgba32(ref actual); // Assert Assert.Equal(expected, actual.R); diff --git a/tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs index 988002c099..6a7b20cbed 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs @@ -115,10 +115,11 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats var gray = new Gray8(input); // Act - var actual = gray.ToRgba32(); + Rgba32 actual = default; + gray.ToRgba32(ref actual); // Assert - Assert.Equal(input, actual.R); + Assert.Equal(input, actual.R); Assert.Equal(input, actual.G); Assert.Equal(input, actual.B); Assert.Equal(byte.MaxValue, actual.A); diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs index a60509146d..92e8d302d4 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs @@ -104,7 +104,8 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats public void ToRgba32() { var rgb = new Rgb24(1, 2, 3); - var rgba = rgb.ToRgba32(); + Rgba32 rgba = default; + rgb.ToRgba32(ref rgba); Assert.Equal(new Rgba32(1, 2, 3, 255), rgba); } diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgb48Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgb48Tests.cs index a7f0e5edfc..d30e498609 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgb48Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgb48Tests.cs @@ -52,7 +52,8 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats var expected = new Rgba32(20, 38, 76, 255); // act - var actual = rgba48.ToRgba32(); + Rgba32 actual = default; + rgba48.ToRgba32(ref actual); // assert Assert.Equal(expected, actual); diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs index ad7df30769..a897dd4cdb 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs @@ -79,7 +79,8 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats var expected = new Rgba32(25, 0, 128, 0); // act - var actual = rgba.ToRgba32(); + Rgba32 actual = default; + rgba.ToRgba32(ref actual); // assert Assert.Equal(expected, actual); diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs index 564c26b8b1..3e5d7a56ed 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs @@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats var expected = new Rgba32(20, 38, 76, 115); // act - actual = rgba64.ToRgba32(); + rgba64.ToRgba32(ref actual); // assert Assert.Equal(expected, actual); diff --git a/tests/ImageSharp.Tests/PixelFormats/Short2Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Short2Tests.cs index 725e1a0d14..c9a3b33c9a 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Short2Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Short2Tests.cs @@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats var expected = new Rgba32(128, 127, 0, 255); // act - actual = short2.ToRgba32(); + short2.ToRgba32(ref actual); // assert Assert.Equal(expected, actual); @@ -104,7 +104,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // act short2.FromRgba32(expected); - actual = short2.ToRgba32(); + short2.ToRgba32(ref actual); // assert Assert.Equal(expected, actual); diff --git a/tests/ImageSharp.Tests/PixelFormats/Short4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Short4Tests.cs index b19917f34a..247342a053 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Short4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Short4Tests.cs @@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats var expected = new Rgba32(172, 177, 243, 128); // act - actual = shortValue.ToRgba32(); + shortValue.ToRgba32(ref actual); // assert Assert.Equal(expected, actual); @@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // act short4.FromRgba32(expected); - actual = short4.ToRgba32(); + short4.ToRgba32(ref actual); // assert Assert.Equal(expected, actual); @@ -124,7 +124,9 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // act short4.FromBgra32(expected); - actual.FromRgba32(short4.ToRgba32()); + Rgba32 temp = default; + short4.ToRgba32(ref temp); + actual.FromRgba32(temp); // assert Assert.Equal(expected, actual); @@ -140,7 +142,9 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // act short4.FromArgb32(expected); - actual.FromRgba32(short4.ToRgba32()); + Rgba32 temp = default; + short4.ToRgba32(ref temp); + actual.FromRgba32(temp); // assert Assert.Equal(expected, actual); diff --git a/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs b/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs index 29c97ce35f..bd8c647421 100644 --- a/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs @@ -84,8 +84,10 @@ namespace SixLabors.ImageSharp.Tests.Colors var color = new Rgba32(24, 48, 96, 192); var colorVector = new RgbaVector(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F); - var rgba = color.ToRgba32(); - var rgbaVector = colorVector.ToRgba32(); + Rgba32 rgba = default; + Rgba32 rgbaVector = default; + color.ToRgba32(ref rgba); + colorVector.ToRgba32(ref rgbaVector); Assert.Equal(rgba, rgbaVector); } diff --git a/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs b/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs index fa855aef77..577dc83c53 100644 --- a/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs +++ b/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs @@ -106,9 +106,10 @@ namespace SixLabors.ImageSharp.Tests { // Transparent pixels are much more likely to be found at the end of a palette int index = -1; + Rgba32 trans = default; for (int i = quantized.Palette.Length - 1; i >= 0; i--) { - var trans = quantized.Palette[i].ToRgba32(); + quantized.Palette[i].ToRgba32(ref trans); if (trans.Equals(default)) { diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs index e6a5ffc84b..d7755ff7a4 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs @@ -80,8 +80,11 @@ namespace SixLabors.ImageSharp.Tests } else { - rgb1 = ca.ToRgba32().Rgb; - rgb2 = cb.ToRgba32().Rgb; + Rgba32 rgba = default; + ca.ToRgba32(ref rgba); + rgb1 = rgba.Rgb; + cb.ToRgba32(ref rgba); + rgb2 = rgba.Rgb; if (!rgb1.Equals(rgb2)) { diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs index 1d284af15e..a8140e39d4 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -275,11 +275,12 @@ namespace SixLabors.ImageSharp.Tests Assert.Equal(20, img.Height); Buffer2D pixels = img.GetRootFramePixelBuffer(); + Rgba32 rgba = default; for (int y = 0; y < pixels.Height; y++) { for (int x = 0; x < pixels.Width; x++) { - var rgba = pixels[x, y].ToRgba32(); + pixels[x, y].ToRgba32(ref rgba); Assert.Equal(255, rgba.R); Assert.Equal(100, rgba.G);