From ca60ecf7f4564af0fafdbde62759a39d60a01a06 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 23 Oct 2018 01:11:14 +0200 Subject: [PATCH 01/17] pass Configuration to Vector4 converters in PixelOperations --- .../Processing/BrushApplicator.cs | 2 +- .../Processing/ImageBrush{TPixel}.cs | 7 +- .../Processing/PatternBrush{TPixel}.cs | 7 +- .../Processors/Drawing/DrawImageProcessor.cs | 4 +- .../Processing/RecolorBrush{TPixel}.cs | 7 +- .../Processing/SolidBrush{TPixel}.cs | 10 ++- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 17 ++-- .../Decoder/JpegImagePostProcessor.cs | 12 ++- .../Formats/Jpeg/JpegDecoderCore.cs | 2 +- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 3 +- src/ImageSharp/ImageFrame{TPixel}.cs | 16 ++-- .../PixelFormats/PixelBlender{TPixel}.cs | 81 ++++++++++++++----- .../Rgba32.PixelOperations.cs | 20 +++-- .../RgbaVector.PixelOperations.cs | 9 ++- .../PixelFormats/PixelOperations{TPixel}.cs | 28 ++++++- .../Convolution/Convolution2DProcessor.cs | 4 +- .../Convolution/Convolution2PassProcessor.cs | 4 +- .../Convolution/ConvolutionProcessor.cs | 4 +- .../Dithering/PaletteDitherProcessorBase.cs | 19 ++++- .../Overlays/BackgroundColorProcessor.cs | 2 +- .../Processors/Overlays/GlowProcessor.cs | 2 +- .../Processors/Overlays/VignetteProcessor.cs | 2 +- .../FrameQuantizerBase{TPixel}.cs | 4 +- .../Processors/Quantization/IQuantizer.cs | 6 +- .../Quantization/OctreeQuantizer.cs | 5 +- .../PaletteFrameQuantizer{TPixel}.cs | 5 +- .../Quantization/PaletteQuantizer.cs | 15 ++-- .../Quantization/QuantizeProcessor.cs | 2 +- .../Processors/Quantization/WuQuantizer.cs | 5 +- .../Processors/Transforms/ResizeProcessor.cs | 4 +- .../Color/Bulk/FromVector4.cs | 10 ++- .../Color/Bulk/ToVector4.cs | 25 +++--- .../PixelBlenders/PorterDuffBulkVsPixel.cs | 8 +- .../Jpg/JpegImagePostProcessorTests.cs | 4 +- .../PorterDuffFunctionsTests_TPixel.cs | 20 ++--- .../PixelFormats/PixelOperationsTests.cs | 15 ++-- .../Quantization/QuantizedImageTests.cs | 25 ++++-- .../TestUtilities/TestImageExtensions.cs | 36 +++++---- 38 files changed, 301 insertions(+), 150 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/BrushApplicator.cs b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs index 770d44065..0c6e0d3b4 100644 --- a/src/ImageSharp.Drawing/Processing/BrushApplicator.cs +++ b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs @@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing } Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); - this.Blender.Blend(memoryAllocator, destinationRow, destinationRow, overlaySpan, amountSpan); + this.Blender.Blend(this.Target.Configuration, destinationRow, destinationRow, overlaySpan, amountSpan); } } } diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs index c3f81868b..1ef4bb9ec 100644 --- a/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs @@ -140,7 +140,12 @@ namespace SixLabors.ImageSharp.Processing } Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); - this.Blender.Blend(this.source.MemoryAllocator, destinationRow, destinationRow, overlaySpan, amountSpan); + this.Blender.Blend( + this.source.Configuration, + destinationRow, + destinationRow, + overlaySpan, + amountSpan); } } } diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs index 2ce9a7ce5..46ed36f68 100644 --- a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs @@ -170,7 +170,12 @@ namespace SixLabors.ImageSharp.Processing } Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); - this.Blender.Blend(memoryAllocator, destinationRow, destinationRow, overlaySpan, amountSpan); + this.Blender.Blend( + this.Target.Configuration, + destinationRow, + destinationRow, + overlaySpan, + amountSpan); } } } diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs index dc73420f3..0957904c6 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs @@ -79,8 +79,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing int width = maxX - minX; - MemoryAllocator memoryAllocator = this.Image.GetConfiguration().MemoryAllocator; - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); ParallelHelper.IterateRows( @@ -93,7 +91,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing Span background = source.GetPixelRowSpan(y).Slice(minX, width); Span foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); - blender.Blend(memoryAllocator, background, background, foreground, this.Opacity); + blender.Blend(configuration, background, background, foreground, this.Opacity); } }); } diff --git a/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs index 2968b68b5..09a1ff71f 100644 --- a/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs @@ -158,7 +158,12 @@ namespace SixLabors.ImageSharp.Processing } Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); - this.Blender.Blend(memoryAllocator, destinationRow, destinationRow, overlaySpan, amountSpan); + this.Blender.Blend( + this.Target.Configuration, + destinationRow, + destinationRow, + overlaySpan, + amountSpan); } } } diff --git a/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs index 6b69c33f0..a77c6728b 100644 --- a/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs @@ -92,10 +92,11 @@ namespace SixLabors.ImageSharp.Processing Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); MemoryAllocator memoryAllocator = this.Target.MemoryAllocator; + Configuration configuration = this.Target.Configuration; if (this.Options.BlendPercentage == 1f) { - this.Blender.Blend(memoryAllocator, destinationRow, destinationRow, this.Colors.GetSpan(), scanline); + this.Blender.Blend(configuration, destinationRow, destinationRow, this.Colors.GetSpan(), scanline); } else { @@ -108,7 +109,12 @@ namespace SixLabors.ImageSharp.Processing amountSpan[i] = scanline[i] * this.Options.BlendPercentage; } - this.Blender.Blend(memoryAllocator, destinationRow, destinationRow, this.Colors.GetSpan(), amountSpan); + this.Blender.Blend( + configuration, + destinationRow, + destinationRow, + this.Colors.GetSpan(), + amountSpan); } } } diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 7db347aa6..81adf52dd 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -8,6 +8,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.MetaData; using SixLabors.ImageSharp.PixelFormats; @@ -88,7 +89,7 @@ namespace SixLabors.ImageSharp.Formats.Gif // Quantize the image returning a palette. QuantizedFrame quantized = - this.quantizer.CreateFrameQuantizer().QuantizeFrame(image.Frames.RootFrame); + this.quantizer.CreateFrameQuantizer(image.GetConfiguration()).QuantizeFrame(image.Frames.RootFrame); // Get the number of bits. this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length).Clamp(1, 8); @@ -151,7 +152,7 @@ namespace SixLabors.ImageSharp.Formats.Gif else { using (QuantizedFrame paletteQuantized - = palleteQuantizer.CreateFrameQuantizer(() => quantized.Palette).QuantizeFrame(frame)) + = palleteQuantizer.CreateFrameQuantizer(image.GetConfiguration(), () => quantized.Palette).QuantizeFrame(frame)) { this.WriteImageData(paletteQuantized, stream); } @@ -171,15 +172,17 @@ namespace SixLabors.ImageSharp.Formats.Gif if (quantized is null) { // Allow each frame to be encoded at whatever color depth the frame designates if set. - if (previousFrame != null - && previousMeta.ColorTableLength != frameMetaData.ColorTableLength - && frameMetaData.ColorTableLength > 0) + if (previousFrame != null && previousMeta.ColorTableLength != frameMetaData.ColorTableLength + && frameMetaData.ColorTableLength > 0) { - quantized = this.quantizer.CreateFrameQuantizer(frameMetaData.ColorTableLength).QuantizeFrame(frame); + quantized = this.quantizer.CreateFrameQuantizer( + image.GetConfiguration(), + frameMetaData.ColorTableLength).QuantizeFrame(frame); } else { - quantized = this.quantizer.CreateFrameQuantizer().QuantizeFrame(frame); + quantized = this.quantizer.CreateFrameQuantizer(image.GetConfiguration()) + .QuantizeFrame(frame); } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs index 6bd287732..1a6da2b2b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs @@ -26,6 +26,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// internal class JpegImagePostProcessor : IDisposable { + private readonly Configuration configuration; + /// /// The number of block rows to be processed in one Step. /// @@ -49,15 +51,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// /// Initializes a new instance of the class. /// - /// The to use for buffer allocations. + /// The to configure internal operations. /// The representing the uncompressed spectral Jpeg data - public JpegImagePostProcessor(MemoryAllocator memoryAllocator, IRawJpegData rawJpeg) + public JpegImagePostProcessor(Configuration configuration, IRawJpegData rawJpeg) { + this.configuration = configuration; this.RawJpeg = rawJpeg; IJpegComponent c0 = rawJpeg.Components.First(); this.NumberOfPostProcessorSteps = c0.SizeInBlocks.Height / BlockRowsPerStep; this.PostProcessorBufferSize = new Size(c0.SizeInBlocks.Width * 8, PixelRowsPerStep); + MemoryAllocator memoryAllocator = configuration.MemoryAllocator; this.ComponentProcessors = rawJpeg.Components.Select(c => new JpegComponentPostProcessor(memoryAllocator, this, c)).ToArray(); this.rgbaBuffer = memoryAllocator.Allocate(rawJpeg.ImageSizeInPixels.Width); this.colorConverter = JpegColorConverter.GetConverter(rawJpeg.ColorSpace); @@ -158,9 +162,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder this.colorConverter.ConvertToRgba(values, this.rgbaBuffer.GetSpan()); Span destRow = destination.GetPixelRowSpan(yy); - + // TODO: Investigate if slicing is actually necessary - PixelOperations.Instance.FromVector4(this.rgbaBuffer.GetSpan().Slice(0, destRow.Length), destRow); + PixelOperations.Instance.FromVector4(this.configuration, this.rgbaBuffer.GetSpan().Slice(0, destRow.Length), destRow); } } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 22d9cbdee..36246c682 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -936,7 +936,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg private Image PostProcessIntoImage() where TPixel : struct, IPixel { - using (var postProcessor = new JpegImagePostProcessor(this.configuration.MemoryAllocator, this)) + using (var postProcessor = new JpegImagePostProcessor(this.configuration, this)) { var image = new Image(this.configuration, this.ImageWidth, this.ImageHeight, this.MetaData); postProcessor.PostProcess(image.Frames.RootFrame); diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 84f7cb6cc..71945d130 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -237,7 +237,8 @@ namespace SixLabors.ImageSharp.Formats.Png } // Create quantized frame returning the palette and set the bit depth. - quantized = this.quantizer.CreateFrameQuantizer().QuantizeFrame(image.Frames.RootFrame); + quantized = this.quantizer.CreateFrameQuantizer(image.GetConfiguration()) + .QuantizeFrame(image.Frames.RootFrame); byte quantizedBits = (byte)ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length).Clamp(1, 8); bits = Math.Max(bits, quantizedBits); diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs index 25c517d44..bb95bb7b6 100644 --- a/src/ImageSharp/ImageFrame{TPixel}.cs +++ b/src/ImageSharp/ImageFrame{TPixel}.cs @@ -21,7 +21,6 @@ namespace SixLabors.ImageSharp public sealed class ImageFrame : IPixelSource, IDisposable where TPixel : struct, IPixel { - private readonly Configuration configuration; private bool isDisposed; /// @@ -84,7 +83,7 @@ namespace SixLabors.ImageSharp Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); - this.configuration = configuration; + this.Configuration = configuration; this.MemoryAllocator = configuration.MemoryAllocator; this.PixelBuffer = this.MemoryAllocator.Allocate2D(width, height); this.MetaData = metaData ?? new ImageFrameMetaData(); @@ -118,7 +117,7 @@ namespace SixLabors.ImageSharp Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.NotNull(metaData, nameof(metaData)); - this.configuration = configuration; + this.Configuration = configuration; this.MemoryAllocator = configuration.MemoryAllocator; this.PixelBuffer = new Buffer2D(memorySource, width, height); this.MetaData = metaData; @@ -134,7 +133,7 @@ namespace SixLabors.ImageSharp Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(source, nameof(source)); - this.configuration = configuration; + this.Configuration = configuration; this.MemoryAllocator = configuration.MemoryAllocator; this.PixelBuffer = this.MemoryAllocator.Allocate2D(source.PixelBuffer.Width, source.PixelBuffer.Height); source.PixelBuffer.GetSpan().CopyTo(this.PixelBuffer.GetSpan()); @@ -146,6 +145,11 @@ namespace SixLabors.ImageSharp /// public MemoryAllocator MemoryAllocator { get; } + /// + /// Gets the instance associated with this . + /// + internal Configuration Configuration { get; } + /// /// Gets the image pixels. Not private as Buffer2D requires an array in its constructor. /// @@ -254,7 +258,7 @@ namespace SixLabors.ImageSharp /// Clones the current instance. /// /// The - internal ImageFrame Clone() => this.Clone(this.configuration); + internal ImageFrame Clone() => this.Clone(this.Configuration); /// /// Clones the current instance. @@ -269,7 +273,7 @@ namespace SixLabors.ImageSharp /// The pixel format. /// The internal ImageFrame CloneAs() - where TPixel2 : struct, IPixel => this.CloneAs(this.configuration); + where TPixel2 : struct, IPixel => this.CloneAs(this.Configuration); /// /// Returns a copy of the image frame in the given pixel format. diff --git a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs index 6f0bba5cf..5c8e506ae 100644 --- a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs @@ -4,8 +4,8 @@ using System; using System.Buffers; using System.Numerics; + using SixLabors.ImageSharp.Memory; -using SixLabors.Memory; namespace SixLabors.ImageSharp.PixelFormats { @@ -38,7 +38,11 @@ namespace SixLabors.ImageSharp.PixelFormats /// A value between 0 and 1 indicating the weight of the second source vector. /// At amount = 0, "from" is returned, at amount = 1, "to" is returned. /// - protected abstract void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount); + protected abstract void BlendFunction( + Span destination, + ReadOnlySpan background, + ReadOnlySpan source, + float amount); /// /// Blend 2 rows together. @@ -50,12 +54,16 @@ namespace SixLabors.ImageSharp.PixelFormats /// A span with values between 0 and 1 indicating the weight of the second source vector. /// At amount = 0, "from" is returned, at amount = 1, "to" is returned. /// - protected abstract void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount); + protected abstract void BlendFunction( + Span destination, + ReadOnlySpan background, + ReadOnlySpan source, + ReadOnlySpan amount); /// /// Blends 2 rows together /// - /// memory manager to use internally + /// to use internally /// the destination span /// the background span /// the source span @@ -63,16 +71,21 @@ namespace SixLabors.ImageSharp.PixelFormats /// A span with values between 0 and 1 indicating the weight of the second source vector. /// At amount = 0, "from" is returned, at amount = 1, "to" is returned. /// - public void Blend(MemoryAllocator memoryManager, Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + public void Blend( + Configuration configuration, + Span destination, + ReadOnlySpan background, + ReadOnlySpan source, + ReadOnlySpan amount) { - this.Blend(memoryManager, destination, background, source, amount); + this.Blend(configuration, destination, background, source, amount); } /// /// Blends 2 rows together /// /// the pixel format of the source span - /// memory manager to use internally + /// to use internally /// the destination span /// the background span /// the source span @@ -80,25 +93,40 @@ namespace SixLabors.ImageSharp.PixelFormats /// A span with values between 0 and 1 indicating the weight of the second source vector. /// At amount = 0, "from" is returned, at amount = 1, "to" is returned. /// - public void Blend(MemoryAllocator memoryManager, Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + public void Blend( + Configuration configuration, + Span destination, + ReadOnlySpan background, + ReadOnlySpan source, + ReadOnlySpan amount) where TPixelSrc : struct, IPixel { Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); - using (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + using (IMemoryOwner buffer = + configuration.MemoryAllocator.Allocate(destination.Length * 3)) { Span destinationSpan = buffer.Slice(0, destination.Length); Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); - PixelOperations.Instance.ToScaledVector4(background.Slice(0, background.Length), backgroundSpan); - PixelOperations.Instance.ToScaledVector4(source.Slice(0, background.Length), sourceSpan); + PixelOperations.Instance.ToScaledVector4( + configuration, + background.Slice(0, background.Length), + backgroundSpan); + PixelOperations.Instance.ToScaledVector4( + configuration, + source.Slice(0, background.Length), + sourceSpan); this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); - PixelOperations.Instance.FromScaledVector4(destinationSpan.Slice(0, background.Length), destination); + PixelOperations.Instance.FromScaledVector4( + configuration, + destinationSpan.Slice(0, background.Length), + destination); } } @@ -106,7 +134,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Blends 2 rows together /// /// the pixel format of the source span - /// memory manager to use internally + /// to use internally /// the destination span /// the background span /// the source span @@ -114,26 +142,41 @@ namespace SixLabors.ImageSharp.PixelFormats /// A value between 0 and 1 indicating the weight of the second source vector. /// At amount = 0, "from" is returned, at amount = 1, "to" is returned. /// - public void Blend(MemoryAllocator memoryManager, Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + public void Blend( + Configuration configuration, + Span destination, + ReadOnlySpan background, + ReadOnlySpan source, + float amount) where TPixelSrc : struct, IPixel { Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); - using (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + using (IMemoryOwner buffer = + configuration.MemoryAllocator.Allocate(destination.Length * 3)) { Span destinationSpan = buffer.Slice(0, destination.Length); Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); - PixelOperations.Instance.ToScaledVector4(background.Slice(0, background.Length), backgroundSpan); - PixelOperations.Instance.ToScaledVector4(source.Slice(0, background.Length), sourceSpan); + PixelOperations.Instance.ToScaledVector4( + configuration, + background.Slice(0, background.Length), + backgroundSpan); + PixelOperations.Instance.ToScaledVector4( + configuration, + source.Slice(0, background.Length), + sourceSpan); this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); - PixelOperations.Instance.FromScaledVector4(destinationSpan.Slice(0, background.Length), destination); + PixelOperations.Instance.FromScaledVector4( + configuration, + destinationSpan.Slice(0, background.Length), + destination); } } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs index c25baa451..0f5ddf372 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs @@ -19,7 +19,10 @@ namespace SixLabors.ImageSharp.PixelFormats internal partial class PixelOperations : PixelOperations { /// - internal override void ToVector4(ReadOnlySpan sourceColors, Span destinationVectors) + internal override void ToVector4( + Configuration configuration, + ReadOnlySpan sourceColors, + Span destinationVectors) { Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors)); @@ -31,7 +34,10 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(ReadOnlySpan sourceVectors, Span destinationColors) + internal override void FromVector4( + Configuration configuration, + ReadOnlySpan sourceVectors, + Span destinationColors) { Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors)); @@ -43,17 +49,21 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToScaledVector4(ReadOnlySpan sourceColors, Span destinationVectors) + internal override void ToScaledVector4( + Configuration configuration, + ReadOnlySpan sourceColors, + Span destinationVectors) { - this.ToVector4(sourceColors, destinationVectors); + this.ToVector4(configuration, sourceColors, destinationVectors); } /// internal override void FromScaledVector4( + Configuration configuration, ReadOnlySpan sourceVectors, Span destinationColors) { - this.FromVector4(sourceVectors, destinationColors); + this.FromVector4(configuration, sourceVectors, destinationColors); } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs index d1f326365..cb12d944c 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs @@ -19,6 +19,7 @@ namespace SixLabors.ImageSharp.PixelFormats { /// internal override void FromScaledVector4( + Configuration configuration, ReadOnlySpan sourceVectors, Span destinationColors) { @@ -29,12 +30,16 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToScaledVector4( + Configuration configuration, ReadOnlySpan sourceColors, Span destinationVectors) - => this.ToVector4(sourceColors, destinationVectors); + => this.ToVector4(configuration, sourceColors, destinationVectors); /// - internal override void ToVector4(ReadOnlySpan sourceColors, Span destinationVectors) + internal override void ToVector4( + Configuration configuration, + ReadOnlySpan sourceColors, + Span destinationVectors) { Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors)); diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 510645c4e..8f3ea6c11 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -24,10 +24,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Bulk version of converting 'sourceVectors.Length' pixels into 'destinationColors'. /// + /// A to configure internal operations /// The to the source vectors. /// The to the destination colors. - internal virtual void FromVector4(ReadOnlySpan sourceVectors, Span destinationColors) + internal virtual void FromVector4( + Configuration configuration, + ReadOnlySpan sourceVectors, + Span destinationColors) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors)); ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); @@ -44,10 +49,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Bulk version of converting 'sourceColors.Length' pixels into 'destinationVectors'. /// + /// A to configure internal operations /// The to the source colors. /// The to the destination vectors. - internal virtual void ToVector4(ReadOnlySpan sourceColors, Span destinationVectors) + internal virtual void ToVector4( + Configuration configuration, + ReadOnlySpan sourceColors, + Span destinationVectors) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors)); ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors); @@ -64,10 +74,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Bulk version of converting 'sourceVectors.Length' pixels into 'destinationColors'. /// + /// A to configure internal operations /// The to the source vectors. /// The to the destination colors. - internal virtual void FromScaledVector4(ReadOnlySpan sourceVectors, Span destinationColors) + internal virtual void FromScaledVector4( + Configuration configuration, + ReadOnlySpan sourceVectors, + Span destinationColors) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors)); ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); @@ -84,10 +99,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Bulk version of converting 'sourceColors.Length' pixels into 'destinationVectors'. /// + /// A to configure internal operations /// The to the source colors. /// The to the destination vectors. - internal virtual void ToScaledVector4(ReadOnlySpan sourceColors, Span destinationVectors) + internal virtual void ToScaledVector4( + Configuration configuration, + ReadOnlySpan sourceColors, + Span destinationVectors) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors)); ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors); diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs index a26fe6bfd..bd1419e4b 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs @@ -75,14 +75,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution for (int y = rows.Min; y < rows.Max; y++) { Span targetRowSpan = targetPixels.GetRowSpan(y).Slice(startX); - PixelOperations.Instance.ToVector4(targetRowSpan.Slice(0, length), vectorSpan); + PixelOperations.Instance.ToVector4(configuration, targetRowSpan.Slice(0, length), vectorSpan); for (int x = 0; x < width; x++) { DenseMatrixUtils.Convolve2D(in matrixY, in matrixX, source.PixelBuffer, vectorSpan, y, x, maxY, maxX, startX); } - PixelOperations.Instance.FromVector4(vectorSpan.Slice(0, length), targetRowSpan); + PixelOperations.Instance.FromVector4(configuration, vectorSpan.Slice(0, length), targetRowSpan); } }); diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs index 98accb606..05007c370 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs @@ -93,14 +93,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution for (int y = rows.Min; y < rows.Max; y++) { Span targetRowSpan = targetPixels.GetRowSpan(y).Slice(startX); - PixelOperations.Instance.ToVector4(targetRowSpan.Slice(0, length), vectorSpan); + PixelOperations.Instance.ToVector4(configuration, targetRowSpan.Slice(0, length), vectorSpan); for (int x = 0; x < width; x++) { DenseMatrixUtils.Convolve(in matrix, sourcePixels, vectorSpan, y, x, maxY, maxX, startX); } - PixelOperations.Instance.FromVector4(vectorSpan.Slice(0, length), targetRowSpan); + PixelOperations.Instance.FromVector4(configuration, vectorSpan.Slice(0, length), targetRowSpan); } }); } diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs index dcecf2b82..8ef64bdac 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs @@ -59,14 +59,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution for (int y = rows.Min; y < rows.Max; y++) { Span targetRowSpan = targetPixels.GetRowSpan(y).Slice(startX); - PixelOperations.Instance.ToVector4(targetRowSpan.Slice(0, length), vectorSpan); + PixelOperations.Instance.ToVector4(configuration, targetRowSpan.Slice(0, length), vectorSpan); for (int x = 0; x < width; x++) { DenseMatrixUtils.Convolve(in matrix, source.PixelBuffer, vectorSpan, y, x, maxY, maxX, startX); } - PixelOperations.Instance.FromVector4(vectorSpan.Slice(0, length), targetRowSpan); + PixelOperations.Instance.FromVector4(configuration, vectorSpan.Slice(0, length), targetRowSpan); } }); diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs index fd9380109..f01865ec0 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Dithering { @@ -21,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// /// The vector representation of the image palette. /// - private readonly Vector4[] paletteVector; + private Vector4[] paletteVector; /// /// Initializes a new instance of the class. @@ -30,8 +31,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering protected PaletteDitherProcessorBase(TPixel[] palette) { this.Palette = palette ?? throw new ArgumentNullException(nameof(palette)); - this.paletteVector = new Vector4[this.Palette.Length]; - PixelOperations.Instance.ToScaledVector4(this.Palette, this.paletteVector); } /// @@ -40,7 +39,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering public TPixel[] Palette { get; } /// - /// Returns the two closest colors from the palette calcluated via Euclidean distance in the Rgba space. + /// Returns the two closest colors from the palette calculated via Euclidean distance in the Rgba space. /// /// The source color to match. /// The . @@ -90,5 +89,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering return pair; } + + protected override void BeforeFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + base.BeforeFrameApply(source, sourceRectangle, configuration); + + // Lazy init paletteVector: + if (this.paletteVector == null) + { + this.paletteVector = new Vector4[this.Palette.Length]; + PixelOperations.Instance.ToScaledVector4(configuration, this.Palette, this.paletteVector); + } + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs index 4adddd153..25787ff92 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs @@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays // This switched color & destination in the 2nd and 3rd places because we are applying the target color under the current one blender.Blend( - source.MemoryAllocator, + source.Configuration, destination, colors.GetSpan(), destination, diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs index 93d6edff1..21f6be69f 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs @@ -145,7 +145,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays Span destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width); this.blender.Blend( - source.MemoryAllocator, + source.Configuration, destination, destination, rowColors.GetSpan(), diff --git a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs index 52dade4ef..a8fa1d65c 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs @@ -147,7 +147,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays Span destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width); this.blender.Blend( - source.MemoryAllocator, + source.Configuration, destination, destination, rowColors.GetSpan(), diff --git a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs index bc0ed0eab..a41127bfc 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs @@ -17,6 +17,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization public abstract class FrameQuantizerBase : IFrameQuantizer where TPixel : struct, IPixel { + private readonly Configuration configuration; + /// /// A lookup table for colors /// @@ -79,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization // Collect the palette. Required before the second pass runs. TPixel[] palette = this.GetPalette(); this.paletteVector = new Vector4[palette.Length]; - PixelOperations.Instance.ToScaledVector4(palette, this.paletteVector); + PixelOperations.Instance.ToScaledVector4(image.Configuration, palette, this.paletteVector); var quantizedFrame = new QuantizedFrame(image.MemoryAllocator, width, height, palette); if (this.Dither) diff --git a/src/ImageSharp/Processing/Processors/Quantization/IQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/IQuantizer.cs index 3da09cde0..f1490a6d2 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/IQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/IQuantizer.cs @@ -19,18 +19,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Creates the generic frame quantizer /// + /// The to configure internal operations. /// The pixel format. /// The - IFrameQuantizer CreateFrameQuantizer() + IFrameQuantizer CreateFrameQuantizer(Configuration configuration) where TPixel : struct, IPixel; /// /// Creates the generic frame quantizer /// /// The pixel format. + /// The to configure internal operations. /// The maximum number of colors to hold in the color palette. /// The - IFrameQuantizer CreateFrameQuantizer(int maxColors) + IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors) where TPixel : struct, IPixel; } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer.cs index 22bb5223f..38962c768 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer.cs @@ -74,13 +74,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// public int MaxColors { get; } + /// /// - public IFrameQuantizer CreateFrameQuantizer() + public IFrameQuantizer CreateFrameQuantizer(Configuration configuration) where TPixel : struct, IPixel => new OctreeFrameQuantizer(this); /// - public IFrameQuantizer CreateFrameQuantizer(int maxColors) + public IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors) where TPixel : struct, IPixel { maxColors = maxColors.Clamp(1, DefaultMaxColors); diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs index 625400413..cab3af6de 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs @@ -31,9 +31,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Initializes a new instance of the class. /// + /// The to configure internal operations. /// The palette quantizer. /// An array of all colors in the palette. - public PaletteFrameQuantizer(PaletteQuantizer quantizer, TPixel[] colors) + public PaletteFrameQuantizer(Configuration configuration, PaletteQuantizer quantizer, TPixel[] colors) : base(quantizer, true) { // TODO: Why is this value constrained? Gif has limitations but theoretically @@ -41,7 +42,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization Guard.MustBeBetweenOrEqualTo(colors.Length, 1, 256, nameof(colors)); this.palette = colors; this.paletteVector = new Vector4[this.palette.Length]; - PixelOperations.Instance.ToScaledVector4(this.palette, this.paletteVector); + PixelOperations.Instance.ToScaledVector4(configuration, this.palette, this.paletteVector); } /// diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs index 27ef05dfe..361791253 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs @@ -43,12 +43,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization public IErrorDiffuser Diffuser { get; } /// - public virtual IFrameQuantizer CreateFrameQuantizer() + public virtual IFrameQuantizer CreateFrameQuantizer(Configuration configuration) where TPixel : struct, IPixel - => this.CreateFrameQuantizer(() => NamedColors.WebSafePalette); + => this.CreateFrameQuantizer(configuration, () => NamedColors.WebSafePalette); /// - public IFrameQuantizer CreateFrameQuantizer(int maxColors) + public IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors) where TPixel : struct, IPixel { TPixel[] websafe = NamedColors.WebSafePalette; @@ -56,21 +56,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization if (max != websafe.Length) { - return this.CreateFrameQuantizer(() => NamedColors.WebSafePalette.AsSpan(0, max).ToArray()); + return this.CreateFrameQuantizer(configuration, () => NamedColors.WebSafePalette.AsSpan(0, max).ToArray()); } - return this.CreateFrameQuantizer(() => websafe); + return this.CreateFrameQuantizer(configuration, () => websafe); } /// /// Gets the palette to use to quantize the image. /// /// The pixel format. + /// The to configure internal operations /// The method to return the palette. /// The - public IFrameQuantizer CreateFrameQuantizer(Func paletteFunction) + public IFrameQuantizer CreateFrameQuantizer(Configuration configuration, Func paletteFunction) where TPixel : struct, IPixel - => new PaletteFrameQuantizer(this, paletteFunction.Invoke()); + => new PaletteFrameQuantizer(configuration, this, paletteFunction.Invoke()); private static IErrorDiffuser GetDiffuser(bool dither) => dither ? KnownDiffusers.FloydSteinberg : null; } diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor.cs index bd5a6e9ec..8da89bf94 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor.cs @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { - IFrameQuantizer executor = this.Quantizer.CreateFrameQuantizer(); + IFrameQuantizer executor = this.Quantizer.CreateFrameQuantizer(configuration); using (QuantizedFrame quantized = executor.QuantizeFrame(source)) { int paletteCount = quantized.Palette.Length - 1; diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs index 5123e737d..4cd09a14f 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs @@ -73,13 +73,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// public int MaxColors { get; } + /// /// - public IFrameQuantizer CreateFrameQuantizer() + public IFrameQuantizer CreateFrameQuantizer(Configuration configuration) where TPixel : struct, IPixel => new WuFrameQuantizer(this); /// - public IFrameQuantizer CreateFrameQuantizer(int maxColors) + public IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors) where TPixel : struct, IPixel { maxColors = maxColors.Clamp(1, DefaultMaxColors); diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs index 05c4464f1..4d4ed06ce 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs @@ -257,7 +257,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms Span sourceRow = source.GetPixelRowSpan(y); Span tempRowSpan = tempRowBuffer.Span; - PixelOperations.Instance.ToVector4(sourceRow, tempRowSpan); + PixelOperations.Instance.ToVector4(configuration, sourceRow, tempRowSpan); Vector4Utils.Premultiply(tempRowSpan); ref Vector4 firstPassBaseRef = ref firstPassPixelsTransposed.Span[y]; @@ -309,7 +309,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } Span targetRowSpan = destination.GetPixelRowSpan(y); - PixelOperations.Instance.FromVector4(tempRowSpan, targetRowSpan); + PixelOperations.Instance.FromVector4(configuration, tempRowSpan, targetRowSpan); } }); } diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs index 1cd8c0196..2b9573ed7 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs @@ -24,6 +24,8 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk protected IMemoryOwner destination; + protected Configuration Configuration => Configuration.Default; + [Params( 64, 2048 @@ -33,8 +35,8 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk [GlobalSetup] public void Setup() { - this.destination = Configuration.Default.MemoryAllocator.Allocate(this.Count); - this.source = Configuration.Default.MemoryAllocator.Allocate(this.Count); + this.destination = this.Configuration.MemoryAllocator.Allocate(this.Count); + this.source = this.Configuration.MemoryAllocator.Allocate(this.Count); } [GlobalCleanup] @@ -59,13 +61,13 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk [Benchmark] public void PixelOperations_Base() { - new PixelOperations().FromVector4(this.source.GetSpan(), this.destination.GetSpan()); + new PixelOperations().FromVector4(this.Configuration, this.source.GetSpan(), this.destination.GetSpan()); } [Benchmark] public void PixelOperations_Specialized() { - PixelOperations.Instance.FromVector4(this.source.GetSpan(), this.destination.GetSpan()); + PixelOperations.Instance.FromVector4(this.Configuration, this.source.GetSpan(), this.destination.GetSpan()); } } diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs index e313953a6..f0fee649a 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs @@ -10,10 +10,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Attributes.Jobs; -using BenchmarkDotNet.Configs; -using BenchmarkDotNet.Environments; -using BenchmarkDotNet.Jobs; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -27,20 +23,21 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk protected IMemoryOwner destination; + protected Configuration Configuration => Configuration.Default; + [Params( - 64, + 64, //256, //512, //1024, - 2048 - )] + 2048)] public int Count { get; set; } [GlobalSetup] public void Setup() { - this.source = Configuration.Default.MemoryAllocator.Allocate(this.Count); - this.destination = Configuration.Default.MemoryAllocator.Allocate(this.Count); + this.source = this.Configuration.MemoryAllocator.Allocate(this.Count); + this.destination = this.Configuration.MemoryAllocator.Allocate(this.Count); } [GlobalCleanup] @@ -65,13 +62,19 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk [Benchmark] public void PixelOperations_Base() { - new PixelOperations().ToVector4(this.source.GetSpan(), this.destination.GetSpan()); + new PixelOperations().ToVector4( + this.Configuration, + this.source.GetSpan(), + this.destination.GetSpan()); } [Benchmark] public void PixelOperations_Specialized() { - PixelOperations.Instance.ToVector4(this.source.GetSpan(), this.destination.GetSpan()); + PixelOperations.Instance.ToVector4( + this.Configuration, + this.source.GetSpan(), + this.destination.GetSpan()); } } diff --git a/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs b/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs index 051646f90..cdd56fa07 100644 --- a/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs +++ b/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs @@ -17,6 +17,8 @@ namespace SixLabors.ImageSharp.Benchmarks public class PorterDuffBulkVsPixel : BenchmarkBase { + private Configuration Configuration => Configuration.Default; + private void BulkVectorConvert( Span destination, Span background, @@ -35,15 +37,15 @@ namespace SixLabors.ImageSharp.Benchmarks Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); - PixelOperations.Instance.ToVector4(background, backgroundSpan); - PixelOperations.Instance.ToVector4(source, sourceSpan); + PixelOperations.Instance.ToVector4(this.Configuration, background, backgroundSpan); + PixelOperations.Instance.ToVector4(this.Configuration, source, sourceSpan); for (int i = 0; i < destination.Length; i++) { destinationSpan[i] = PorterDuffFunctions.NormalSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } - PixelOperations.Instance.FromVector4(destinationSpan, destination); + PixelOperations.Instance.FromVector4(this.Configuration, destinationSpan, destination); } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs index cfa421a82..b3219115d 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs @@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { string imageFile = provider.SourceFileOrDescription; using (JpegDecoderCore decoder = JpegFixture.ParseJpegStream(imageFile)) - using (var pp = new JpegImagePostProcessor(Configuration.Default.MemoryAllocator, decoder)) + using (var pp = new JpegImagePostProcessor(Configuration.Default, decoder)) using (var imageFrame = new ImageFrame(Configuration.Default, decoder.ImageWidth, decoder.ImageHeight)) { pp.DoPostProcessorStep(imageFrame); @@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { string imageFile = provider.SourceFileOrDescription; using (JpegDecoderCore decoder = JpegFixture.ParseJpegStream(imageFile)) - using (var pp = new JpegImagePostProcessor(Configuration.Default.MemoryAllocator, decoder)) + using (var pp = new JpegImagePostProcessor(Configuration.Default, decoder)) using (var image = new Image(decoder.ImageWidth, decoder.ImageHeight)) { pp.PostProcess(image.Frames.RootFrame); diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTests_TPixel.cs b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTests_TPixel.cs index 3ea9bcad4..7de1cbb19 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTests_TPixel.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTests_TPixel.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders { new TestPixel(1,1,1,1), new TestPixel(0,0,0,.8f), .5f, new TestPixel(0.6f, 0.6f, 0.6f, 1) }, }; - private MemoryAllocator MemoryAllocator { get; } = Configuration.Default.MemoryAllocator; + private Configuration Configuration => Configuration.Default; [Theory] [MemberData(nameof(NormalBlendFunctionData))] @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { var dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.NormalSrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.NormalSrcOver().Blend(this.Configuration, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { var dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.MultiplySrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.MultiplySrcOver().Blend(this.Configuration, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -128,7 +128,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { var dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.AddSrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.AddSrcOver().Blend(this.Configuration, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -167,7 +167,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { var dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.SubtractSrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.SubtractSrcOver().Blend(this.Configuration, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -206,7 +206,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { var dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.ScreenSrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.ScreenSrcOver().Blend(this.Configuration, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -245,7 +245,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { var dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.DarkenSrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.DarkenSrcOver().Blend(this.Configuration, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -284,7 +284,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { var dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.LightenSrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.LightenSrcOver().Blend(this.Configuration, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -323,7 +323,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { var dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.OverlaySrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.OverlaySrcOver().Blend(this.Configuration, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -362,7 +362,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { var dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.HardLightSrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.HardLightSrcOver().Blend(this.Configuration, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs index 0082e6c0e..8314bd9b4 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs @@ -269,7 +269,10 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { this.Measure( times, - () => PixelOperations.Instance.ToVector4(source.GetSpan(), dest.GetSpan())); + () => PixelOperations.Instance.ToVector4( + this.Configuration, + source.GetSpan(), + dest.GetSpan())); } } } @@ -333,6 +336,8 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats public static TheoryData ArraySizesData => new TheoryData { 0, 1, 2, 7, 16, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 1111 }; + protected Configuration Configuration => Configuration.Default; + internal static PixelOperations Operations => PixelOperations.Instance; internal static TPixel[] CreateExpectedPixelData(Vector4[] source) @@ -367,7 +372,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromVector4(s, d.GetSpan()) + (s, d) => Operations.FromVector4(this.Configuration, s, d.GetSpan()) ); } @@ -381,7 +386,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromScaledVector4(s, d.GetSpan()) + (s, d) => Operations.FromScaledVector4(this.Configuration, s, d.GetSpan()) ); } @@ -417,7 +422,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToVector4(s, d.GetSpan()) + (s, d) => Operations.ToVector4(this.Configuration, s, d.GetSpan()) ); } @@ -431,7 +436,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToScaledVector4(s, d.GetSpan()) + (s, d) => Operations.ToScaledVector4(this.Configuration, s, d.GetSpan()) ); } diff --git a/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs b/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs index 719e9793a..fa855aef7 100644 --- a/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs +++ b/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs @@ -10,6 +10,8 @@ namespace SixLabors.ImageSharp.Tests { public class QuantizedImageTests { + private Configuration Configuration => Configuration.Default; + [Fact] public void QuantizersDitherByDefault() { @@ -21,15 +23,17 @@ namespace SixLabors.ImageSharp.Tests Assert.NotNull(octree.Diffuser); Assert.NotNull(wu.Diffuser); - Assert.True(palette.CreateFrameQuantizer().Dither); - Assert.True(octree.CreateFrameQuantizer().Dither); - Assert.True(wu.CreateFrameQuantizer().Dither); + Assert.True(palette.CreateFrameQuantizer(this.Configuration).Dither); + Assert.True(octree.CreateFrameQuantizer(this.Configuration).Dither); + Assert.True(wu.CreateFrameQuantizer(this.Configuration).Dither); } [Theory] [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32, true)] [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32, false)] - public void PaletteQuantizerYieldsCorrectTransparentPixel(TestImageProvider provider, bool dither) + public void PaletteQuantizerYieldsCorrectTransparentPixel( + TestImageProvider provider, + bool dither) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) @@ -40,7 +44,8 @@ namespace SixLabors.ImageSharp.Tests foreach (ImageFrame frame in image.Frames) { - QuantizedFrame quantized = quantizer.CreateFrameQuantizer().QuantizeFrame(frame); + QuantizedFrame quantized = + quantizer.CreateFrameQuantizer(this.Configuration).QuantizeFrame(frame); int index = this.GetTransparentIndex(quantized); Assert.Equal(index, quantized.GetPixelSpan()[0]); @@ -51,7 +56,9 @@ namespace SixLabors.ImageSharp.Tests [Theory] [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32, true)] [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32, false)] - public void OctreeQuantizerYieldsCorrectTransparentPixel(TestImageProvider provider, bool dither) + public void OctreeQuantizerYieldsCorrectTransparentPixel( + TestImageProvider provider, + bool dither) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) @@ -62,7 +69,8 @@ namespace SixLabors.ImageSharp.Tests foreach (ImageFrame frame in image.Frames) { - QuantizedFrame quantized = quantizer.CreateFrameQuantizer().QuantizeFrame(frame); + QuantizedFrame quantized = + quantizer.CreateFrameQuantizer(this.Configuration).QuantizeFrame(frame); int index = this.GetTransparentIndex(quantized); Assert.Equal(index, quantized.GetPixelSpan()[0]); @@ -84,7 +92,8 @@ namespace SixLabors.ImageSharp.Tests foreach (ImageFrame frame in image.Frames) { - QuantizedFrame quantized = quantizer.CreateFrameQuantizer().QuantizeFrame(frame); + QuantizedFrame quantized = + quantizer.CreateFrameQuantizer(this.Configuration).QuantizeFrame(frame); int index = this.GetTransparentIndex(quantized); Assert.Equal(index, quantized.GetPixelSpan()[0]); diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index f055ce548..29d39596b 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -30,27 +30,29 @@ namespace SixLabors.ImageSharp.Tests { MemoryAllocator memoryAllocator = ctx.MemoryAllocator; - ctx.Apply(img => - { - using (Buffer2D temp = memoryAllocator.Allocate2D(img.Width, img.Height)) - { - Span tempSpan = temp.GetSpan(); - foreach (ImageFrame frame in img.Frames) + ctx.Apply( + img => { - Span pixelSpan = frame.GetPixelSpan(); + Configuration configuration = img.GetConfiguration(); + using (Buffer2D temp = memoryAllocator.Allocate2D(img.Width, img.Height)) + { + Span tempSpan = temp.GetSpan(); + foreach (ImageFrame frame in img.Frames) + { + Span pixelSpan = frame.GetPixelSpan(); - PixelOperations.Instance.ToScaledVector4(pixelSpan, tempSpan); + PixelOperations.Instance.ToScaledVector4(configuration, pixelSpan, tempSpan); - for (int i = 0; i < tempSpan.Length; i++) - { - ref Vector4 v = ref tempSpan[i]; - v.W = 1F; - } + for (int i = 0; i < tempSpan.Length; i++) + { + ref Vector4 v = ref tempSpan[i]; + v.W = 1F; + } - PixelOperations.Instance.FromScaledVector4(tempSpan, pixelSpan); - } - } - }); + PixelOperations.Instance.FromScaledVector4(configuration, tempSpan, pixelSpan); + } + } + }); } public static Image DebugSave( From 53ac430e7e48ce2a4043ada85fac44a75a089567 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 23 Oct 2018 01:49:24 +0200 Subject: [PATCH 02/17] Feed Configuration to all methods in PixelOperations --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 12 +- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 17 +- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 18 +- .../Encoder/YCbCrForwardConverter{TPixel}.cs | 6 +- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 2 + src/ImageSharp/Formats/Png/PngEncoderCore.cs | 46 +++-- .../Formats/Png/PngScanlineProcessor.cs | 8 +- src/ImageSharp/ImageFrame{TPixel}.cs | 4 +- .../PixelFormats/NamedColors{TPixel}.cs | 6 +- .../Argb32.PixelOperations.Generated.cs | 20 +- .../Bgr24.PixelOperations.Generated.cs | 20 +- .../Bgra32.PixelOperations.Generated.cs | 20 +- .../Gray16.PixelOperations.Generated.cs | 20 +- .../Gray8.PixelOperations.Generated.cs | 20 +- .../Rgb24.PixelOperations.Generated.cs | 20 +- .../Rgb48.PixelOperations.Generated.cs | 20 +- .../Rgba32.PixelOperations.Generated.cs | 20 +- .../Rgba64.PixelOperations.Generated.cs | 20 +- .../Generated/_Common.ttinclude | 6 +- .../PixelOperations{TPixel}.Generated.cs | 180 +++++++++++------- .../PixelOperations{TPixel}.Generated.tt | 20 +- .../PixelFormats/PixelOperations{TPixel}.cs | 2 + .../Quantization/WuFrameQuantizer{TPixel}.cs | 2 +- .../Color/Bulk/FromRgba32Bytes.cs | 11 +- .../ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs | 21 +- .../Color/Bulk/ToXyzw.cs | 21 +- .../PixelFormats/PixelOperationsTests.cs | 44 ++--- .../ImageComparison/ExactImageComparer.cs | 5 +- .../ImageComparison/TolerantImageComparer.cs | 5 +- .../ReferenceCodecs/MagickReferenceDecoder.cs | 12 +- .../ReferenceCodecs/SystemDrawingBridge.cs | 23 ++- 31 files changed, 405 insertions(+), 246 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 77cd32222..cea90cb45 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -436,7 +436,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.stream.Read(row); int newY = Invert(y, height, inverted); Span pixelSpan = pixels.GetRowSpan(newY); - PixelOperations.Instance.FromBgr24Bytes(row.GetSpan(), pixelSpan, width); + PixelOperations.Instance.FromBgr24Bytes( + this.configuration, + row.GetSpan(), + pixelSpan, + width); } } } @@ -461,7 +465,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.stream.Read(row); int newY = Invert(y, height, inverted); Span pixelSpan = pixels.GetRowSpan(newY); - PixelOperations.Instance.FromBgra32Bytes(row.GetSpan(), pixelSpan, width); + PixelOperations.Instance.FromBgra32Bytes( + this.configuration, + row.GetSpan(), + pixelSpan, + width); } } } diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 186ff812f..a67c581eb 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -3,6 +3,8 @@ using System; using System.IO; + +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.MetaData; @@ -23,6 +25,8 @@ namespace SixLabors.ImageSharp.Formats.Bmp private readonly MemoryAllocator memoryAllocator; + private Configuration configuration; + private BmpBitsPerPixel? bitsPerPixel; /// @@ -48,6 +52,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp Guard.NotNull(image, nameof(image)); Guard.NotNull(stream, nameof(stream)); + this.configuration = image.GetConfiguration(); ImageMetaData metaData = image.MetaData; BmpMetaData bmpMetaData = metaData.GetFormatMetaData(BmpFormat.Instance); this.bitsPerPixel = this.bitsPerPixel ?? bmpMetaData.BitsPerPixel; @@ -163,7 +168,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp for (int y = pixels.Height - 1; y >= 0; y--) { Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.ToBgra32Bytes(pixelSpan, row.GetSpan(), pixelSpan.Length); + PixelOperations.Instance.ToBgra32Bytes( + this.configuration, + pixelSpan, + row.GetSpan(), + pixelSpan.Length); stream.Write(row.Array, 0, row.Length()); } } @@ -183,7 +192,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp for (int y = pixels.Height - 1; y >= 0; y--) { Span pixelSpan = pixels.GetRowSpan(y); - PixelOperations.Instance.ToBgr24Bytes(pixelSpan, row.GetSpan(), pixelSpan.Length); + PixelOperations.Instance.ToBgr24Bytes( + this.configuration, + pixelSpan, + row.GetSpan(), + pixelSpan.Length); stream.Write(row.Array, 0, row.Length()); } } diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 81adf52dd..d7e2e40e2 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -27,6 +27,11 @@ namespace SixLabors.ImageSharp.Formats.Gif /// private readonly MemoryAllocator memoryAllocator; + /// + /// Configuration bound to the encoding operation. + /// + private Configuration configuration; + /// /// A reusable buffer used to reduce allocations. /// @@ -82,6 +87,8 @@ namespace SixLabors.ImageSharp.Formats.Gif Guard.NotNull(image, nameof(image)); Guard.NotNull(stream, nameof(stream)); + this.configuration = image.GetConfiguration(); + ImageMetaData metaData = image.MetaData; this.gifMetaData = metaData.GetFormatMetaData(GifFormat.Instance); this.colorTableMode = this.colorTableMode ?? this.gifMetaData.ColorTableMode; @@ -220,7 +227,7 @@ namespace SixLabors.ImageSharp.Formats.Gif { Span rgbaSpan = rgbaBuffer.GetSpan(); ref Rgba32 paletteRef = ref MemoryMarshal.GetReference(rgbaSpan); - PixelOperations.Instance.ToRgba32(quantized.Palette, rgbaSpan); + PixelOperations.Instance.ToRgba32(this.configuration, quantized.Palette, rgbaSpan); for (int i = quantized.Palette.Length - 1; i >= 0; i--) { @@ -322,7 +329,8 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The stream to write to. private void WriteComments(ImageMetaData metadata, Stream stream) { - if (!metadata.TryGetProperty(GifConstants.Comments, out ImageProperty property) || string.IsNullOrEmpty(property.Value)) + if (!metadata.TryGetProperty(GifConstants.Comments, out ImageProperty property) + || string.IsNullOrEmpty(property.Value)) { return; } @@ -420,7 +428,11 @@ namespace SixLabors.ImageSharp.Formats.Gif using (IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength)) { - PixelOperations.Instance.ToRgb24Bytes(image.Palette.AsSpan(), colorTable.GetSpan(), pixelCount); + PixelOperations.Instance.ToRgb24Bytes( + this.configuration, + image.Palette.AsSpan(), + colorTable.GetSpan(), + pixelCount); stream.Write(colorTable.Array, 0, colorTableLength); } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs index b2a8fccf4..d775425c5 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs @@ -53,12 +53,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder /// /// Converts a 8x8 image area inside 'pixels' at position (x,y) placing the result members of the structure (, , ) /// - public void Convert(IPixelSource pixels, int x, int y) + public void Convert(ImageFrame frame, int x, int y) { - this.pixelBlock.LoadAndStretchEdges(pixels, x, y); + this.pixelBlock.LoadAndStretchEdges(frame, x, y); Span rgbSpan = this.rgbBlock.AsSpanUnsafe(); - PixelOperations.Instance.ToRgb24(this.pixelBlock.AsSpanUnsafe(), rgbSpan); + PixelOperations.Instance.ToRgb24(frame.Configuration, this.pixelBlock.AsSpanUnsafe(), rgbSpan); ref float yBlockStart = ref Unsafe.As(ref this.Y); ref float cbBlockStart = ref Unsafe.As(ref this.Cb); diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index d66ac6c0d..11c4d831b 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -702,6 +702,7 @@ namespace SixLabors.ImageSharp.Formats.Png case PngColorType.Rgb: PngScanlineProcessor.ProcessRgbScanline( + this.configuration, this.header, scanlineSpan, rowSpan, @@ -715,6 +716,7 @@ namespace SixLabors.ImageSharp.Formats.Png case PngColorType.RgbWithAlpha: PngScanlineProcessor.ProcessRgbaScanline( + this.configuration, this.header, scanlineSpan, rowSpan, diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 71945d130..7ae716aa0 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -43,6 +43,11 @@ namespace SixLabors.ImageSharp.Formats.Png /// private readonly MemoryAllocator memoryAllocator; + /// + /// The configuration instance for the decoding operation + /// + private Configuration configuration; + /// /// The maximum block size, defaults at 64k for uncompressed blocks. /// @@ -201,6 +206,7 @@ namespace SixLabors.ImageSharp.Formats.Png Guard.NotNull(image, nameof(image)); Guard.NotNull(stream, nameof(stream)); + this.configuration = image.GetConfiguration(); this.width = image.Width; this.height = image.Height; @@ -328,7 +334,7 @@ namespace SixLabors.ImageSharp.Formats.Png { Span luminanceSpan = luminanceBuffer.GetSpan(); ref Gray16 luminanceRef = ref MemoryMarshal.GetReference(luminanceSpan); - PixelOperations.Instance.ToGray16(rowSpan, luminanceSpan); + PixelOperations.Instance.ToGray16(this.configuration, rowSpan, luminanceSpan); // Can't map directly to byte array as it's big endian. for (int x = 0, o = 0; x < luminanceSpan.Length; x++, o += 2) @@ -343,19 +349,28 @@ namespace SixLabors.ImageSharp.Formats.Png if (this.bitDepth == 8) { // 8 bit grayscale - PixelOperations.Instance.ToGray8Bytes(rowSpan, rawScanlineSpan, rowSpan.Length); + PixelOperations.Instance.ToGray8Bytes( + this.configuration, + rowSpan, + rawScanlineSpan, + rowSpan.Length); } else { // 1, 2, and 4 bit grayscale - using (IManagedByteBuffer temp = this.memoryAllocator.AllocateManagedByteBuffer(rowSpan.Length, AllocationOptions.Clean)) + using (IManagedByteBuffer temp = this.memoryAllocator.AllocateManagedByteBuffer( + rowSpan.Length, + AllocationOptions.Clean)) { int scaleFactor = 255 / (ImageMaths.GetColorCountForBitDepth(this.bitDepth) - 1); Span tempSpan = temp.GetSpan(); - ref byte tempSpanRef = ref MemoryMarshal.GetReference(tempSpan); // We need to first create an array of luminance bytes then scale them down to the correct bit depth. - PixelOperations.Instance.ToGray8Bytes(rowSpan, tempSpan, rowSpan.Length); + PixelOperations.Instance.ToGray8Bytes( + this.configuration, + rowSpan, + tempSpan, + rowSpan.Length); this.ScaleDownFrom8BitArray(tempSpan, rawScanlineSpan, this.bitDepth, scaleFactor); } } @@ -371,7 +386,7 @@ namespace SixLabors.ImageSharp.Formats.Png { Span rgbaSpan = rgbaBuffer.GetSpan(); ref Rgba64 rgbaRef = ref MemoryMarshal.GetReference(rgbaSpan); - PixelOperations.Instance.ToRgba64(rowSpan, rgbaSpan); + PixelOperations.Instance.ToRgba64(this.configuration, rowSpan, rgbaSpan); // Can't map directly to byte array as it's big endian. for (int x = 0, o = 0; x < rgbaSpan.Length; x++, o += 4) @@ -391,7 +406,8 @@ namespace SixLabors.ImageSharp.Formats.Png for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 2) { Unsafe.Add(ref rowSpanRef, x).ToRgba32(ref rgba); - Unsafe.Add(ref rawScanlineSpanRef, o) = ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); + Unsafe.Add(ref rawScanlineSpanRef, o) = + ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); Unsafe.Add(ref rawScanlineSpanRef, o + 1) = rgba.A; } } @@ -413,14 +429,22 @@ namespace SixLabors.ImageSharp.Formats.Png case 4: { // 8 bit Rgba - PixelOperations.Instance.ToRgba32Bytes(rowSpan, rawScanlineSpan, this.width); + PixelOperations.Instance.ToRgba32Bytes( + this.configuration, + rowSpan, + rawScanlineSpan, + this.width); break; } case 3: { // 8 bit Rgb - PixelOperations.Instance.ToRgb24Bytes(rowSpan, rawScanlineSpan, this.width); + PixelOperations.Instance.ToRgb24Bytes( + this.configuration, + rowSpan, + rawScanlineSpan, + this.width); break; } @@ -431,7 +455,7 @@ namespace SixLabors.ImageSharp.Formats.Png { Span rgbaSpan = rgbaBuffer.GetSpan(); ref Rgba64 rgbaRef = ref MemoryMarshal.GetReference(rgbaSpan); - PixelOperations.Instance.ToRgba64(rowSpan, rgbaSpan); + PixelOperations.Instance.ToRgba64(this.configuration, rowSpan, rgbaSpan); // Can't map directly to byte array as it's big endian. for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 8) @@ -454,7 +478,7 @@ namespace SixLabors.ImageSharp.Formats.Png { Span rgbSpan = rgbBuffer.GetSpan(); ref Rgb48 rgbRef = ref MemoryMarshal.GetReference(rgbSpan); - PixelOperations.Instance.ToRgb48(rowSpan, rgbSpan); + PixelOperations.Instance.ToRgb48(this.configuration, rowSpan, rgbSpan); // Can't map directly to byte array as it's big endian. for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 6) diff --git a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs index e4a2562e6..3fe590ee2 100644 --- a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs +++ b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs @@ -11,6 +11,7 @@ namespace SixLabors.ImageSharp.Formats.Png { /// /// Provides methods to allow the decoding of raw scanlines to image rows of different pixel formats. + /// TODO: We should make this a stateful class or struct to reduce the number of arguments on methods (most are invariant). /// internal static class PngScanlineProcessor { @@ -346,6 +347,7 @@ namespace SixLabors.ImageSharp.Formats.Png } public static void ProcessRgbScanline( + Configuration configuration, in PngHeader header, ReadOnlySpan scanlineSpan, Span rowSpan, @@ -357,7 +359,6 @@ namespace SixLabors.ImageSharp.Formats.Png where TPixel : struct, IPixel { TPixel pixel = default; - ref byte scanlineSpanRef = ref MemoryMarshal.GetReference(scanlineSpan); ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan); if (!hasTrans) @@ -377,7 +378,7 @@ namespace SixLabors.ImageSharp.Formats.Png } else { - PixelOperations.Instance.FromRgb24Bytes(scanlineSpan, rowSpan, header.Width); + PixelOperations.Instance.FromRgb24Bytes(configuration, scanlineSpan, rowSpan, header.Width); } return; @@ -500,6 +501,7 @@ namespace SixLabors.ImageSharp.Formats.Png } public static void ProcessRgbaScanline( + Configuration configuration, in PngHeader header, ReadOnlySpan scanlineSpan, Span rowSpan, @@ -526,7 +528,7 @@ namespace SixLabors.ImageSharp.Formats.Png } else { - PixelOperations.Instance.FromRgba32Bytes(scanlineSpan, rowSpan, header.Width); + PixelOperations.Instance.FromRgba32Bytes(configuration, scanlineSpan, rowSpan, header.Width); } } diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs index bb95bb7b6..f69ae3757 100644 --- a/src/ImageSharp/ImageFrame{TPixel}.cs +++ b/src/ImageSharp/ImageFrame{TPixel}.cs @@ -252,7 +252,7 @@ namespace SixLabors.ImageSharp } /// - public override string ToString() => $"ImageFrame<{typeof(TPixel).Name}>: {this.Width}x{this.Height}"; + public override string ToString() => $"ImageFrame<{typeof(TPixel).Name}>({this.Width}x{this.Height})"; /// /// Clones the current instance. @@ -300,7 +300,7 @@ namespace SixLabors.ImageSharp { Span sourceRow = this.GetPixelRowSpan(y); Span targetRow = target.GetPixelRowSpan(y); - PixelOperations.Instance.To(sourceRow, targetRow); + PixelOperations.Instance.To(configuration, sourceRow, targetRow); } }); diff --git a/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs b/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs index 1923faa1f..08530c2bb 100644 --- a/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs @@ -739,7 +739,11 @@ namespace SixLabors.ImageSharp.PixelFormats var safe = new TPixel[constants.Length + 1]; Span constantsBytes = MemoryMarshal.Cast(constants.AsSpan()); - PixelOperations.Instance.FromRgba32Bytes(constantsBytes, safe, constants.Length); + PixelOperations.Instance.FromRgba32Bytes( + Configuration.Default, + constantsBytes, + safe, + constants.Length); return safe; } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs index 26e85e043..09f10716e 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.PixelFormats { /// - internal override void FromArgb32(ReadOnlySpan source, Span destPixels) + internal override void FromArgb32(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// - internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -107,7 +107,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs index 080a25429..f8c61e4fa 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.PixelFormats { /// - internal override void FromBgr24(ReadOnlySpan source, Span destPixels) + internal override void FromBgr24(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// - internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -107,7 +107,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs index 6a1bb6cdc..9bddd18e9 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.PixelFormats { /// - internal override void FromBgra32(ReadOnlySpan source, Span destPixels) + internal override void FromBgra32(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// - internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -107,7 +107,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs index cbb9df445..31c575534 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.PixelFormats { /// - internal override void FromGray16(ReadOnlySpan source, Span destPixels) + internal override void FromGray16(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// - internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -107,7 +107,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs index b88f18e8d..14a2c858c 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.PixelFormats { /// - internal override void FromGray8(ReadOnlySpan source, Span destPixels) + internal override void FromGray8(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// - internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -107,7 +107,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs index 49c56f4fa..f8b80020e 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.PixelFormats { /// - internal override void FromRgb24(ReadOnlySpan source, Span destPixels) + internal override void FromRgb24(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// - internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -107,7 +107,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs index cda6dbf72..5741b1070 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.PixelFormats { /// - internal override void FromRgb48(ReadOnlySpan source, Span destPixels) + internal override void FromRgb48(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// - internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -107,7 +107,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs index ab264f870..9f7b624c0 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.PixelFormats { /// - internal override void FromRgba32(ReadOnlySpan source, Span destPixels) + internal override void FromRgba32(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// - internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -107,7 +107,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs index 4bc6b101a..411178b82 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.PixelFormats { /// - internal override void FromRgba64(ReadOnlySpan source, Span destPixels) + internal override void FromRgba64(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// - internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -107,7 +107,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude index 176075a40..bc23edb01 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude @@ -19,7 +19,7 @@ using System.Runtime.InteropServices; #> /// - internal override void From<#=pixelType#>(ReadOnlySpan<<#=pixelType#>> source, Span<<#=pixelType#>> destPixels) + internal override void From<#=pixelType#>(Configuration configuration, ReadOnlySpan<<#=pixelType#>> source, Span<<#=pixelType#>> destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -27,7 +27,7 @@ using System.Runtime.InteropServices; } /// - internal override void To<#=pixelType#>(ReadOnlySpan<<#=pixelType#>> sourcePixels, Span<<#=pixelType#>> destPixels) + internal override void To<#=pixelType#>(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span<<#=pixelType#>> destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -42,7 +42,7 @@ using System.Runtime.InteropServices; #> /// - internal override void To<#=toPixelType#>(ReadOnlySpan<<#=fromPixelType#>> sourcePixels, Span<<#=toPixelType#>> destPixels) + internal override void To<#=toPixelType#>(Configuration configuration, ReadOnlySpan<<#=fromPixelType#>> sourcePixels, Span<<#=toPixelType#>> destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs index 07ecf8756..207a8767d 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs @@ -13,9 +13,10 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Converts all pixels in 'source` span of into a span of -s. /// + /// A to configure internal operations /// The source of data. /// The to the destination pixels. - internal virtual void FromArgb32(ReadOnlySpan source, Span destPixels) + internal virtual void FromArgb32(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -32,24 +33,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span. + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void FromArgb32Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) + internal void FromArgb32Bytes(Configuration configuration, ReadOnlySpan sourceBytes, Span destPixels, int count) { - this.FromArgb32(MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); + this.FromArgb32(configuration, MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); } /// /// Converts all pixels of the 'sourcePixels` span to a span of -s. /// + /// A to configure internal operations /// The span of source pixels /// The destination span of data. - internal virtual void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels) + internal virtual void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -66,24 +69,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span as destination. + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source pixels. /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToArgb32Bytes(ReadOnlySpan sourcePixels, Span destBytes, int count) + internal void ToArgb32Bytes(Configuration configuration, ReadOnlySpan sourcePixels, Span destBytes, int count) { - this.ToArgb32(sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); + this.ToArgb32(configuration, sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); } /// /// Converts all pixels in 'source` span of into a span of -s. /// + /// A to configure internal operations /// The source of data. /// The to the destination pixels. - internal virtual void FromBgr24(ReadOnlySpan source, Span destPixels) + internal virtual void FromBgr24(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -100,24 +105,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span. + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void FromBgr24Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) + internal void FromBgr24Bytes(Configuration configuration, ReadOnlySpan sourceBytes, Span destPixels, int count) { - this.FromBgr24(MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); + this.FromBgr24(configuration, MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); } /// /// Converts all pixels of the 'sourcePixels` span to a span of -s. /// + /// A to configure internal operations /// The span of source pixels /// The destination span of data. - internal virtual void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels) + internal virtual void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -134,24 +141,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span as destination. + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source pixels. /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToBgr24Bytes(ReadOnlySpan sourcePixels, Span destBytes, int count) + internal void ToBgr24Bytes(Configuration configuration, ReadOnlySpan sourcePixels, Span destBytes, int count) { - this.ToBgr24(sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); + this.ToBgr24(configuration, sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); } /// /// Converts all pixels in 'source` span of into a span of -s. /// + /// A to configure internal operations /// The source of data. /// The to the destination pixels. - internal virtual void FromBgra32(ReadOnlySpan source, Span destPixels) + internal virtual void FromBgra32(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -168,24 +177,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span. + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void FromBgra32Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) + internal void FromBgra32Bytes(Configuration configuration, ReadOnlySpan sourceBytes, Span destPixels, int count) { - this.FromBgra32(MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); + this.FromBgra32(configuration, MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); } /// /// Converts all pixels of the 'sourcePixels` span to a span of -s. /// + /// A to configure internal operations /// The span of source pixels /// The destination span of data. - internal virtual void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels) + internal virtual void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -202,24 +213,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span as destination. + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source pixels. /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToBgra32Bytes(ReadOnlySpan sourcePixels, Span destBytes, int count) + internal void ToBgra32Bytes(Configuration configuration, ReadOnlySpan sourcePixels, Span destBytes, int count) { - this.ToBgra32(sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); + this.ToBgra32(configuration, sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); } /// /// Converts all pixels in 'source` span of into a span of -s. /// + /// A to configure internal operations /// The source of data. /// The to the destination pixels. - internal virtual void FromGray8(ReadOnlySpan source, Span destPixels) + internal virtual void FromGray8(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -236,24 +249,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span. + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void FromGray8Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) + internal void FromGray8Bytes(Configuration configuration, ReadOnlySpan sourceBytes, Span destPixels, int count) { - this.FromGray8(MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); + this.FromGray8(configuration, MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); } /// /// Converts all pixels of the 'sourcePixels` span to a span of -s. /// + /// A to configure internal operations /// The span of source pixels /// The destination span of data. - internal virtual void ToGray8(ReadOnlySpan sourcePixels, Span destPixels) + internal virtual void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -270,24 +285,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span as destination. + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source pixels. /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToGray8Bytes(ReadOnlySpan sourcePixels, Span destBytes, int count) + internal void ToGray8Bytes(Configuration configuration, ReadOnlySpan sourcePixels, Span destBytes, int count) { - this.ToGray8(sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); + this.ToGray8(configuration, sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); } /// /// Converts all pixels in 'source` span of into a span of -s. /// + /// A to configure internal operations /// The source of data. /// The to the destination pixels. - internal virtual void FromGray16(ReadOnlySpan source, Span destPixels) + internal virtual void FromGray16(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -304,24 +321,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span. + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void FromGray16Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) + internal void FromGray16Bytes(Configuration configuration, ReadOnlySpan sourceBytes, Span destPixels, int count) { - this.FromGray16(MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); + this.FromGray16(configuration, MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); } /// /// Converts all pixels of the 'sourcePixels` span to a span of -s. /// + /// A to configure internal operations /// The span of source pixels /// The destination span of data. - internal virtual void ToGray16(ReadOnlySpan sourcePixels, Span destPixels) + internal virtual void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -338,24 +357,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span as destination. + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source pixels. /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToGray16Bytes(ReadOnlySpan sourcePixels, Span destBytes, int count) + internal void ToGray16Bytes(Configuration configuration, ReadOnlySpan sourcePixels, Span destBytes, int count) { - this.ToGray16(sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); + this.ToGray16(configuration, sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); } /// /// Converts all pixels in 'source` span of into a span of -s. /// + /// A to configure internal operations /// The source of data. /// The to the destination pixels. - internal virtual void FromRgb24(ReadOnlySpan source, Span destPixels) + internal virtual void FromRgb24(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -372,24 +393,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span. + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void FromRgb24Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) + internal void FromRgb24Bytes(Configuration configuration, ReadOnlySpan sourceBytes, Span destPixels, int count) { - this.FromRgb24(MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); + this.FromRgb24(configuration, MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); } /// /// Converts all pixels of the 'sourcePixels` span to a span of -s. /// + /// A to configure internal operations /// The span of source pixels /// The destination span of data. - internal virtual void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels) + internal virtual void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -406,24 +429,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span as destination. + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source pixels. /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToRgb24Bytes(ReadOnlySpan sourcePixels, Span destBytes, int count) + internal void ToRgb24Bytes(Configuration configuration, ReadOnlySpan sourcePixels, Span destBytes, int count) { - this.ToRgb24(sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); + this.ToRgb24(configuration, sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); } /// /// Converts all pixels in 'source` span of into a span of -s. /// + /// A to configure internal operations /// The source of data. /// The to the destination pixels. - internal virtual void FromRgba32(ReadOnlySpan source, Span destPixels) + internal virtual void FromRgba32(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -440,24 +465,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span. + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void FromRgba32Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) + internal void FromRgba32Bytes(Configuration configuration, ReadOnlySpan sourceBytes, Span destPixels, int count) { - this.FromRgba32(MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); + this.FromRgba32(configuration, MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); } /// /// Converts all pixels of the 'sourcePixels` span to a span of -s. /// + /// A to configure internal operations /// The span of source pixels /// The destination span of data. - internal virtual void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels) + internal virtual void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -474,24 +501,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span as destination. + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source pixels. /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToRgba32Bytes(ReadOnlySpan sourcePixels, Span destBytes, int count) + internal void ToRgba32Bytes(Configuration configuration, ReadOnlySpan sourcePixels, Span destBytes, int count) { - this.ToRgba32(sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); + this.ToRgba32(configuration, sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); } /// /// Converts all pixels in 'source` span of into a span of -s. /// + /// A to configure internal operations /// The source of data. /// The to the destination pixels. - internal virtual void FromRgb48(ReadOnlySpan source, Span destPixels) + internal virtual void FromRgb48(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -508,24 +537,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span. + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void FromRgb48Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) + internal void FromRgb48Bytes(Configuration configuration, ReadOnlySpan sourceBytes, Span destPixels, int count) { - this.FromRgb48(MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); + this.FromRgb48(configuration, MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); } /// /// Converts all pixels of the 'sourcePixels` span to a span of -s. /// + /// A to configure internal operations /// The span of source pixels /// The destination span of data. - internal virtual void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels) + internal virtual void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -542,24 +573,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span as destination. + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source pixels. /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToRgb48Bytes(ReadOnlySpan sourcePixels, Span destBytes, int count) + internal void ToRgb48Bytes(Configuration configuration, ReadOnlySpan sourcePixels, Span destBytes, int count) { - this.ToRgb48(sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); + this.ToRgb48(configuration, sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); } /// /// Converts all pixels in 'source` span of into a span of -s. /// + /// A to configure internal operations /// The source of data. /// The to the destination pixels. - internal virtual void FromRgba64(ReadOnlySpan source, Span destPixels) + internal virtual void FromRgba64(Configuration configuration, ReadOnlySpan source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -576,24 +609,26 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span. + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void FromRgba64Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) + internal void FromRgba64Bytes(Configuration configuration, ReadOnlySpan sourceBytes, Span destPixels, int count) { - this.FromRgba64(MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); + this.FromRgba64(configuration, MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); } /// /// Converts all pixels of the 'sourcePixels` span to a span of -s. /// + /// A to configure internal operations /// The span of source pixels /// The destination span of data. - internal virtual void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels) + internal virtual void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -610,16 +645,17 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - /// A helper for that expects a byte span as destination. + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source pixels. /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ToRgba64Bytes(ReadOnlySpan sourcePixels, Span destBytes, int count) + internal void ToRgba64Bytes(Configuration configuration, ReadOnlySpan sourcePixels, Span destBytes, int count) { - this.ToRgba64(sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); + this.ToRgba64(configuration, sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt index ef73378a2..8579423b3 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt @@ -18,9 +18,10 @@ /// /// Converts all pixels in 'source` span of into a span of -s. /// + /// A to configure internal operations /// The source of data. /// The to the destination pixels. - internal virtual void From<#=pixelType#>(ReadOnlySpan<<#=pixelType#>> source, Span destPixels) + internal virtual void From<#=pixelType#>(Configuration configuration, ReadOnlySpan<<#=pixelType#>> source, Span destPixels) { Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); @@ -37,16 +38,17 @@ } /// - /// A helper for that expects a byte span. + /// A helper for that expects a byte span. /// The layout of the data in 'sourceBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source bytes. /// The to the destination pixels. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void From<#=pixelType#>Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count) + internal void From<#=pixelType#>Bytes(Configuration configuration, ReadOnlySpan sourceBytes, Span destPixels, int count) { - this.From<#=pixelType#>(MemoryMarshal.Cast>(sourceBytes).Slice(0, count), destPixels); + this.From<#=pixelType#>(configuration, MemoryMarshal.Cast>(sourceBytes).Slice(0, count), destPixels); } <# @@ -58,9 +60,10 @@ /// /// Converts all pixels of the 'sourcePixels` span to a span of -s. /// + /// A to configure internal operations /// The span of source pixels /// The destination span of data. - internal virtual void To<#=pixelType#>(ReadOnlySpan sourcePixels, Span<<#=pixelType#>> destPixels) + internal virtual void To<#=pixelType#>(Configuration configuration, ReadOnlySpan sourcePixels, Span<<#=pixelType#>> destPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); @@ -77,16 +80,17 @@ } /// - /// A helper for that expects a byte span as destination. + /// A helper for that expects a byte span as destination. /// The layout of the data in 'destBytes' must be compatible with layout. /// + /// A to configure internal operations /// The to the source pixels. /// The to the destination bytes. /// The number of pixels to convert. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void To<#=pixelType#>Bytes(ReadOnlySpan sourcePixels, Span destBytes, int count) + internal void To<#=pixelType#>Bytes(Configuration configuration, ReadOnlySpan sourcePixels, Span destBytes, int count) { - this.To<#=pixelType#>(sourcePixels.Slice(0, count), MemoryMarshal.Cast>(destBytes)); + this.To<#=pixelType#>(configuration, sourcePixels.Slice(0, count), MemoryMarshal.Cast>(destBytes)); } <# } diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 8f3ea6c11..ea03af683 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -125,9 +125,11 @@ namespace SixLabors.ImageSharp.PixelFormats /// Converts 'sourceColors.Length' pixels from 'sourceColors' into 'destinationColors'. /// /// The destination pixel type. + /// A to configure internal operations /// The to the source colors. /// The to the destination colors. internal virtual void To( + Configuration configuration, ReadOnlySpan sourceColors, Span destinationColors) where TDestinationPixel : struct, IPixel diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs index 98a5d5eb5..43d22597d 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs @@ -448,7 +448,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization { Span row = source.GetPixelRowSpan(y); Span rgbaSpan = rgbaBuffer.GetSpan(); - PixelOperations.Instance.ToRgba32(row, rgbaSpan); + PixelOperations.Instance.ToRgba32(source.Configuration, row, rgbaSpan); ref Rgba32 scanBaseRef = ref MemoryMarshal.GetReference(rgbaSpan); // And loop through each column diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/FromRgba32Bytes.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/FromRgba32Bytes.cs index f3245ebaf..32565c23d 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/FromRgba32Bytes.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/FromRgba32Bytes.cs @@ -20,14 +20,17 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk private IMemoryOwner source; + private Configuration configuration; + [Params(16, 128, 1024)] public int Count { get; set; } [GlobalSetup] public void Setup() { - this.destination = Configuration.Default.MemoryAllocator.Allocate(this.Count); - this.source = Configuration.Default.MemoryAllocator.Allocate(this.Count * 4); + this.configuration = Configuration.Default; + this.destination = this.configuration.MemoryAllocator.Allocate(this.Count); + this.source = this.configuration.MemoryAllocator.Allocate(this.Count * 4); } [GlobalCleanup] @@ -55,13 +58,13 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk [Benchmark] public void CommonBulk() { - new PixelOperations().FromRgba32Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count); + new PixelOperations().FromRgba32Bytes(this.configuration, this.source.GetSpan(), this.destination.GetSpan(), this.Count); } [Benchmark] public void OptimizedBulk() { - PixelOperations.Instance.FromRgba32Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count); + PixelOperations.Instance.FromRgba32Bytes(this.configuration, this.source.GetSpan(), this.destination.GetSpan(), this.Count); } } diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs index f96023f00..912c3e4b2 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs @@ -17,14 +17,17 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk private IMemoryOwner destination; + private Configuration configuration; + [Params(16, 128, 1024)] public int Count { get; set; } [GlobalSetup] public void Setup() { - this.source = Configuration.Default.MemoryAllocator.Allocate(this.Count); - this.destination = Configuration.Default.MemoryAllocator.Allocate(this.Count * 3); + this.configuration = Configuration.Default; + this.source = this.configuration.MemoryAllocator.Allocate(this.Count); + this.destination = this.configuration.MemoryAllocator.Allocate(this.Count * 3); } [GlobalCleanup] @@ -35,10 +38,20 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk } [Benchmark(Baseline = true)] - public void CommonBulk() => new PixelOperations().ToRgb24Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count); + public void CommonBulk() => + new PixelOperations().ToRgb24Bytes( + this.configuration, + this.source.GetSpan(), + this.destination.GetSpan(), + this.Count); [Benchmark] - public void OptimizedBulk() => PixelOperations.Instance.ToRgb24Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count); + public void OptimizedBulk() => + PixelOperations.Instance.ToRgb24Bytes( + this.configuration, + this.source.GetSpan(), + this.destination.GetSpan(), + this.Count); } public class ToXyz_Rgba32 : ToXyz diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs index 0cf7087d4..37694f64c 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs @@ -19,14 +19,17 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk private IMemoryOwner destination; + private Configuration configuration; + [Params(16, 128, 1024)] public int Count { get; set; } [GlobalSetup] public void Setup() { - this.source = Configuration.Default.MemoryAllocator.Allocate(this.Count); - this.destination = Configuration.Default.MemoryAllocator.Allocate(this.Count * 4); + this.configuration = Configuration.Default; + this.source = this.configuration.MemoryAllocator.Allocate(this.Count); + this.destination = this.configuration.MemoryAllocator.Allocate(this.Count * 4); } [GlobalCleanup] @@ -56,10 +59,20 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk } [Benchmark] - public void CommonBulk() => new PixelOperations().ToRgba32Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count); + public void CommonBulk() => + new PixelOperations().ToRgba32Bytes( + this.configuration, + this.source.GetSpan(), + this.destination.GetSpan(), + this.Count); [Benchmark] - public void OptimizedBulk() => PixelOperations.Instance.ToRgba32Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count); + public void OptimizedBulk() => + PixelOperations.Instance.ToRgba32Bytes( + this.configuration, + this.source.GetSpan(), + this.destination.GetSpan(), + this.Count); } public class ToXyzw_Rgba32 : ToXyzw diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs index 8314bd9b4..e66ca9a71 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromGray8Bytes(s, d.GetSpan(), count) + (s, d) => Operations.FromGray8Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToGray8Bytes(s, d.GetSpan(), count) + (s, d) => Operations.ToGray8Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -123,7 +123,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromGray16Bytes(s, d.GetSpan(), count) + (s, d) => Operations.FromGray16Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -147,7 +147,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToGray16Bytes(s, d.GetSpan(), count) + (s, d) => Operations.ToGray16Bytes(this.Configuration, s, d.GetSpan(), count) ); } } @@ -177,7 +177,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromGray8Bytes(s, d.GetSpan(), count) + (s, d) => Operations.FromGray8Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -198,7 +198,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToGray8Bytes(s, d.GetSpan(), count) + (s, d) => Operations.ToGray8Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromGray16Bytes(s, d.GetSpan(), count) + (s, d) => Operations.FromGray16Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -243,7 +243,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToGray16Bytes(s, d.GetSpan(), count) + (s, d) => Operations.ToGray16Bytes(this.Configuration, s, d.GetSpan(), count) ); } } @@ -457,7 +457,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromArgb32Bytes(s, d.GetSpan(), count) + (s, d) => Operations.FromArgb32Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -483,7 +483,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToArgb32Bytes(s, d.GetSpan(), count) + (s, d) => Operations.ToArgb32Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -504,7 +504,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromBgr24Bytes(s, d.GetSpan(), count) + (s, d) => Operations.FromBgr24Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -528,7 +528,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToBgr24Bytes(s, d.GetSpan(), count) + (s, d) => Operations.ToBgr24Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -549,7 +549,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromBgra32Bytes(s, d.GetSpan(), count) + (s, d) => Operations.FromBgra32Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -574,7 +574,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToBgra32Bytes(s, d.GetSpan(), count) + (s, d) => Operations.ToBgra32Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -595,7 +595,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromRgb24Bytes(s, d.GetSpan(), count) + (s, d) => Operations.FromRgb24Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -619,7 +619,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToRgb24Bytes(s, d.GetSpan(), count) + (s, d) => Operations.ToRgb24Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -640,7 +640,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromRgba32Bytes(s, d.GetSpan(), count) + (s, d) => Operations.FromRgba32Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -665,7 +665,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToRgba32Bytes(s, d.GetSpan(), count) + (s, d) => Operations.ToRgba32Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -686,7 +686,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromRgb48Bytes(s, d.GetSpan(), count) + (s, d) => Operations.FromRgb48Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -714,7 +714,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToRgb48Bytes(s, d.GetSpan(), count) + (s, d) => Operations.ToRgb48Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -735,7 +735,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.FromRgba64Bytes(s, d.GetSpan(), count) + (s, d) => Operations.FromRgba64Bytes(this.Configuration, s, d.GetSpan(), count) ); } @@ -765,7 +765,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats TestOperation( source, expected, - (s, d) => Operations.ToRgba64Bytes(s, d.GetSpan(), count) + (s, d) => Operations.ToRgba64Bytes(this.Configuration, s, d.GetSpan(), count) ); } diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs index 886e02c13..462782ba5 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs @@ -28,14 +28,15 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison var bBuffer = new Rgba64[width]; var differences = new List(); + Configuration configuration = expected.Configuration; for (int y = 0; y < actual.Height; y++) { Span aSpan = expected.GetPixelRowSpan(y); Span bSpan = actual.GetPixelRowSpan(y); - PixelOperations.Instance.ToRgba64(aSpan, aBuffer); - PixelOperations.Instance.ToRgba64(bSpan, bBuffer); + PixelOperations.Instance.ToRgba64(configuration, aSpan, aBuffer); + PixelOperations.Instance.ToRgba64(configuration, bSpan, bBuffer); for (int x = 0; x < width; x++) { diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs index 9563edbb5..be12f5621 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs @@ -74,14 +74,15 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison float totalDifference = 0F; var differences = new List(); + Configuration configuration = expected.Configuration; for (int y = 0; y < actual.Height; y++) { Span aSpan = expected.GetPixelRowSpan(y); Span bSpan = actual.GetPixelRowSpan(y); - PixelOperations.Instance.ToRgba64(aSpan, aBuffer); - PixelOperations.Instance.ToRgba64(bSpan, bBuffer); + PixelOperations.Instance.ToRgba64(configuration, aSpan, aBuffer); + PixelOperations.Instance.ToRgba64(configuration, bSpan, bBuffer); for (int x = 0; x < width; x++) { diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index 2409ff9ad..3dd330e4d 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -31,14 +31,22 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs { byte[] data = pixels.ToByteArray(PixelMapping.RGBA); - PixelOperations.Instance.FromRgba32Bytes(data, resultPixels, resultPixels.Length); + PixelOperations.Instance.FromRgba32Bytes( + configuration, + data, + resultPixels, + resultPixels.Length); } else if (magickImage.Depth == 16) { ushort[] data = pixels.ToShortArray(PixelMapping.RGBA); Span bytes = MemoryMarshal.Cast(data.AsSpan()); - PixelOperations.Instance.FromRgba64Bytes(bytes, resultPixels, resultPixels.Length); + PixelOperations.Instance.FromRgba64Bytes( + configuration, + bytes, + resultPixels, + resultPixels.Length); } else { diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs index e96825db1..7e87c23db 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs @@ -33,7 +33,9 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs if (bmp.PixelFormat != PixelFormat.Format32bppArgb) { - throw new ArgumentException($"{nameof(From32bppArgbSystemDrawingBitmap)} : pixel format should be {PixelFormat.Format32bppArgb}!", nameof(bmp)); + throw new ArgumentException( + $"{nameof(From32bppArgbSystemDrawingBitmap)} : pixel format should be {PixelFormat.Format32bppArgb}!", + nameof(bmp)); } BitmapData data = bmp.LockBits(fullRect, ImageLockMode.ReadWrite, bmp.PixelFormat); @@ -43,6 +45,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs long destRowByteCount = w * sizeof(Bgra32); var image = new Image(w, h); + Configuration configuration = image.GetConfiguration(); using (IMemoryOwner workBuffer = Configuration.Default.MemoryAllocator.Allocate(w)) { @@ -55,7 +58,10 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs byte* sourcePtr = sourcePtrBase + (data.Stride * y); Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); - PixelOperations.Instance.FromBgra32(workBuffer.GetSpan().Slice(0, w), row); + PixelOperations.Instance.FromBgra32( + configuration, + workBuffer.GetSpan().Slice(0, w), + row); } } } @@ -79,7 +85,9 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs if (bmp.PixelFormat != PixelFormat.Format24bppRgb) { - throw new ArgumentException($"{nameof(From24bppRgbSystemDrawingBitmap)}: pixel format should be {PixelFormat.Format24bppRgb}!", nameof(bmp)); + throw new ArgumentException( + $"{nameof(From24bppRgbSystemDrawingBitmap)}: pixel format should be {PixelFormat.Format24bppRgb}!", + nameof(bmp)); } BitmapData data = bmp.LockBits(fullRect, ImageLockMode.ReadWrite, bmp.PixelFormat); @@ -89,6 +97,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs long destRowByteCount = w * sizeof(Bgr24); var image = new Image(w, h); + Configuration configuration = image.GetConfiguration(); using (IMemoryOwner workBuffer = Configuration.Default.MemoryAllocator.Allocate(w)) { @@ -101,7 +110,10 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs byte* sourcePtr = sourcePtrBase + (data.Stride * y); Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); - PixelOperations.Instance.FromBgr24(workBuffer.GetSpan().Slice(0, w), row); + PixelOperations.Instance.FromBgr24( + configuration, + workBuffer.GetSpan().Slice(0, w), + row); } } } @@ -112,6 +124,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs internal static unsafe Bitmap To32bppArgbSystemDrawingBitmap(Image image) where TPixel : struct, IPixel { + Configuration configuration = image.GetConfiguration(); int w = image.Width; int h = image.Height; @@ -130,7 +143,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs for (int y = 0; y < h; y++) { Span row = image.Frames.RootFrame.GetPixelRowSpan(y); - PixelOperations.Instance.ToBgra32(row, workBuffer.GetSpan()); + PixelOperations.Instance.ToBgra32(configuration, row, workBuffer.GetSpan()); byte* destPtr = destPtrBase + (data.Stride * y); Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); From 8dce0c740ce9660bd41b039a5023bbe204cdbf05 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 23 Oct 2018 11:06:32 +0200 Subject: [PATCH 03/17] bitwise conversion + benchmarks WIP --- .../Decoder/JpegImagePostProcessor.cs | 2 +- src/ImageSharp/PixelFormats/PixelConverter.cs | 47 ++++++ .../FrameQuantizerBase{TPixel}.cs | 2 - .../PixelConversion_ConvertFromRgba32.cs | 144 +++++++++++++---- .../General/PixelConversion/TestArgb.cs | 62 ++++---- .../General/PixelConversion/TestRgba.cs | 14 +- .../PixelFormats/PixelConverterTests.cs | 150 ++++++++++++++++++ .../PixelFormats/Rgba32Tests.cs | 1 + 8 files changed, 347 insertions(+), 75 deletions(-) create mode 100644 src/ImageSharp/PixelFormats/PixelConverter.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs index 1a6da2b2b..7ce86b4c9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs @@ -162,7 +162,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder this.colorConverter.ConvertToRgba(values, this.rgbaBuffer.GetSpan()); Span destRow = destination.GetPixelRowSpan(yy); - + // TODO: Investigate if slicing is actually necessary PixelOperations.Instance.FromVector4(this.configuration, this.rgbaBuffer.GetSpan().Slice(0, destRow.Length), destRow); } diff --git a/src/ImageSharp/PixelFormats/PixelConverter.cs b/src/ImageSharp/PixelFormats/PixelConverter.cs new file mode 100644 index 000000000..3686092cd --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelConverter.cs @@ -0,0 +1,47 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.PixelFormats +{ + /// + /// Contains optimized implementations for conversion between pixel formats. + /// + /// + /// 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. + /// + internal static class PixelConverter + { + public static class Rgba32 + { + /// + /// Converts a packed to . + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static uint ToArgb32(uint packedRgba) + { + // packedRgba = [aa bb gg rr] + // ROL(8, packedRgba): + return (packedRgba << 8) | (packedRgba >> 24); + } + } + + public static class Argb32 + { + /// + /// Converts a packed to . + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static uint ToRgba32(uint packedArgb) + { + // packedArgb = [bb gg rr aa] + // ROR(8, packedArgb): + return (packedArgb >> 8) | (packedArgb << 24); + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs index a41127bfc..a8c6c5d7e 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs @@ -17,8 +17,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization public abstract class FrameQuantizerBase : IFrameQuantizer where TPixel : struct, IPixel { - private readonly Configuration configuration; - /// /// A lookup table for colors /// diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs index 6a96c8576..1be8347c3 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs @@ -1,6 +1,8 @@ // ReSharper disable InconsistentNaming +using System; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; @@ -8,14 +10,14 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion { - public class PixelConversion_ConvertFromRgba32 + public abstract class PixelConversion_ConvertFromRgba32 { - struct ConversionRunner + internal struct ConversionRunner where T : struct, ITestPixel { - private T[] dest; + public readonly T[] dest; - private Rgba32[] source; + public readonly Rgba32[] source; public ConversionRunner(int count) { @@ -67,72 +69,146 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion } } - private ConversionRunner compatibleMemLayoutRunner; + internal ConversionRunner compatibleMemLayoutRunner; - private ConversionRunner permutedRunner; + internal ConversionRunner permutedRunnerRgbaToArgb; - [Params(32)] + [Params( + 256, + 2048 + )] public int Count { get; set; } [GlobalSetup] public void Setup() { this.compatibleMemLayoutRunner = new ConversionRunner(this.Count); - this.permutedRunner = new ConversionRunner(this.Count); + this.permutedRunnerRgbaToArgb = new ConversionRunner(this.Count); } + } + public class PixelConversion_ConvertFromRgba32_Compatible : PixelConversion_ConvertFromRgba32 + { [Benchmark(Baseline = true)] - public void CompatibleByRef() + public void ByRef() { this.compatibleMemLayoutRunner.RunByRefConversion(); } [Benchmark] - public void CompatibleByVal() + public void ByVal() { this.compatibleMemLayoutRunner.RunByValConversion(); } [Benchmark] - public void CompatibleFromBytes() + public void FromBytes() { this.compatibleMemLayoutRunner.RunFromBytesConversion(); } + [Benchmark] + public void Inline() + { + ref Rgba32 sBase = ref this.compatibleMemLayoutRunner.source[0]; + ref Rgba32 dBase = ref Unsafe.As(ref this.compatibleMemLayoutRunner.dest[0]); + + for (int i = 0; i < this.Count; i++) + { + Unsafe.Add(ref dBase, i) = Unsafe.Add(ref sBase, i); + } + } + + // Method | Count | Mean | Error | StdDev | Scaled | ScaledSD | + // ---------- |------ |---------:|---------:|---------:|-------:|---------:| + // ByRef | 256 | 128.5 ns | 1.217 ns | 1.138 ns | 1.00 | 0.00 | + // ByVal | 256 | 196.7 ns | 2.792 ns | 2.612 ns | 1.53 | 0.02 | + // FromBytes | 256 | 321.7 ns | 2.180 ns | 1.820 ns | 2.50 | 0.03 | + // Inline | 256 | 129.9 ns | 2.759 ns | 2.581 ns | 1.01 | 0.02 | + } + + public class PixelConversion_ConvertFromRgba32_Permuted_RgbaToArgb : PixelConversion_ConvertFromRgba32 + { + [Benchmark(Baseline = true)] + public void ByRef() + { + this.permutedRunnerRgbaToArgb.RunByRefConversion(); + } + + [Benchmark] + public void ByVal() + { + this.permutedRunnerRgbaToArgb.RunByValConversion(); + } + + [Benchmark] + public void FromBytes() + { + this.permutedRunnerRgbaToArgb.RunFromBytesConversion(); + } [Benchmark] - public void PermutedByRef() + public void InlineShuffle() { - this.permutedRunner.RunByRefConversion(); + ref Rgba32 sBase = ref this.permutedRunnerRgbaToArgb.source[0]; + ref TestArgb dBase = ref this.permutedRunnerRgbaToArgb.dest[0]; + + for (int i = 0; i < this.Count; i++) + { + Rgba32 s = Unsafe.Add(ref sBase, i); + ref TestArgb d = ref Unsafe.Add(ref dBase, i); + + d.R = s.R; + d.G = s.G; + d.B = s.B; + d.A = s.A; + } } [Benchmark] - public void PermutedByVal() + public void PixelConverter_Rgba32_ToArgb32() { - this.permutedRunner.RunByValConversion(); + ref uint sBase = ref Unsafe.As(ref this.permutedRunnerRgbaToArgb.source[0]); + ref uint dBase = ref Unsafe.As(ref this.permutedRunnerRgbaToArgb.dest[0]); + + for (int i = 0; i < this.Count; i++) + { + uint s = Unsafe.Add(ref sBase, i); + Unsafe.Add(ref dBase, i) = PixelConverter.Rgba32.ToArgb32(s); + } } [Benchmark] - public void PermutedFromBytes() + public void PixelConverter_Rgba32_ToArgb32_CopyThenWorkOnSingleBuffer() { - this.permutedRunner.RunFromBytesConversion(); + Span source = MemoryMarshal.Cast(this.permutedRunnerRgbaToArgb.source); + Span dest = MemoryMarshal.Cast(this.permutedRunnerRgbaToArgb.dest); + source.CopyTo(dest); + + ref uint dBase = ref MemoryMarshal.GetReference(dest); + + for (int i = 0; i < this.Count; i++) + { + uint s = Unsafe.Add(ref dBase, i); + Unsafe.Add(ref dBase, i) = PixelConverter.Rgba32.ToArgb32(s); + } } - } - /* - * 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 FromBytes() OR FromRgba32(). - */ + // RESULTS: + // Method | Count | Mean | Error | StdDev | Scaled | ScaledSD | + // ---------------------------------------------------------- |------ |-----------:|-----------:|-----------:|-------:|---------:| + // ByRef | 256 | 328.7 ns | 6.6141 ns | 6.1868 ns | 1.00 | 0.00 | + // ByVal | 256 | 322.0 ns | 4.3541 ns | 4.0728 ns | 0.98 | 0.02 | + // FromBytes | 256 | 321.5 ns | 3.3499 ns | 3.1335 ns | 0.98 | 0.02 | + // InlineShuffle | 256 | 330.7 ns | 4.2525 ns | 3.9778 ns | 1.01 | 0.02 | + // PixelConverter_Rgba32_ToArgb32 | 256 | 167.4 ns | 0.6357 ns | 0.5309 ns | 0.51 | 0.01 | + // PixelConverter_Rgba32_ToArgb32_CopyThenWorkOnSingleBuffer | 256 | 196.6 ns | 0.8929 ns | 0.7915 ns | 0.60 | 0.01 | + // | | | | | | | + // ByRef | 2048 | 2,534.4 ns | 8.2947 ns | 6.9265 ns | 1.00 | 0.00 | + // ByVal | 2048 | 2,638.5 ns | 52.6843 ns | 70.3320 ns | 1.04 | 0.03 | + // FromBytes | 2048 | 2,517.2 ns | 40.8055 ns | 38.1695 ns | 0.99 | 0.01 | + // InlineShuffle | 2048 | 2,546.5 ns | 21.2506 ns | 19.8778 ns | 1.00 | 0.01 | + // PixelConverter_Rgba32_ToArgb32 | 2048 | 1,265.7 ns | 5.1397 ns | 4.5562 ns | 0.50 | 0.00 | + // PixelConverter_Rgba32_ToArgb32_CopyThenWorkOnSingleBuffer | 2048 | 1,410.3 ns | 11.1939 ns | 9.9231 ns | 0.56 | 0.00 |// + } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/TestArgb.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/TestArgb.cs index 61a7df81d..76de794ec 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/TestArgb.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/TestArgb.cs @@ -9,81 +9,81 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion [StructLayout(LayoutKind.Sequential)] struct TestArgb : ITestPixel { - private byte a, r, g, b; + public 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; + 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; + 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; + this.R = r; + this.G = g; + this.B = b; + this.A = a; } [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; + 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; + this.R = (byte)p.X; + this.G = (byte)p.Y; + this.B = (byte)p.Z; + this.A = (byte)p.W; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Rgba32 ToRgba32() { - return new Rgba32(this.r, this.g, this.b, this.a); + 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; + dest.R = this.R; + dest.G = this.G; + dest.B = this.B; + dest.A = this.A; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ToVector4() { - return new Vector4(this.r, this.g, this.b, this.a); + return new Vector4(this.R, this.G, this.B, this.A); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CopyToVector4(ref Vector4 dest) { - dest.X = this.r; - dest.Y = this.g; - dest.Z = this.b; - dest.W = this.a; + dest.X = this.R; + dest.Y = this.G; + dest.Z = this.B; + dest.W = this.A; } } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/TestRgba.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/TestRgba.cs index cc8cf352a..36d5f3e5b 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/TestRgba.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/TestRgba.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion [StructLayout(LayoutKind.Sequential)] struct TestRgba : ITestPixel { - private byte r, g, b, a; + public byte R, G, B, A; [MethodImpl(MethodImplOptions.AggressiveInlining)] public void FromRgba32(Rgba32 source) @@ -26,10 +26,10 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion [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; + this.R = r; + this.G = g; + this.B = b; + this.A = a; } public void FromVector4(Vector4 source) @@ -57,13 +57,13 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ToVector4() { - return new Vector4(this.r, this.g, this.b, this.a) * new Vector4(1f / 255f); + return new Vector4(this.R, this.G, this.B, this.A) * new Vector4(1f / 255f); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CopyToVector4(ref Vector4 dest) { - var tmp = new Vector4(this.r, this.g, this.b, this.a); + var tmp = new Vector4(this.R, this.G, this.B, this.A); tmp *= new Vector4(1f / 255f); dest = tmp; } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs new file mode 100644 index 000000000..83c4e34f2 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs @@ -0,0 +1,150 @@ +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.PixelFormats +{ + public class PixelConverterTests + { + public static readonly TheoryData RgbaData = + new TheoryData + { + { 0, 0, 0, 0 }, + { 0, 0, 0, 255 }, + { 0, 0, 255, 0 }, + { 0, 255, 0, 0 }, + { 255, 0, 0, 0 }, + { 255, 255, 255, 255 }, + { 0, 0, 0, 1 }, + { 0, 0, 1, 0 }, + { 0, 1, 0, 0 }, + { 1, 0, 0, 0 }, + { 3, 5, 7, 11 }, + { 67, 71, 101, 109 } + }; + + [Theory] + [MemberData(nameof(RgbaData))] + public void Rgba32ToArgb32(byte r, byte g, byte b, byte a) + { + Rgba32 s = ReferenceImplementations.MakeRgba32(r, g, b, a); + + // Act: + uint actualPacked = PixelConverter.Rgba32.ToArgb32(s.PackedValue); + + // Assert: + uint expectedPacked = ReferenceImplementations.ToArgb32(s).PackedValue; + + Assert.Equal(expectedPacked, actualPacked); + } + + [Theory] + [MemberData(nameof(RgbaData))] + public void Argb32ToRgba32(byte r, byte g, byte b, byte a) + { + Argb32 s = ReferenceImplementations.MakeArgb32(r, g, b, a); + + // Act: + uint actualPacked = PixelConverter.Argb32.ToRgba32(s.PackedValue); + + // Assert: + uint expectedPacked = ReferenceImplementations.ToRgba32(s).PackedValue; + + Assert.Equal(expectedPacked, actualPacked); + } + + + private static class ReferenceImplementations + { + public static Rgba32 MakeRgba32(byte r, byte g, byte b, byte a) + { + Rgba32 d = default; + d.R = r; + d.G = g; + d.B = b; + d.A = a; + return d; + } + + public static Argb32 MakeArgb32(byte r, byte g, byte b, byte a) + { + Argb32 d = default; + d.R = r; + d.G = g; + d.B = b; + d.A = a; + return d; + } + + public static Bgra32 MakeBgra32(byte r, byte g, byte b, byte a) + { + Bgra32 d = default; + d.R = r; + d.G = g; + d.B = b; + d.A = a; + return d; + } + + public static Argb32 ToArgb32(Rgba32 s) + { + Argb32 d = default; + d.R = s.R; + d.G = s.G; + d.B = s.B; + d.A = s.A; + return d; + } + + public static Argb32 ToArgb32(Bgra32 s) + { + Argb32 d = default; + d.R = s.R; + d.G = s.G; + d.B = s.B; + d.A = s.A; + return d; + } + + public static Rgba32 ToRgba32(Argb32 s) + { + Rgba32 d = default; + d.R = s.R; + d.G = s.G; + d.B = s.B; + d.A = s.A; + return d; + } + + public static Rgba32 ToRgba32(Bgra32 s) + { + Rgba32 d = default; + d.R = s.R; + d.G = s.G; + d.B = s.B; + d.A = s.A; + return d; + } + + public static Bgra32 ToBgra32(Rgba32 s) + { + Bgra32 d = default; + d.R = s.R; + d.G = s.G; + d.B = s.B; + d.A = s.A; + return d; + } + + public static Bgra32 ToBgra32(Argb32 s) + { + Bgra32 d = default; + d.R = s.R; + d.G = s.G; + d.B = s.B; + d.A = s.A; + return d; + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs index 8c702f66d..ad1d13740 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs @@ -5,6 +5,7 @@ using System; using System.Numerics; using SixLabors.ImageSharp.PixelFormats; using Xunit; +using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests.PixelFormats { From 96d0ae80b9b743ca8e67435e40ba7ff9c0937b75 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 23 Oct 2018 20:14:05 +0200 Subject: [PATCH 04/17] Rgba32 <-> Argb32 <-> Bgra32 --- src/ImageSharp/PixelFormats/PixelConverter.cs | 76 +++++++- .../PixelFormats/PixelOperations{TPixel}.cs | 22 --- .../PixelConversion_ConvertFromRgba32.cs | 4 +- .../PixelFormats/PixelConverterTests.cs | 167 +++++++++--------- 4 files changed, 158 insertions(+), 111 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelConverter.cs b/src/ImageSharp/PixelFormats/PixelConverter.cs index 3686092cd..8fde490fd 100644 --- a/src/ImageSharp/PixelFormats/PixelConverter.cs +++ b/src/ImageSharp/PixelFormats/PixelConverter.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers.Binary; using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.PixelFormats @@ -16,32 +17,91 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal static class PixelConverter { - public static class Rgba32 + public static class FromRgba32 { /// - /// Converts a packed to . + /// Converts a packed to . /// [MethodImpl(InliningOptions.ShortMethod)] public static uint ToArgb32(uint packedRgba) { - // packedRgba = [aa bb gg rr] - // ROL(8, packedRgba): + // packedRgba = [aa bb gg rr] + // ROL(8, packedRgba) = [bb gg rr aa] return (packedRgba << 8) | (packedRgba >> 24); } + + /// + /// Converts a packed to . + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static uint ToBgra32(uint packedRgba) + { + // packedRgba = [aa bb gg rr] + // tmp1 = [aa 00 gg 00] + // tmp2 = [00 bb 00 rr] + // tmp3=ROL(16, tmp2) = [00 rr 00 bb] + // tmp1 + tmp3 = [aa rr gg bb] + uint tmp1 = packedRgba & 0xFF00FF00; + uint tmp2 = packedRgba & 0x00FF00FF; + uint tmp3 = (tmp2 << 16) | (tmp2 >> 16); + return tmp1 + tmp3; + } } - public static class Argb32 + public static class FromArgb32 { /// - /// Converts a packed to . + /// Converts a packed to . /// [MethodImpl(InliningOptions.ShortMethod)] public static uint ToRgba32(uint packedArgb) { - // packedArgb = [bb gg rr aa] - // ROR(8, packedArgb): + // packedArgb = [bb gg rr aa] + // ROR(8, packedArgb) = [aa bb gg rr] return (packedArgb >> 8) | (packedArgb << 24); } + + /// + /// Converts a packed to . + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static uint ToBgra32(uint packedArgb) + { + // packedArgb = [bb gg rr aa] + // REVERSE(packedArgb) = [aa rr gg bb] + return BinaryPrimitives.ReverseEndianness(packedArgb); + } + } + + public static class FromBgra32 + { + /// + /// Converts a packed to . + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static uint ToArgb32(uint packedBgra) + { + // packedBgra = [aa rr gg bb] + // REVERSE(packedBgra) = [bb gg rr aa] + return BinaryPrimitives.ReverseEndianness(packedBgra); + } + + /// + /// Converts a packed to . + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static uint ToRgba32(uint packedBgra) + { + // packedRgba = [aa rr gg bb] + // tmp1 = [aa 00 gg 00] + // tmp2 = [00 rr 00 bb] + // tmp3=ROL(16, tmp2) = [00 bb 00 rr] + // tmp1 + tmp3 = [aa bb gg rr] + uint tmp1 = packedBgra & 0xFF00FF00; + uint tmp2 = packedBgra & 0x00FF00FF; + uint tmp3 = (tmp2 << 16) | (tmp2 >> 16); + return tmp1 + tmp3; + } } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 02b80de9b..ad5aee8c7 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -178,27 +178,5 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromScaledVector4(sp.ToScaledVector4()); } } - - /// - /// Verifies that the given 'source' and 'destination' spans are at least of 'minLength' size. - /// Throwing an if the condition is not met. - /// - /// 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( - ReadOnlySpan source, - string sourceParamName, - Span destination, - string destinationParamName, - int minLength) - { - Guard.MustBeSizedAtLeast(source, minLength, sourceParamName); - Guard.MustBeSizedAtLeast(destination, minLength, destinationParamName); - } } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs index 1be8347c3..424020e2f 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs @@ -174,7 +174,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion for (int i = 0; i < this.Count; i++) { uint s = Unsafe.Add(ref sBase, i); - Unsafe.Add(ref dBase, i) = PixelConverter.Rgba32.ToArgb32(s); + Unsafe.Add(ref dBase, i) = PixelConverter.FromRgba32.ToArgb32(s); } } @@ -190,7 +190,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion for (int i = 0; i < this.Count; i++) { uint s = Unsafe.Add(ref dBase, i); - Unsafe.Add(ref dBase, i) = PixelConverter.Rgba32.ToArgb32(s); + Unsafe.Add(ref dBase, i) = PixelConverter.FromRgba32.ToArgb32(s); } } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs index 83c4e34f2..9b32f7aee 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs @@ -4,7 +4,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { - public class PixelConverterTests + public abstract class PixelConverterTests { public static readonly TheoryData RgbaData = new TheoryData @@ -23,34 +23,103 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { 67, 71, 101, 109 } }; - [Theory] - [MemberData(nameof(RgbaData))] - public void Rgba32ToArgb32(byte r, byte g, byte b, byte a) + public class FromRgba32 : PixelConverterTests { - Rgba32 s = ReferenceImplementations.MakeRgba32(r, g, b, a); + [Theory] + [MemberData(nameof(RgbaData))] + public void ToArgb32(byte r, byte g, byte b, byte a) + { + Rgba32 s = ReferenceImplementations.MakeRgba32(r, g, b, a); + + // Act: + uint actualPacked = PixelConverter.FromRgba32.ToArgb32(s.PackedValue); + + // Assert: + uint expectedPacked = ReferenceImplementations.MakeArgb32(r, g, b, a).PackedValue; + + Assert.Equal(expectedPacked, actualPacked); + } + + [Theory] + [MemberData(nameof(RgbaData))] + public void ToBgra32(byte r, byte g, byte b, byte a) + { + Rgba32 s = ReferenceImplementations.MakeRgba32(r, g, b, a); + + // Act: + uint actualPacked = PixelConverter.FromRgba32.ToBgra32(s.PackedValue); + + // Assert: + uint expectedPacked = ReferenceImplementations.MakeBgra32(r, g, b, a).PackedValue; + + Assert.Equal(expectedPacked, actualPacked); + } + } + + public class FromArgb32 : PixelConverterTests + { + [Theory] + [MemberData(nameof(RgbaData))] + public void ToRgba32(byte r, byte g, byte b, byte a) + { + Argb32 s = ReferenceImplementations.MakeArgb32(r, g, b, a); - // Act: - uint actualPacked = PixelConverter.Rgba32.ToArgb32(s.PackedValue); + // Act: + uint actualPacked = PixelConverter.FromArgb32.ToRgba32(s.PackedValue); - // Assert: - uint expectedPacked = ReferenceImplementations.ToArgb32(s).PackedValue; + // Assert: + uint expectedPacked = ReferenceImplementations.MakeRgba32(r, g, b, a).PackedValue; - Assert.Equal(expectedPacked, actualPacked); + Assert.Equal(expectedPacked, actualPacked); + } + + [Theory] + [MemberData(nameof(RgbaData))] + public void ToBgra32(byte r, byte g, byte b, byte a) + { + Argb32 s = ReferenceImplementations.MakeArgb32(r, g, b, a); + + // Act: + uint actualPacked = PixelConverter.FromArgb32.ToBgra32(s.PackedValue); + + // Assert: + uint expectedPacked = ReferenceImplementations.MakeBgra32(r, g, b, a).PackedValue; + + Assert.Equal(expectedPacked, actualPacked); + } } - [Theory] - [MemberData(nameof(RgbaData))] - public void Argb32ToRgba32(byte r, byte g, byte b, byte a) + public class FromBgra32 : PixelConverterTests { - Argb32 s = ReferenceImplementations.MakeArgb32(r, g, b, a); + [Theory] + [MemberData(nameof(RgbaData))] + public void ToArgb32(byte r, byte g, byte b, byte a) + { + Bgra32 s = ReferenceImplementations.MakeBgra32(r, g, b, a); - // Act: - uint actualPacked = PixelConverter.Argb32.ToRgba32(s.PackedValue); + // Act: + uint actualPacked = PixelConverter.FromBgra32.ToArgb32(s.PackedValue); - // Assert: - uint expectedPacked = ReferenceImplementations.ToRgba32(s).PackedValue; + // Assert: + uint expectedPacked = ReferenceImplementations.MakeArgb32(r, g, b, a).PackedValue; - Assert.Equal(expectedPacked, actualPacked); + Assert.Equal(expectedPacked, actualPacked); + } + + [Theory] + [MemberData(nameof(RgbaData))] + public void ToRgba32(byte r, byte g, byte b, byte a) + { + Bgra32 s = ReferenceImplementations.MakeBgra32(r, g, b, a); + + // Act: + uint actualPacked = PixelConverter.FromBgra32.ToRgba32(s.PackedValue); + + // Assert: + uint expectedPacked = ReferenceImplementations.MakeRgba32(r, g, b, a).PackedValue; + + Assert.Equal(expectedPacked, actualPacked); + } } @@ -85,66 +154,6 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats d.A = a; return d; } - - public static Argb32 ToArgb32(Rgba32 s) - { - Argb32 d = default; - d.R = s.R; - d.G = s.G; - d.B = s.B; - d.A = s.A; - return d; - } - - public static Argb32 ToArgb32(Bgra32 s) - { - Argb32 d = default; - d.R = s.R; - d.G = s.G; - d.B = s.B; - d.A = s.A; - return d; - } - - public static Rgba32 ToRgba32(Argb32 s) - { - Rgba32 d = default; - d.R = s.R; - d.G = s.G; - d.B = s.B; - d.A = s.A; - return d; - } - - public static Rgba32 ToRgba32(Bgra32 s) - { - Rgba32 d = default; - d.R = s.R; - d.G = s.G; - d.B = s.B; - d.A = s.A; - return d; - } - - public static Bgra32 ToBgra32(Rgba32 s) - { - Bgra32 d = default; - d.R = s.R; - d.G = s.G; - d.B = s.B; - d.A = s.A; - return d; - } - - public static Bgra32 ToBgra32(Argb32 s) - { - Bgra32 d = default; - d.R = s.R; - d.G = s.G; - d.B = s.B; - d.A = s.A; - return d; - } } } } \ No newline at end of file From d5cae6987bffbba1de98269842497a548429a5ec Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 23 Oct 2018 23:34:24 +0200 Subject: [PATCH 05/17] disappointing benchmark for Rgba32 -> Bgra32 --- .../PixelConversion_Rgba32_To_Argb32.cs | 278 +++++++++++++ .../PixelConversion_Rgba32_To_Bgra32.cs | 393 ++++++++++++++++++ 2 files changed, 671 insertions(+) create mode 100644 tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Argb32.cs create mode 100644 tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Argb32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Argb32.cs new file mode 100644 index 000000000..519014527 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Argb32.cs @@ -0,0 +1,278 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using BenchmarkDotNet.Attributes; + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion +{ + public class PixelConversion_Rgba32_To_Argb32 + { + private Rgba32[] source; + + private Argb32[] dest; + + [Params(64)] + public int Count { get; set; } + + [GlobalSetup] + public void Setup() + { + this.source = new Rgba32[this.Count]; + this.dest = new Argb32[this.Count]; + } + + [Benchmark(Baseline = true)] + public void Default() + { + ref Rgba32 sBase = ref this.source[0]; + ref Argb32 dBase = ref this.dest[0]; + + for (int i = 0; i < this.Count; i++) + { + Rgba32 s = Unsafe.Add(ref sBase, i); + Unsafe.Add(ref dBase, i).FromRgba32(s); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Default_GenericImpl(ReadOnlySpan source, Span dest) + where TPixel : struct, IPixel + { + ref Rgba32 sBase = ref MemoryMarshal.GetReference(source); + ref TPixel dBase = ref MemoryMarshal.GetReference(dest); + + for (int i = 0; i < source.Length; i++) + { + Rgba32 s = Unsafe.Add(ref sBase, i); + Unsafe.Add(ref dBase, i).FromRgba32(s); + } + } + + [Benchmark] + public void Default_Generic() + { + Default_GenericImpl(this.source.AsSpan(), this.dest.AsSpan()); + } + + [Benchmark] + public void Default_Group2() + { + ref Rgba32 sBase = ref this.source[0]; + ref Argb32 dBase = ref this.dest[0]; + + for (int i = 0; i < this.Count / 2; i += 2) + { + ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); + Rgba32 s1 = Unsafe.Add(ref s0, 1); + + ref Argb32 d0 = ref Unsafe.Add(ref dBase, i); + d0.FromRgba32(s0); + Unsafe.Add(ref d0, 1).FromRgba32(s1); + } + } + + + [Benchmark] + public void Default_Group4() + { + ref Rgba32 sBase = ref this.source[0]; + ref Argb32 dBase = ref this.dest[0]; + + for (int i = 0; i < this.Count / 4; i += 4) + { + ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); + ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); + ref Rgba32 s2 = ref Unsafe.Add(ref s1, 1); + Rgba32 s3 = Unsafe.Add(ref s2, 1); + + ref Argb32 d0 = ref Unsafe.Add(ref dBase, i); + ref Argb32 d1 = ref Unsafe.Add(ref d0, 1); + ref Argb32 d2 = ref Unsafe.Add(ref d1, 1); + + d0.FromRgba32(s0); + d1.FromRgba32(s1); + d2.FromRgba32(s2); + Unsafe.Add(ref d2, 1).FromRgba32(s3); + } + } + + [Benchmark] + public void Default_Group4_ManualInline_V1() + { + ref Rgba32 sBase = ref this.source[0]; + ref Argb32 dBase = ref this.dest[0]; + + for (int i = 0; i < this.Count / 4; i += 4) + { + ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); + ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); + ref Rgba32 s2 = ref Unsafe.Add(ref s1, 1); + Rgba32 s3 = Unsafe.Add(ref s2, 1); + + ref Argb32 d0 = ref Unsafe.Add(ref dBase, i); + ref Argb32 d1 = ref Unsafe.Add(ref d0, 1); + ref Argb32 d2 = ref Unsafe.Add(ref d1, 1); + ref Argb32 d3 = ref Unsafe.Add(ref d2, 1); + + d0.R = s0.R; + d0.G = s0.G; + d0.B = s0.B; + d0.A = s0.A; + + d1.R = s1.R; + d1.G = s1.G; + d1.B = s1.B; + d1.A = s1.A; + + d2.R = s2.R; + d2.G = s2.G; + d2.B = s2.B; + d2.A = s2.A; + + d3.R = s3.R; + d3.G = s3.G; + d3.B = s3.B; + d3.A = s3.A; + } + } + + [Benchmark] + public void Default_Group4_ManualInline_V2() + { + ref Rgba32 sBase = ref this.source[0]; + ref Argb32 dBase = ref this.dest[0]; + + for (int i = 0; i < this.Count / 4; i += 4) + { + ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); + ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); + ref Rgba32 s2 = ref Unsafe.Add(ref s1, 1); + Rgba32 s3 = Unsafe.Add(ref s2, 1); + + ref Argb32 d0 = ref Unsafe.Add(ref dBase, i); + ref Argb32 d1 = ref Unsafe.Add(ref d0, 1); + ref Argb32 d2 = ref Unsafe.Add(ref d1, 1); + ref Argb32 d3 = ref Unsafe.Add(ref d2, 1); + + d0.R = s0.R; + d1.R = s1.R; + d2.R = s2.R; + d3.R = s3.R; + + d0.G = s0.G; + d1.G = s1.G; + d2.G = s2.G; + d3.G = s3.G; + + d0.B = s0.B; + d1.B = s1.B; + d2.B = s2.B; + d3.B = s3.B; + + d0.A = s0.A; + d1.A = s1.A; + d2.A = s2.A; + d3.A = s3.A; + } + } + + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Group4GenericImpl(ReadOnlySpan source, Span dest) + where TPixel : struct, IPixel + { + ref Rgba32 sBase = ref MemoryMarshal.GetReference(source); + ref TPixel dBase = ref MemoryMarshal.GetReference(dest); + + for (int i = 0; i < source.Length / 4; i += 4) + { + ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); + ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); + ref Rgba32 s2 = ref Unsafe.Add(ref s1, 1); + Rgba32 s3 = Unsafe.Add(ref s2, 1); + + ref TPixel d0 = ref Unsafe.Add(ref dBase, i); + ref TPixel d1 = ref Unsafe.Add(ref d0, 1); + ref TPixel d2 = ref Unsafe.Add(ref d1, 1); + + d0.FromRgba32(s0); + d1.FromRgba32(s1); + d2.FromRgba32(s2); + Unsafe.Add(ref d2, 1).FromRgba32(s3); + } + } + + [Benchmark] + public void Default_Group4_Generic() + { + Group4GenericImpl(this.source.AsSpan(), this.dest.AsSpan()); + } + + [Benchmark] + public void BitOps() + { + ref uint sBase = ref Unsafe.As(ref this.source[0]); + ref uint dBase = ref Unsafe.As(ref this.dest[0]); + + for (int i = 0; i < this.Count; i++) + { + uint s = Unsafe.Add(ref sBase, i); + Unsafe.Add(ref dBase, i) = FromRgba32.ToArgb32(s); + } + } + + [Benchmark] + public void BitOps_GroupAsULong() + { + ref ulong sBase = ref Unsafe.As(ref this.source[0]); + ref ulong dBase = ref Unsafe.As(ref this.dest[0]); + + for (int i = 0; i < this.Count / 2; i++) + { + ulong s = Unsafe.Add(ref sBase, i); + uint lo = (uint)s; + uint hi = (uint)(s >> 32); + lo = FromRgba32.ToArgb32(lo); + hi = FromRgba32.ToArgb32(hi); + + s = (ulong)(hi << 32) | lo; + + Unsafe.Add(ref dBase, i) = s; + } + } + + public static class FromRgba32 + { + /// + /// Converts a packed to . + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static uint ToArgb32(uint packedRgba) + { + // packedRgba = [aa bb gg rr] + // ROL(8, packedRgba) = [bb gg rr aa] + return (packedRgba << 8) | (packedRgba >> 24); + } + + /// + /// Converts a packed to . + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static uint ToBgra32(uint packedRgba) + { + // packedRgba = [aa bb gg rr] + // tmp1 = [aa 00 gg 00] + // tmp2 = [00 bb 00 rr] + // tmp3=ROL(16, tmp2) = [00 rr 00 bb] + // tmp1 + tmp3 = [aa rr gg bb] + uint tmp1 = packedRgba & 0xFF00FF00; + uint tmp2 = packedRgba & 0x00FF00FF; + uint tmp3 = (tmp2 << 16) | (tmp2 >> 16); + return tmp1 + tmp3; + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs new file mode 100644 index 000000000..9e638dbcc --- /dev/null +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs @@ -0,0 +1,393 @@ +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes.Jobs; + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tuples; + +namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion +{ + //[MonoJob] + [RyuJitX64Job] + public class PixelConversion_Rgba32_To_Bgra32 + { + private Rgba32[] source; + + private Bgra32[] dest; + + [StructLayout(LayoutKind.Sequential)] + struct Tuple4OfUInt32 + { + public uint V0, V1, V2, V3; + + public void ConvertMe() + { + this.V0 = FromRgba32.ToBgra32(this.V0); + this.V1 = FromRgba32.ToBgra32(this.V1); + this.V2 = FromRgba32.ToBgra32(this.V2); + this.V3 = FromRgba32.ToBgra32(this.V3); + } + } + + [Params(64)] + public int Count { get; set; } + + [GlobalSetup] + public void Setup() + { + this.source = new Rgba32[this.Count]; + this.dest = new Bgra32[this.Count]; + } + + [Benchmark(Baseline = true)] + public void Default() + { + ref Rgba32 sBase = ref this.source[0]; + ref Bgra32 dBase = ref this.dest[0]; + + for (int i = 0; i < this.Count; i++) + { + Rgba32 s = Unsafe.Add(ref sBase, i); + Unsafe.Add(ref dBase, i).FromRgba32(s); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Default_GenericImpl(ReadOnlySpan source, Span dest) + where TPixel : struct, IPixel + { + ref Rgba32 sBase = ref MemoryMarshal.GetReference(source); + ref TPixel dBase = ref MemoryMarshal.GetReference(dest); + + for (int i = 0; i < source.Length; i++) + { + Rgba32 s = Unsafe.Add(ref sBase, i); + Unsafe.Add(ref dBase, i).FromRgba32(s); + } + } + + [Benchmark] + public void Default_Generic() + { + Default_GenericImpl(this.source.AsSpan(), this.dest.AsSpan()); + } + + [Benchmark] + public void Default_Group2() + { + ref Rgba32 sBase = ref this.source[0]; + ref Bgra32 dBase = ref this.dest[0]; + + for (int i = 0; i < this.Count / 2; i+=2) + { + ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); + Rgba32 s1 = Unsafe.Add(ref s0, 1); + + ref Bgra32 d0 = ref Unsafe.Add(ref dBase, i); + d0.FromRgba32(s0); + Unsafe.Add(ref d0, 1).FromRgba32(s1); + } + } + + [Benchmark] + public void Default_Group4() + { + ref Rgba32 sBase = ref this.source[0]; + ref Bgra32 dBase = ref this.dest[0]; + + for (int i = 0; i < this.Count / 4; i += 4) + { + ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); + ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); + ref Rgba32 s2 = ref Unsafe.Add(ref s1, 1); + Rgba32 s3 = Unsafe.Add(ref s2, 1); + + ref Bgra32 d0 = ref Unsafe.Add(ref dBase, i); + ref Bgra32 d1 = ref Unsafe.Add(ref d0, 1); + ref Bgra32 d2 = ref Unsafe.Add(ref d1, 1); + + d0.FromRgba32(s0); + d1.FromRgba32(s1); + d2.FromRgba32(s2); + Unsafe.Add(ref d2, 1).FromRgba32(s3); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Group4GenericImpl(ReadOnlySpan source, Span dest) + where TPixel : struct, IPixel + { + ref Rgba32 sBase = ref MemoryMarshal.GetReference(source); + ref TPixel dBase = ref MemoryMarshal.GetReference(dest); + + for (int i = 0; i < source.Length / 4; i += 4) + { + ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); + ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); + ref Rgba32 s2 = ref Unsafe.Add(ref s1, 1); + Rgba32 s3 = Unsafe.Add(ref s2, 1); + + ref TPixel d0 = ref Unsafe.Add(ref dBase, i); + ref TPixel d1 = ref Unsafe.Add(ref d0, 1); + ref TPixel d2 = ref Unsafe.Add(ref d1, 1); + + d0.FromRgba32(s0); + d1.FromRgba32(s1); + d2.FromRgba32(s2); + Unsafe.Add(ref d2, 1).FromRgba32(s3); + } + } + + [Benchmark] + public void Default_Group4_Generic() + { + Group4GenericImpl(this.source.AsSpan(), this.dest.AsSpan()); + } + + //[Benchmark] + public void Default_Group8() + { + ref Rgba32 sBase = ref this.source[0]; + ref Bgra32 dBase = ref this.dest[0]; + + for (int i = 0; i < this.Count / 4; i += 4) + { + ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); + ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); + ref Rgba32 s2 = ref Unsafe.Add(ref s1, 1); + ref Rgba32 s3 = ref Unsafe.Add(ref s1, 1); + + ref Rgba32 s4 = ref Unsafe.Add(ref s3, 1); + ref Rgba32 s5 = ref Unsafe.Add(ref s4, 1); + ref Rgba32 s6 = ref Unsafe.Add(ref s5, 1); + Rgba32 s7 = Unsafe.Add(ref s6, 1); + + ref Bgra32 d0 = ref Unsafe.Add(ref dBase, i); + ref Bgra32 d1 = ref Unsafe.Add(ref d0, 1); + ref Bgra32 d2 = ref Unsafe.Add(ref d1, 1); + ref Bgra32 d3 = ref Unsafe.Add(ref d2, 1); + ref Bgra32 d4 = ref Unsafe.Add(ref d3, 1); + + ref Bgra32 d5 = ref Unsafe.Add(ref d4, 1); + ref Bgra32 d6 = ref Unsafe.Add(ref d5, 1); + + + d0.FromRgba32(s0); + d1.FromRgba32(s1); + d2.FromRgba32(s2); + d3.FromRgba32(s3); + + d4.FromRgba32(s4); + d5.FromRgba32(s5); + d6.FromRgba32(s6); + Unsafe.Add(ref d6, 1).FromRgba32(s7); + } + } + + [Benchmark] + public void BitOps() + { + ref uint sBase = ref Unsafe.As(ref this.source[0]); + ref uint dBase = ref Unsafe.As(ref this.dest[0]); + + for (int i = 0; i < this.Count; i++) + { + uint s = Unsafe.Add(ref sBase, i); + Unsafe.Add(ref dBase, i) = FromRgba32.ToBgra32(s); + } + } + + [Benchmark] + public void Bitops_Tuple() + { + ref Tuple4OfUInt32 sBase = ref Unsafe.As(ref this.source[0]); + ref Tuple4OfUInt32 dBase = ref Unsafe.As(ref this.dest[0]); + + for (int i = 0; i < this.Count / 4; i++) + { + ref Tuple4OfUInt32 d = ref Unsafe.Add(ref dBase, i); + d = Unsafe.Add(ref sBase, i); + d.ConvertMe(); + } + } + + [Benchmark] + public void Bitops_SingleTuple() + { + ref Tuple4OfUInt32 sBase = ref Unsafe.As(ref this.source[0]); + + for (int i = 0; i < this.Count / 4; i++) + { + Unsafe.Add(ref sBase, i).ConvertMe(); + } + } + + [Benchmark] + public void Bitops_Simd() + { + ref Octet.OfUInt32 sBase = ref Unsafe.As(ref this.source[0]); + ref Octet.OfUInt32 dBase = ref Unsafe.As(ref this.dest[0]); + + for (int i = 0; i < this.Count / 8; i++) + { + BitopsSimdImpl(ref Unsafe.Add(ref sBase, i), ref Unsafe.Add(ref dBase, i)); + } + } + + [StructLayout(LayoutKind.Sequential)] + struct B + { + public uint tmp2, tmp5, tmp8, tmp11, tmp14, tmp17, tmp20, tmp23; + } + + [StructLayout(LayoutKind.Sequential)] + struct C + { + public uint tmp3, tmp6, tmp9, tmp12, tmp15, tmp18, tmp21, tmp24; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void BitopsSimdImpl(ref Octet.OfUInt32 s, ref Octet.OfUInt32 d) + { + Vector sVec = Unsafe.As>(ref s); + Vector aMask = new Vector(0xFF00FF00); + Vector bMask = new Vector(0x00FF00FF); + + Vector aa = sVec & aMask; + Vector bb = sVec & bMask; + + B b = Unsafe.As, B>(ref bb); + + C c = default; + + c.tmp3 = (b.tmp2 << 16) | (b.tmp2 >> 16); + c.tmp6 = (b.tmp5 << 16) | (b.tmp5 >> 16); + c.tmp9 = (b.tmp8 << 16) | (b.tmp8 >> 16); + c.tmp12 = (b.tmp11 << 16) | (b.tmp11 >> 16); + c.tmp15 = (b.tmp14 << 16) | (b.tmp14 >> 16); + c.tmp18 = (b.tmp17 << 16) | (b.tmp17 >> 16); + c.tmp21 = (b.tmp20 << 16) | (b.tmp20 >> 16); + c.tmp24 = (b.tmp23 << 16) | (b.tmp23 >> 16); + + Vector cc = Unsafe.As>(ref c); + Vector dd = aa + cc; + + d = Unsafe.As, Octet.OfUInt32>(ref dd); + } + + //[Benchmark] + public void BitOps_Group2() + { + ref uint sBase = ref Unsafe.As(ref this.source[0]); + ref uint dBase = ref Unsafe.As(ref this.dest[0]); + + for (int i = 0; i < this.Count; i++) + { + ref uint s0 = ref Unsafe.Add(ref sBase, i); + uint s1 = Unsafe.Add(ref s0, 1); + + ref uint d0 = ref Unsafe.Add(ref dBase, i); + d0 = FromRgba32.ToBgra32(s0); + Unsafe.Add(ref d0, 1) = FromRgba32.ToBgra32(s1); + } + } + + [Benchmark] + public void BitOps_GroupAsULong() + { + ref ulong sBase = ref Unsafe.As(ref this.source[0]); + ref ulong dBase = ref Unsafe.As(ref this.dest[0]); + + for (int i = 0; i < this.Count / 2; i++) + { + ulong s = Unsafe.Add(ref sBase, i); + uint lo = (uint)s; + uint hi = (uint)(s >> 32); + lo = FromRgba32.ToBgra32(lo); + hi = FromRgba32.ToBgra32(hi); + + s = (ulong)(hi << 32) | lo; + + Unsafe.Add(ref dBase, i) = s; + } + } + + //[Benchmark] + public void BitOps_GroupAsULong_V2() + { + ref ulong sBase = ref Unsafe.As(ref this.source[0]); + ref ulong dBase = ref Unsafe.As(ref this.dest[0]); + + for (int i = 0; i < this.Count / 2; i++) + { + ulong s = Unsafe.Add(ref sBase, i); + uint lo = (uint)s; + uint hi = (uint)(s >> 32); + + uint tmp1 = lo & 0xFF00FF00; + uint tmp4 = hi & 0xFF00FF00; + + uint tmp2 = lo & 0x00FF00FF; + uint tmp5 = hi & 0x00FF00FF; + + uint tmp3 = (tmp2 << 16) | (tmp2 >> 16); + uint tmp6 = (tmp5 << 16) | (tmp5 >> 16); + + lo = tmp1 + tmp3; + hi = tmp4 + tmp6; + + s = (ulong)(hi << 32) | lo; + + Unsafe.Add(ref dBase, i) = s; + } + } + + public static class FromRgba32 + { + /// + /// Converts a packed to . + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static uint ToArgb32(uint packedRgba) + { + // packedRgba = [aa bb gg rr] + // ROL(8, packedRgba) = [bb gg rr aa] + return (packedRgba << 8) | (packedRgba >> 24); + } + + /// + /// Converts a packed to . + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static uint ToBgra32(uint packedRgba) + { + // packedRgba = [aa bb gg rr] + // tmp1 = [aa 00 gg 00] + // tmp2 = [00 bb 00 rr] + // tmp3=ROL(16, tmp2) = [00 rr 00 bb] + // tmp1 + tmp3 = [aa rr gg bb] + uint tmp1 = packedRgba & 0xFF00FF00; + uint tmp2 = packedRgba & 0x00FF00FF; + uint tmp3 = (tmp2 << 16) | (tmp2 >> 16); + return tmp1 + tmp3; + } + } + + + // RESULTS: + // Method | Count | Mean | Error | StdDev | Scaled | + // ----------------------- |------ |----------:|----------:|----------:|-------:| + // Default | 64 | 107.13 ns | 0.7752 ns | 0.6872 ns | 1.00 | + // Default_Generic | 64 | 113.78 ns | 0.7713 ns | 0.6022 ns | 1.06 | + // Default_Group2 | 64 | 43.72 ns | 0.1711 ns | 0.1600 ns | 0.41 | + // Default_Group4 | 64 | 23.47 ns | 0.1901 ns | 0.1588 ns | 0.22 | + // Default_Group4_Generic | 64 | 32.46 ns | 0.4297 ns | 0.4019 ns | 0.30 | + // Bitops_Tuple | 64 | 77.71 ns | 0.2779 ns | 0.2599 ns | 0.73 | + // Bitops_SingleTuple | 64 | 58.64 ns | 0.4511 ns | 0.4220 ns | 0.55 | + // Bitops_Simd | 64 | 110.58 ns | 0.4686 ns | 0.4383 ns | 1.03 | + } +} \ No newline at end of file From 3dde4917124c90c891b790ec0806aa4c61e978f7 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Wed, 24 Oct 2018 01:49:26 +0200 Subject: [PATCH 06/17] Fixed the benchmarks. All results make sense now! (cherry picked from commit 0d79d4eb58fa1002979f4157eb18c6291a164b06) --- .../PixelConversion_Rgba32_To_Argb32.cs | 128 ++---------------- .../PixelConversion_Rgba32_To_Bgra32.cs | 33 +++-- 2 files changed, 29 insertions(+), 132 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Argb32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Argb32.cs index 519014527..40893914e 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Argb32.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Argb32.cs @@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion ref Rgba32 sBase = ref this.source[0]; ref Argb32 dBase = ref this.dest[0]; - for (int i = 0; i < this.Count / 2; i += 2) + for (int i = 0; i < this.Count; i += 2) { ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); Rgba32 s1 = Unsafe.Add(ref s0, 1); @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion ref Rgba32 sBase = ref this.source[0]; ref Argb32 dBase = ref this.dest[0]; - for (int i = 0; i < this.Count / 4; i += 4) + for (int i = 0; i < this.Count; i += 4) { ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); @@ -98,119 +98,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion Unsafe.Add(ref d2, 1).FromRgba32(s3); } } - - [Benchmark] - public void Default_Group4_ManualInline_V1() - { - ref Rgba32 sBase = ref this.source[0]; - ref Argb32 dBase = ref this.dest[0]; - - for (int i = 0; i < this.Count / 4; i += 4) - { - ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); - ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); - ref Rgba32 s2 = ref Unsafe.Add(ref s1, 1); - Rgba32 s3 = Unsafe.Add(ref s2, 1); - - ref Argb32 d0 = ref Unsafe.Add(ref dBase, i); - ref Argb32 d1 = ref Unsafe.Add(ref d0, 1); - ref Argb32 d2 = ref Unsafe.Add(ref d1, 1); - ref Argb32 d3 = ref Unsafe.Add(ref d2, 1); - - d0.R = s0.R; - d0.G = s0.G; - d0.B = s0.B; - d0.A = s0.A; - - d1.R = s1.R; - d1.G = s1.G; - d1.B = s1.B; - d1.A = s1.A; - - d2.R = s2.R; - d2.G = s2.G; - d2.B = s2.B; - d2.A = s2.A; - - d3.R = s3.R; - d3.G = s3.G; - d3.B = s3.B; - d3.A = s3.A; - } - } - - [Benchmark] - public void Default_Group4_ManualInline_V2() - { - ref Rgba32 sBase = ref this.source[0]; - ref Argb32 dBase = ref this.dest[0]; - - for (int i = 0; i < this.Count / 4; i += 4) - { - ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); - ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); - ref Rgba32 s2 = ref Unsafe.Add(ref s1, 1); - Rgba32 s3 = Unsafe.Add(ref s2, 1); - - ref Argb32 d0 = ref Unsafe.Add(ref dBase, i); - ref Argb32 d1 = ref Unsafe.Add(ref d0, 1); - ref Argb32 d2 = ref Unsafe.Add(ref d1, 1); - ref Argb32 d3 = ref Unsafe.Add(ref d2, 1); - - d0.R = s0.R; - d1.R = s1.R; - d2.R = s2.R; - d3.R = s3.R; - - d0.G = s0.G; - d1.G = s1.G; - d2.G = s2.G; - d3.G = s3.G; - - d0.B = s0.B; - d1.B = s1.B; - d2.B = s2.B; - d3.B = s3.B; - - d0.A = s0.A; - d1.A = s1.A; - d2.A = s2.A; - d3.A = s3.A; - } - } - - - [MethodImpl(MethodImplOptions.NoInlining)] - private static void Group4GenericImpl(ReadOnlySpan source, Span dest) - where TPixel : struct, IPixel - { - ref Rgba32 sBase = ref MemoryMarshal.GetReference(source); - ref TPixel dBase = ref MemoryMarshal.GetReference(dest); - - for (int i = 0; i < source.Length / 4; i += 4) - { - ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); - ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); - ref Rgba32 s2 = ref Unsafe.Add(ref s1, 1); - Rgba32 s3 = Unsafe.Add(ref s2, 1); - - ref TPixel d0 = ref Unsafe.Add(ref dBase, i); - ref TPixel d1 = ref Unsafe.Add(ref d0, 1); - ref TPixel d2 = ref Unsafe.Add(ref d1, 1); - - d0.FromRgba32(s0); - d1.FromRgba32(s1); - d2.FromRgba32(s2); - Unsafe.Add(ref d2, 1).FromRgba32(s3); - } - } - - [Benchmark] - public void Default_Group4_Generic() - { - Group4GenericImpl(this.source.AsSpan(), this.dest.AsSpan()); - } - + [Benchmark] public void BitOps() { @@ -274,5 +162,15 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion return tmp1 + tmp3; } } + + // RESULTS: + // Method | Count | Mean | Error | StdDev | Scaled | + // -------------------- |------ |----------:|----------:|----------:|-------:| + // Default | 64 | 107.33 ns | 1.0633 ns | 0.9426 ns | 1.00 | + // Default_Generic | 64 | 111.15 ns | 0.3789 ns | 0.3544 ns | 1.04 | + // Default_Group2 | 64 | 90.36 ns | 0.7779 ns | 0.6896 ns | 0.84 | + // Default_Group4 | 64 | 82.39 ns | 0.2726 ns | 0.2550 ns | 0.77 | + // BitOps | 64 | 39.25 ns | 0.3266 ns | 0.2895 ns | 0.37 | + // BitOps_GroupAsULong | 64 | 41.80 ns | 0.2227 ns | 0.2083 ns | 0.39 | } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs index 9e638dbcc..9cf16ea19 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs @@ -82,7 +82,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion ref Rgba32 sBase = ref this.source[0]; ref Bgra32 dBase = ref this.dest[0]; - for (int i = 0; i < this.Count / 2; i+=2) + for (int i = 0; i < this.Count; i+=2) { ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); Rgba32 s1 = Unsafe.Add(ref s0, 1); @@ -99,7 +99,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion ref Rgba32 sBase = ref this.source[0]; ref Bgra32 dBase = ref this.dest[0]; - for (int i = 0; i < this.Count / 4; i += 4) + for (int i = 0; i < this.Count; i += 4) { ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); @@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion Unsafe.Add(ref d2, 1).FromRgba32(s3); } } - + [MethodImpl(MethodImplOptions.NoInlining)] private static void Group4GenericImpl(ReadOnlySpan source, Span dest) where TPixel : struct, IPixel @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion ref Rgba32 sBase = ref MemoryMarshal.GetReference(source); ref TPixel dBase = ref MemoryMarshal.GetReference(dest); - for (int i = 0; i < source.Length / 4; i += 4) + for (int i = 0; i < source.Length; i += 4) { ref Rgba32 s0 = ref Unsafe.Add(ref sBase, i); ref Rgba32 s1 = ref Unsafe.Add(ref s0, 1); @@ -142,7 +142,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion } } - [Benchmark] + //[Benchmark] public void Default_Group4_Generic() { Group4GenericImpl(this.source.AsSpan(), this.dest.AsSpan()); @@ -215,7 +215,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion } } - [Benchmark] + //[Benchmark] public void Bitops_SingleTuple() { ref Tuple4OfUInt32 sBase = ref Unsafe.As(ref this.source[0]); @@ -226,7 +226,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion } } - [Benchmark] + //[Benchmark] public void Bitops_Simd() { ref Octet.OfUInt32 sBase = ref Unsafe.As(ref this.source[0]); @@ -379,15 +379,14 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion // RESULTS: - // Method | Count | Mean | Error | StdDev | Scaled | - // ----------------------- |------ |----------:|----------:|----------:|-------:| - // Default | 64 | 107.13 ns | 0.7752 ns | 0.6872 ns | 1.00 | - // Default_Generic | 64 | 113.78 ns | 0.7713 ns | 0.6022 ns | 1.06 | - // Default_Group2 | 64 | 43.72 ns | 0.1711 ns | 0.1600 ns | 0.41 | - // Default_Group4 | 64 | 23.47 ns | 0.1901 ns | 0.1588 ns | 0.22 | - // Default_Group4_Generic | 64 | 32.46 ns | 0.4297 ns | 0.4019 ns | 0.30 | - // Bitops_Tuple | 64 | 77.71 ns | 0.2779 ns | 0.2599 ns | 0.73 | - // Bitops_SingleTuple | 64 | 58.64 ns | 0.4511 ns | 0.4220 ns | 0.55 | - // Bitops_Simd | 64 | 110.58 ns | 0.4686 ns | 0.4383 ns | 1.03 | + // Method | Count | Mean | Error | StdDev | Scaled | + // -------------------- |------ |----------:|----------:|----------:|-------:| + // Default | 64 | 106.84 ns | 0.4042 ns | 0.3583 ns | 1.00 | + // Default_Generic | 64 | 113.11 ns | 0.6998 ns | 0.6203 ns | 1.06 | + // Default_Group2 | 64 | 86.81 ns | 0.4976 ns | 0.4654 ns | 0.81 | + // Default_Group4 | 64 | 83.53 ns | 1.3826 ns | 1.2933 ns | 0.78 | + // BitOps | 64 | 54.23 ns | 0.1920 ns | 0.1796 ns | 0.51 | + // Bitops_Tuple | 64 | 73.45 ns | 0.5475 ns | 0.4853 ns | 0.69 | + // BitOps_GroupAsULong | 64 | 64.28 ns | 0.4046 ns | 0.3785 ns | 0.60 | } } \ No newline at end of file From e70e7d4ab7b06fab386084c9878c72d4f85b3561 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 25 Oct 2018 02:04:55 +0200 Subject: [PATCH 07/17] Optimized bulk conversion for common pixel types --- .../Argb32.PixelOperations.Generated.cs | 117 ++++++++++++++---- .../Bgr24.PixelOperations.Generated.cs | 37 ++++++ .../Bgra32.PixelOperations.Generated.cs | 111 +++++++++++++---- .../Gray16.PixelOperations.Generated.cs | 12 ++ .../Gray8.PixelOperations.Generated.cs | 12 ++ .../Rgb24.PixelOperations.Generated.cs | 37 ++++++ .../Rgb48.PixelOperations.Generated.cs | 12 ++ .../Rgba32.PixelOperations.Generated.cs | 76 +++++++++--- .../Rgba64.PixelOperations.Generated.cs | 12 ++ .../Generated/_Common.ttinclude | 100 ++++++++++++++- .../Rgba32.PixelOperations.cs | 20 +-- .../RgbaVector.PixelOperations.cs | 8 +- .../PixelFormats/PixelOperations{TPixel}.cs | 82 ++++++++++-- 13 files changed, 537 insertions(+), 99 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs index 09f10716e..e6b8922e9 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs @@ -4,6 +4,8 @@ // using System; +using System.Buffers; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -24,6 +26,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromArgb32(Configuration configuration, ReadOnlySpan source, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); source.CopyTo(destPixels); @@ -32,109 +35,167 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); sourcePixels.CopyTo(destPixels); } - + /// - internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + { + this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + } + + /// + internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) + { + this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + } + + /// + internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + { + this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + } + + /// + internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) + { + this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + } + + /// + internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); - ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels); + ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destPixels)); for (int i = 0; i < sourcePixels.Length; i++) { - ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); - - dp.FromArgb32(sp); + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.FromArgb32.ToRgba32(sp); } } - + /// - internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + internal override void FromRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destPixels)); - ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels); + for (int i = 0; i < sourcePixels.Length; i++) + { + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.FromRgba32.ToArgb32(sp); + } + } + /// + internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destPixels)); for (int i = 0; i < sourcePixels.Length; i++) { - ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Bgra32 dp = ref Unsafe.Add(ref destRef, i); + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.FromArgb32.ToBgra32(sp); + } + } - dp.FromArgb32(sp); + /// + internal override void FromBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destPixels)); + + for (int i = 0; i < sourcePixels.Length; i++) + { + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.FromBgra32.ToArgb32(sp); } } /// - internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels); + ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels); for (int i = 0; i < sourcePixels.Length; i++) { ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Gray8 dp = ref Unsafe.Add(ref destRef, i); + ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); dp.FromArgb32(sp); } } /// - internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels); + ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels); for (int i = 0; i < sourcePixels.Length; i++) { ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Gray16 dp = ref Unsafe.Add(ref destRef, i); + ref Gray8 dp = ref Unsafe.Add(ref destRef, i); dp.FromArgb32(sp); } } /// - internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels); + ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels); for (int i = 0; i < sourcePixels.Length; i++) { ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgb24 dp = ref Unsafe.Add(ref destRef, i); + ref Gray16 dp = ref Unsafe.Add(ref destRef, i); dp.FromArgb32(sp); } } /// - internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels); + ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels); for (int i = 0; i < sourcePixels.Length; i++) { ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); + ref Rgb24 dp = ref Unsafe.Add(ref destRef, i); dp.FromArgb32(sp); } @@ -143,6 +204,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -160,6 +222,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs index f8c61e4fa..9b1740013 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs @@ -4,6 +4,8 @@ // using System; +using System.Buffers; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -24,6 +26,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromBgr24(Configuration configuration, ReadOnlySpan source, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); source.CopyTo(destPixels); @@ -32,15 +35,42 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); sourcePixels.CopyTo(destPixels); } + + /// + internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + { + this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + } + + /// + internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) + { + this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + } + + /// + internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + { + this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + } + + /// + internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) + { + this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + } + /// internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -58,6 +88,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -75,6 +106,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -92,6 +124,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -109,6 +142,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -126,6 +160,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -143,6 +178,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -160,6 +196,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs index 9bddd18e9..37d6b72d7 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs @@ -4,6 +4,8 @@ // using System; +using System.Buffers; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -24,6 +26,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromBgra32(Configuration configuration, ReadOnlySpan source, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); source.CopyTo(destPixels); @@ -32,32 +35,104 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); sourcePixels.CopyTo(destPixels); } - + + /// + internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + { + this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + } + + /// + internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) + { + this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + } + + /// + internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + { + this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + } + /// - internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) + { + this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + } + + /// + internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); - ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels); + ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destPixels)); for (int i = 0; i < sourcePixels.Length; i++) { - ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Argb32 dp = ref Unsafe.Add(ref destRef, i); + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.FromBgra32.ToRgba32(sp); + } + } - dp.FromBgra32(sp); + /// + internal override void FromRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destPixels)); + + for (int i = 0; i < sourcePixels.Length; i++) + { + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.FromRgba32.ToBgra32(sp); + } + } + /// + internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destPixels)); + + for (int i = 0; i < sourcePixels.Length; i++) + { + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.FromBgra32.ToArgb32(sp); + } + } + + /// + internal override void FromArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destPixels)); + + for (int i = 0; i < sourcePixels.Length; i++) + { + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.FromArgb32.ToBgra32(sp); } } /// internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -75,6 +150,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -92,6 +168,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -109,6 +186,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -119,23 +197,6 @@ namespace SixLabors.ImageSharp.PixelFormats ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i); ref Rgb24 dp = ref Unsafe.Add(ref destRef, i); - dp.FromBgra32(sp); - } - } - - /// - internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) - { - Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); - - ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels); - - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); - dp.FromBgra32(sp); } } @@ -143,6 +204,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -160,6 +222,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs index 31c575534..638db1d0d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs @@ -4,6 +4,8 @@ // using System; +using System.Buffers; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -24,6 +26,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromGray16(Configuration configuration, ReadOnlySpan source, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); source.CopyTo(destPixels); @@ -32,6 +35,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); sourcePixels.CopyTo(destPixels); @@ -41,6 +45,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -58,6 +63,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -75,6 +81,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -92,6 +99,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -109,6 +117,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -126,6 +135,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -143,6 +153,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -160,6 +171,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs index 14a2c858c..6bf0693c2 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs @@ -4,6 +4,8 @@ // using System; +using System.Buffers; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -24,6 +26,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromGray8(Configuration configuration, ReadOnlySpan source, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); source.CopyTo(destPixels); @@ -32,6 +35,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); sourcePixels.CopyTo(destPixels); @@ -41,6 +45,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -58,6 +63,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -75,6 +81,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -92,6 +99,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -109,6 +117,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -126,6 +135,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -143,6 +153,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -160,6 +171,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs index f8b80020e..6ff87eb38 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs @@ -4,6 +4,8 @@ // using System; +using System.Buffers; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -24,6 +26,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromRgb24(Configuration configuration, ReadOnlySpan source, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); source.CopyTo(destPixels); @@ -32,15 +35,42 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); sourcePixels.CopyTo(destPixels); } + + /// + internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + { + this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + } + + /// + internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) + { + this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + } + + /// + internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + { + this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + } + + /// + internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) + { + this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + } + /// internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -58,6 +88,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -75,6 +106,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -92,6 +124,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -109,6 +142,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -126,6 +160,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -143,6 +178,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -160,6 +196,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs index 5741b1070..9b4584d76 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs @@ -4,6 +4,8 @@ // using System; +using System.Buffers; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -24,6 +26,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromRgb48(Configuration configuration, ReadOnlySpan source, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); source.CopyTo(destPixels); @@ -32,6 +35,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); sourcePixels.CopyTo(destPixels); @@ -41,6 +45,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -58,6 +63,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -75,6 +81,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -92,6 +99,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -109,6 +117,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -126,6 +135,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -143,6 +153,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -160,6 +171,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs index 9f7b624c0..8e15ca1f4 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs @@ -4,6 +4,8 @@ // using System; +using System.Buffers; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -24,6 +26,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromRgba32(Configuration configuration, ReadOnlySpan source, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); source.CopyTo(destPixels); @@ -32,58 +35,88 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); sourcePixels.CopyTo(destPixels); } - - /// - internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + /// + internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); - ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels); + ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destPixels)); for (int i = 0; i < sourcePixels.Length; i++) { - ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Argb32 dp = ref Unsafe.Add(ref destRef, i); - - dp.FromRgba32(sp); + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.FromRgba32.ToArgb32(sp); } } - + /// - internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + internal override void FromArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destPixels)); - ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels); + for (int i = 0; i < sourcePixels.Length; i++) + { + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.FromArgb32.ToRgba32(sp); + } + } + /// + internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destPixels)); for (int i = 0; i < sourcePixels.Length; i++) { - ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.FromRgba32.ToBgra32(sp); + } + } - dp.FromRgba32(sp); + /// + internal override void FromBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destPixels)); + + for (int i = 0; i < sourcePixels.Length; i++) + { + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.FromBgra32.ToRgba32(sp); } } /// - internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels); + ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels); for (int i = 0; i < sourcePixels.Length; i++) { ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Bgra32 dp = ref Unsafe.Add(ref destRef, i); + ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); dp.FromRgba32(sp); } @@ -92,6 +125,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -109,6 +143,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -126,6 +161,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -143,6 +179,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -160,6 +197,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs index 411178b82..caaba7809 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs @@ -4,6 +4,8 @@ // using System; +using System.Buffers; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -24,6 +26,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromRgba64(Configuration configuration, ReadOnlySpan source, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); source.CopyTo(destPixels); @@ -32,6 +35,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); sourcePixels.CopyTo(destPixels); @@ -41,6 +45,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -58,6 +63,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -75,6 +81,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -92,6 +99,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -109,6 +117,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -126,6 +135,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -143,6 +153,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -160,6 +171,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude index bc23edb01..4501f4972 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude @@ -9,10 +9,17 @@ // using System; +using System.Buffers; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; <#+ - static readonly string[] CommonPixelTypeNames = { "Argb32", "Bgr24", "Bgra32", "Gray8", "Gray16", "Rgb24", "Rgba32", "Rgb48", "Rgba64" }; + static readonly string[] CommonPixelTypes = { "Argb32", "Bgr24", "Bgra32", "Gray8", "Gray16", "Rgb24", "Rgba32", "Rgb48", "Rgba64" }; + + static readonly string[] Optimized32BitTypes = { "Rgba32", "Argb32", "Bgra32" }; + + // Types with Rgba32-combatible to/from Vector4 conversion + static readonly string[] Rgba32CompatibleTypes = { "Argb32", "Bgra32", "Rgb24", "Bgr24" }; void GenerateDefaultSelfConversionMethods(string pixelType) { @@ -21,6 +28,7 @@ using System.Runtime.InteropServices; /// internal override void From<#=pixelType#>(Configuration configuration, ReadOnlySpan<<#=pixelType#>> source, Span<<#=pixelType#>> destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); source.CopyTo(destPixels); @@ -29,6 +37,7 @@ using System.Runtime.InteropServices; /// internal override void To<#=pixelType#>(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span<<#=pixelType#>> destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); sourcePixels.CopyTo(destPixels); @@ -44,6 +53,7 @@ using System.Runtime.InteropServices; /// internal override void To<#=toPixelType#>(Configuration configuration, ReadOnlySpan<<#=fromPixelType#>> sourcePixels, Span<<#=toPixelType#>> destPixels) { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); ref <#=fromPixelType#> sourceRef = ref MemoryMarshal.GetReference(sourcePixels); @@ -60,13 +70,97 @@ using System.Runtime.InteropServices; <#+ } + void GenerateOptimized32BitConversionMethods(string thisPixelType, string otherPixelType) + { + #> + /// + internal override void To<#=otherPixelType#>(Configuration configuration, ReadOnlySpan<<#=thisPixelType#>> sourcePixels, Span<<#=otherPixelType#>> destPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref uint sourceRef = ref Unsafe.As<<#=thisPixelType#>,uint>(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As<<#=otherPixelType#>, uint>(ref MemoryMarshal.GetReference(destPixels)); + + for (int i = 0; i < sourcePixels.Length; i++) + { + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.From<#=thisPixelType#>.To<#=otherPixelType#>(sp); + } + } + + /// + internal override void From<#=otherPixelType#>(Configuration configuration, ReadOnlySpan<<#=otherPixelType#>> sourcePixels, Span<<#=thisPixelType#>> destPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref uint sourceRef = ref Unsafe.As<<#=otherPixelType#>,uint>(ref MemoryMarshal.GetReference(sourcePixels)); + ref uint destRef = ref Unsafe.As<<#=thisPixelType#>, uint>(ref MemoryMarshal.GetReference(destPixels)); + + for (int i = 0; i < sourcePixels.Length; i++) + { + uint sp = Unsafe.Add(ref sourceRef, i); + Unsafe.Add(ref destRef, i) = PixelConverter.From<#=otherPixelType#>.To<#=thisPixelType#>(sp); + } + } + <#+ + } + + void GenerateRgba32CompatibleVector4ConversionMethods(string pixelType) + { + #> + + /// + internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span<<#=pixelType#>> destPixels) + { + this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + } + + /// + internal override void ToVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors) + { + this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + } + + /// + internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span<<#=pixelType#>> destPixels) + { + this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + } + + /// + internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors) + { + this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + } + + <#+ + } + void GenerateAllDefaultConversionMethods(string pixelType) { GenerateDefaultSelfConversionMethods(pixelType); - var allOtherPixelTypes = CommonPixelTypeNames.Where(p => p != pixelType); + if (Rgba32CompatibleTypes.Contains(pixelType)) + { + GenerateRgba32CompatibleVector4ConversionMethods(pixelType); + } + + var matching32BitTypes = Optimized32BitTypes.Contains(pixelType) ? + Optimized32BitTypes.Where(p => p != pixelType) : + Enumerable.Empty(); + + foreach (string destPixelType in matching32BitTypes) + { + GenerateOptimized32BitConversionMethods(pixelType, destPixelType); + } + + var otherCommonNon32Types = CommonPixelTypes + .Where(p => p != pixelType) + .Except(matching32BitTypes); - foreach (string destPixelType in allOtherPixelTypes) + foreach (string destPixelType in otherCommonNon32Types) { GenerateDefaultConvertToMethod(pixelType, destPixelType); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs index 0f5ddf372..004b25cd3 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs @@ -21,31 +21,31 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToVector4( Configuration configuration, - ReadOnlySpan sourceColors, - Span destinationVectors) + ReadOnlySpan sourcePixels, + Span destVectors) { - Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); - destinationVectors = destinationVectors.Slice(0, sourceColors.Length); + destVectors = destVectors.Slice(0, sourcePixels.Length); SimdUtils.BulkConvertByteToNormalizedFloat( - MemoryMarshal.Cast(sourceColors), - MemoryMarshal.Cast(destinationVectors)); + MemoryMarshal.Cast(sourcePixels), + MemoryMarshal.Cast(destVectors)); } /// internal override void FromVector4( Configuration configuration, ReadOnlySpan sourceVectors, - Span destinationColors) + Span destPixels) { - Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors)); + Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); - destinationColors = destinationColors.Slice(0, sourceVectors.Length); + destPixels = destPixels.Slice(0, sourceVectors.Length); SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows( MemoryMarshal.Cast(sourceVectors), - MemoryMarshal.Cast(destinationColors)); + MemoryMarshal.Cast(destPixels)); } /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs index cb12d944c..bffaf57dd 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs @@ -38,12 +38,12 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void ToVector4( Configuration configuration, - ReadOnlySpan sourceColors, - Span destinationVectors) + ReadOnlySpan sourcePixels, + Span destVectors) { - Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); - MemoryMarshal.Cast(sourceColors).CopyTo(destinationVectors); + MemoryMarshal.Cast(sourcePixels).CopyTo(destVectors); } } } diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index ad5aee8c7..3cebf7b54 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -26,17 +27,17 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// A to configure internal operations /// The to the source vectors. - /// The to the destination colors. + /// The to the destination colors. internal virtual void FromVector4( Configuration configuration, ReadOnlySpan sourceVectors, - Span destinationColors) + Span destPixels) { Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors)); + Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); - ref TPixel destRef = ref MemoryMarshal.GetReference(destinationColors); + ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels); for (int i = 0; i < sourceVectors.Length; i++) { @@ -50,20 +51,20 @@ namespace SixLabors.ImageSharp.PixelFormats /// Bulk version of converting 'sourceColors.Length' pixels into 'destinationVectors'. /// /// A to configure internal operations - /// The to the source colors. - /// The to the destination vectors. + /// The to the source colors. + /// The to the destination vectors. internal virtual void ToVector4( Configuration configuration, - ReadOnlySpan sourceColors, - Span destinationVectors) + ReadOnlySpan sourcePixels, + Span destVectors) { Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); - ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors); - ref Vector4 destRef = ref MemoryMarshal.GetReference(destinationVectors); + ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourcePixels); + ref Vector4 destRef = ref MemoryMarshal.GetReference(destVectors); - for (int i = 0; i < sourceColors.Length; i++) + for (int i = 0; i < sourcePixels.Length; i++) { ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); ref Vector4 dp = ref Unsafe.Add(ref destRef, i); @@ -178,5 +179,62 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromScaledVector4(sp.ToScaledVector4()); } } + + /// + /// Provides an efficient default implementation for and + /// which is applicable for -compatible pixel types where + /// returns the same scaled result as . + /// The method is works by internally converting to a therefore it's not applicable for that type! + /// + [MethodImpl(InliningOptions.ShortMethod)] + internal void RunRgba32CompatibleToVector4Conversion( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destVectors) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); + + int count = sourcePixels.Length; + + using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(count)) + { + Span tempSpan = tempBuffer.Memory.Span; + this.ToRgba32(configuration, sourcePixels, tempSpan); + + SimdUtils.BulkConvertByteToNormalizedFloat( + MemoryMarshal.Cast(tempSpan), + MemoryMarshal.Cast(destVectors)); + } + } + + /// + /// Provides an efficient default implementation for and + /// which is applicable for -compatible pixel types where + /// returns the same scaled result as . + /// The method is works by internally converting to a therefore it's not applicable for that type! + /// + [MethodImpl(InliningOptions.ShortMethod)] + internal void RunRgba32CompatibleFromVector4Conversion( + Configuration configuration, + ReadOnlySpan sourceVectors, + Span destPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); + + int count = sourceVectors.Length; + + using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(count)) + { + Span tempSpan = tempBuffer.Memory.Span; + + SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows( + MemoryMarshal.Cast(sourceVectors), + MemoryMarshal.Cast(tempSpan)); + + this.FromRgba32(configuration, tempSpan, destPixels); + } + } } } \ No newline at end of file From 0fc01d75f454babd74b295cd329df817a32b4b1e Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 25 Oct 2018 02:43:02 +0200 Subject: [PATCH 08/17] run default implementation for small buffers --- .../PixelFormats/PixelOperations{TPixel}.cs | 63 +++++++++++++------ .../Color/Bulk/ToVector4.cs | 28 ++++++--- 2 files changed, 66 insertions(+), 25 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 3cebf7b54..c3d8e23b9 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -36,15 +36,7 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); - ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); - ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels); - - for (int i = 0; i < sourceVectors.Length; i++) - { - ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i); - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - dp.FromVector4(sp); - } + FromVector4DefaultImpl(sourceVectors, destPixels); } /// @@ -61,15 +53,7 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); - ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Vector4 destRef = ref MemoryMarshal.GetReference(destVectors); - - for (int i = 0; i < sourcePixels.Length; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - ref Vector4 dp = ref Unsafe.Add(ref destRef, i); - dp = sp.ToVector4(); - } + ToVector4DefaultImpl(sourcePixels, destVectors); } /// @@ -135,6 +119,7 @@ namespace SixLabors.ImageSharp.PixelFormats Span destinationColors) where TDestinationPixel : struct, IPixel { + Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourceColors, destinationColors, nameof(destinationColors)); int count = sourceColors.Length; @@ -197,6 +182,13 @@ namespace SixLabors.ImageSharp.PixelFormats int count = sourcePixels.Length; + // Not worth for small buffers: + if (count < 128) + { + ToVector4DefaultImpl(sourcePixels, destVectors); + return; + } + using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(count)) { Span tempSpan = tempBuffer.Memory.Span; @@ -225,6 +217,13 @@ namespace SixLabors.ImageSharp.PixelFormats int count = sourceVectors.Length; + // Not worth for small buffers: + if (count < 128) + { + FromVector4DefaultImpl(sourceVectors, destPixels); + return; + } + using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(count)) { Span tempSpan = tempBuffer.Memory.Span; @@ -236,5 +235,33 @@ namespace SixLabors.ImageSharp.PixelFormats this.FromRgba32(configuration, tempSpan, destPixels); } } + + [MethodImpl(InliningOptions.ShortMethod)] + private static void FromVector4DefaultImpl(ReadOnlySpan sourceVectors, Span destPixels) + { + ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); + ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels); + + for (int i = 0; i < sourceVectors.Length; i++) + { + ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i); + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + dp.FromVector4(sp); + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + private static void ToVector4DefaultImpl(ReadOnlySpan sourcePixels, Span destVectors) + { + ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourcePixels); + ref Vector4 destRef = ref MemoryMarshal.GetReference(destVectors); + + for (int i = 0; i < sourcePixels.Length; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); + ref Vector4 dp = ref Unsafe.Add(ref destRef, i); + dp = sp.ToVector4(); + } + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs index f0fee649a..897badd9f 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk [Params( 64, - //256, + 256, //512, //1024, 2048)] @@ -58,20 +58,25 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk d[i] = s[i].ToVector4(); } } + [Benchmark] - public void PixelOperations_Base() + public void PixelOperations_Specialized() { - new PixelOperations().ToVector4( + PixelOperations.Instance.ToVector4( this.Configuration, this.source.GetSpan(), this.destination.GetSpan()); } + } - [Benchmark] - public void PixelOperations_Specialized() + [Config(typeof(Config.ShortClr))] + public class ToVector4_Bgra32 : ToVector4 + { + [Benchmark(Baseline = true)] + public void PixelOperations_Base() { - PixelOperations.Instance.ToVector4( + new PixelOperations().ToVector4( this.Configuration, this.source.GetSpan(), this.destination.GetSpan()); @@ -89,7 +94,16 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk SimdUtils.FallbackIntrinsics128.BulkConvertByteToNormalizedFloat(sBytes, dFloats); } - + + [Benchmark] + public void PixelOperations_Base() + { + new PixelOperations().ToVector4( + this.Configuration, + this.source.GetSpan(), + this.destination.GetSpan()); + } + [Benchmark(Baseline = true)] public void BasicIntrinsics256() { From d154c45007cc56cc44f29deabcdcc2de0eb44749 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 26 Oct 2018 14:30:11 +0200 Subject: [PATCH 09/17] fix Gray8.ToString() --- src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs index d23fda799..4ed5904c2 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs @@ -140,7 +140,7 @@ namespace SixLabors.ImageSharp.PixelFormats public bool Equals(Gray8 other) => this.PackedValue.Equals(other.PackedValue); /// - public override string ToString() => $"Gray8({this.PackedValue}"; + public override string ToString() => $"Gray8({this.PackedValue})"; /// [MethodImpl(InliningOptions.ShortMethod)] From b87c93e1951fa2b63be8c394b645fa68eb422d6e Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 26 Oct 2018 15:18:26 +0200 Subject: [PATCH 10/17] benchmakrs --- .../Color/Bulk/FromRgba32Bytes.cs | 28 ++- .../Color/Bulk/{ToXyz.cs => Rgb24Bytes.cs} | 4 +- .../Bulk/{ToXyzw.cs => ToRgba32Bytes.cs} | 16 +- .../Color/Bulk/ToVector4.cs | 169 +----------------- .../Color/Bulk/ToVector4_Bgra32.cs | 20 +++ .../Color/Bulk/ToVector4_Rgba32.cs | 164 +++++++++++++++++ .../PixelConversion_Rgba32_To_Bgra32.cs | 24 +-- 7 files changed, 232 insertions(+), 193 deletions(-) rename tests/ImageSharp.Benchmarks/Color/Bulk/{ToXyz.cs => Rgb24Bytes.cs} (94%) rename tests/ImageSharp.Benchmarks/Color/Bulk/{ToXyzw.cs => ToRgba32Bytes.cs} (87%) create mode 100644 tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs create mode 100644 tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/FromRgba32Bytes.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/FromRgba32Bytes.cs index 32565c23d..b96422176 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/FromRgba32Bytes.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/FromRgba32Bytes.cs @@ -22,7 +22,10 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk private Configuration configuration; - [Params(16, 128, 1024)] + [Params( + 128, + 1024, + 2048)] public int Count { get; set; } [GlobalSetup] @@ -40,8 +43,8 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk this.source.Dispose(); } - [Benchmark(Baseline = true)] - public void PerElement() + //[Benchmark] + public void Naive() { Span s = this.source.GetSpan(); Span d = this.destination.GetSpan(); @@ -55,7 +58,7 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk } } - [Benchmark] + [Benchmark(Baseline = true)] public void CommonBulk() { new PixelOperations().FromRgba32Bytes(this.configuration, this.source.GetSpan(), this.destination.GetSpan(), this.Count); @@ -68,7 +71,22 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk } } - public class FromRgba32BytesRgba32 : FromRgba32Bytes + public class FromRgba32Bytes_ToRgba32 : FromRgba32Bytes + { + } + + public class FromRgba32Bytes_ToBgra32 : FromRgba32Bytes { + // RESULTS: + // Method | Count | Mean | Error | StdDev | Scaled | + // -------------- |------ |-----------:|----------:|----------:|-------:| + // CommonBulk | 128 | 207.1 ns | 3.723 ns | 3.300 ns | 1.00 | + // OptimizedBulk | 128 | 166.5 ns | 1.204 ns | 1.005 ns | 0.80 | + // | | | | | | + // CommonBulk | 1024 | 1,333.9 ns | 12.426 ns | 11.624 ns | 1.00 | + // OptimizedBulk | 1024 | 974.1 ns | 18.803 ns | 16.669 ns | 0.73 | + // | | | | | | + // CommonBulk | 2048 | 2,625.4 ns | 30.143 ns | 26.721 ns | 1.00 | + // OptimizedBulk | 2048 | 1,843.0 ns | 20.505 ns | 18.177 ns | 0.70 | } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/Rgb24Bytes.cs similarity index 94% rename from tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs rename to tests/ImageSharp.Benchmarks/Color/Bulk/Rgb24Bytes.cs index 912c3e4b2..294baa9d5 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/Rgb24Bytes.cs @@ -10,7 +10,7 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk { - public abstract class ToXyz + public abstract class Rgb24Bytes where TPixel : struct, IPixel { private IMemoryOwner source; @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk this.Count); } - public class ToXyz_Rgba32 : ToXyz + public class Rgb24Bytes_Rgba32 : Rgb24Bytes { } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToRgba32Bytes.cs similarity index 87% rename from tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs rename to tests/ImageSharp.Benchmarks/Color/Bulk/ToRgba32Bytes.cs index 37694f64c..7f4b2bc41 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToRgba32Bytes.cs @@ -12,7 +12,7 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk { - public abstract class ToXyzw + public abstract class ToRgba32Bytes where TPixel : struct, IPixel { private IMemoryOwner source; @@ -39,8 +39,8 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk this.destination.Dispose(); } - [Benchmark(Baseline = true)] - public void PerElement() + //[Benchmark] + public void Naive() { Span s = this.source.GetSpan(); Span d = this.destination.GetSpan(); @@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk } } - [Benchmark] + [Benchmark(Baseline = true)] public void CommonBulk() => new PixelOperations().ToRgba32Bytes( this.configuration, @@ -75,11 +75,15 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk this.Count); } - public class ToXyzw_Rgba32 : ToXyzw + public class ToRgba32Bytes_FromRgba32 : ToRgba32Bytes + { + } + + public class ToRgba32Bytes_FromArgb32 : ToRgba32Bytes { } - public class ToXyzw_Argb32 : ToXyzw + public class ToRgba32Bytes_FromBgra32 : ToRgba32Bytes { } } diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs index 897badd9f..70de8f4e2 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs @@ -6,8 +6,6 @@ using System.Buffers; using System; using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; @@ -48,7 +46,7 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk } //[Benchmark] - public void PerElement() + public void Naive() { Span s = this.source.GetSpan(); Span d = this.destination.GetSpan(); @@ -69,169 +67,4 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk this.destination.GetSpan()); } } - - [Config(typeof(Config.ShortClr))] - public class ToVector4_Bgra32 : ToVector4 - { - [Benchmark(Baseline = true)] - public void PixelOperations_Base() - { - new PixelOperations().ToVector4( - this.Configuration, - this.source.GetSpan(), - this.destination.GetSpan()); - } - } - - [Config(typeof(Config.ShortClr))] - public class ToVector4_Rgba32 : ToVector4 - { - [Benchmark] - public void FallbackIntrinsics128() - { - Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); - Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); - - SimdUtils.FallbackIntrinsics128.BulkConvertByteToNormalizedFloat(sBytes, dFloats); - } - - [Benchmark] - public void PixelOperations_Base() - { - new PixelOperations().ToVector4( - this.Configuration, - this.source.GetSpan(), - this.destination.GetSpan()); - } - - [Benchmark(Baseline = true)] - public void BasicIntrinsics256() - { - Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); - Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); - - SimdUtils.BasicIntrinsics256.BulkConvertByteToNormalizedFloat(sBytes, dFloats); - } - - [Benchmark] - public void ExtendedIntrinsics() - { - Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); - Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); - - SimdUtils.ExtendedIntrinsics.BulkConvertByteToNormalizedFloat(sBytes, dFloats); - } - - //[Benchmark] - public void ExtendedIntrinsics_BulkConvertByteToNormalizedFloat_2Loops() - { - Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); - Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); - - int n = dFloats.Length / Vector.Count; - - ref Vector sourceBase = ref Unsafe.As>(ref MemoryMarshal.GetReference((ReadOnlySpan)sBytes)); - ref Vector destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dFloats)); - ref Vector destBaseU = ref Unsafe.As, Vector>(ref destBase); - - for (int i = 0; i < n; i++) - { - Vector b = Unsafe.Add(ref sourceBase, i); - - Vector.Widen(b, out Vector s0, out Vector s1); - Vector.Widen(s0, out Vector w0, out Vector w1); - Vector.Widen(s1, out Vector w2, out Vector w3); - - ref Vector d = ref Unsafe.Add(ref destBaseU, i * 4); - d = w0; - Unsafe.Add(ref d, 1) = w1; - Unsafe.Add(ref d, 2) = w2; - Unsafe.Add(ref d, 3) = w3; - } - - n = dFloats.Length / Vector.Count; - var scale = new Vector(1f / 255f); - - for (int i = 0; i < n; i++) - { - ref Vector dRef = ref Unsafe.Add(ref destBase, i); - - Vector du = Vector.AsVectorInt32(dRef); - Vector v = Vector.ConvertToSingle(du); - v *= scale; - - dRef = v; - } - } - - //[Benchmark] - public void ExtendedIntrinsics_BulkConvertByteToNormalizedFloat_ConvertInSameLoop() - { - Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); - Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); - - int n = dFloats.Length / Vector.Count; - - ref Vector sourceBase = ref Unsafe.As>(ref MemoryMarshal.GetReference((ReadOnlySpan)sBytes)); - ref Vector destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dFloats)); - var scale = new Vector(1f / 255f); - - for (int i = 0; i < n; i++) - { - Vector b = Unsafe.Add(ref sourceBase, i); - - Vector.Widen(b, out Vector s0, out Vector s1); - Vector.Widen(s0, out Vector w0, out Vector w1); - Vector.Widen(s1, out Vector w2, out Vector w3); - - Vector f0 = ConvertToNormalizedSingle(w0, scale); - Vector f1 = ConvertToNormalizedSingle(w1, scale); - Vector f2 = ConvertToNormalizedSingle(w2, scale); - Vector f3 = ConvertToNormalizedSingle(w3, scale); - - ref Vector d = ref Unsafe.Add(ref destBase, i * 4); - d = f0; - Unsafe.Add(ref d, 1) = f1; - Unsafe.Add(ref d, 2) = f2; - Unsafe.Add(ref d, 3) = f3; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector ConvertToNormalizedSingle(Vector u, Vector scale) - { - Vector vi = Vector.AsVectorInt32(u); - Vector v = Vector.ConvertToSingle(vi); - v *= scale; - return v; - } - - // RESULTS (2018 October): - // - // Method | Runtime | Count | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated | - // ---------------------------- |-------- |------ |------------:|-------------:|------------:|-------:|---------:|-------:|----------:| - // FallbackIntrinsics128 | Clr | 64 | 287.62 ns | 6.026 ns | 0.3405 ns | 1.19 | 0.00 | - | 0 B | - // BasicIntrinsics256 | Clr | 64 | 240.83 ns | 10.585 ns | 0.5981 ns | 1.00 | 0.00 | - | 0 B | - // ExtendedIntrinsics | Clr | 64 | 168.28 ns | 11.478 ns | 0.6485 ns | 0.70 | 0.00 | - | 0 B | - // PixelOperations_Base | Clr | 64 | 334.08 ns | 38.048 ns | 2.1498 ns | 1.39 | 0.01 | 0.0072 | 24 B | - // PixelOperations_Specialized | Clr | 64 | 255.41 ns | 10.939 ns | 0.6181 ns | 1.06 | 0.00 | - | 0 B | <--- ceremonial overhead has been minimized! - // | | | | | | | | | | - // FallbackIntrinsics128 | Core | 64 | 183.29 ns | 8.931 ns | 0.5046 ns | 1.32 | 0.00 | - | 0 B | - // BasicIntrinsics256 | Core | 64 | 139.18 ns | 7.633 ns | 0.4313 ns | 1.00 | 0.00 | - | 0 B | - // ExtendedIntrinsics | Core | 64 | 66.29 ns | 16.366 ns | 0.9247 ns | 0.48 | 0.01 | - | 0 B | - // PixelOperations_Base | Core | 64 | 257.75 ns | 16.959 ns | 0.9582 ns | 1.85 | 0.01 | 0.0072 | 24 B | - // PixelOperations_Specialized | Core | 64 | 90.14 ns | 9.955 ns | 0.5625 ns | 0.65 | 0.00 | - | 0 B | - // | | | | | | | | | | - // FallbackIntrinsics128 | Clr | 2048 | 5,011.84 ns | 347.991 ns | 19.6621 ns | 1.22 | 0.01 | - | 0 B | - // BasicIntrinsics256 | Clr | 2048 | 4,119.35 ns | 720.153 ns | 40.6900 ns | 1.00 | 0.00 | - | 0 B | - // ExtendedIntrinsics | Clr | 2048 | 1,195.29 ns | 164.389 ns | 9.2883 ns |!! 0.29 | 0.00 | - | 0 B | <--- ExtendedIntrinsics rock! - // PixelOperations_Base | Clr | 2048 | 6,820.58 ns | 823.433 ns | 46.5255 ns | 1.66 | 0.02 | - | 24 B | - // PixelOperations_Specialized | Clr | 2048 | 4,203.53 ns | 176.714 ns | 9.9847 ns | 1.02 | 0.01 | - | 0 B | <--- can't yet detect whether ExtendedIntrinsics are available :( - // | | | | | | | | | | - // FallbackIntrinsics128 | Core | 2048 | 5,017.89 ns | 4,021.533 ns | 227.2241 ns | 1.24 | 0.05 | - | 0 B | - // BasicIntrinsics256 | Core | 2048 | 4,046.51 ns | 1,150.390 ns | 64.9992 ns | 1.00 | 0.00 | - | 0 B | - // ExtendedIntrinsics | Core | 2048 | 1,130.59 ns | 832.588 ns | 47.0427 ns |!! 0.28 | 0.01 | - | 0 B | <--- ExtendedIntrinsics rock! - // PixelOperations_Base | Core | 2048 | 6,752.68 ns | 272.820 ns | 15.4148 ns | 1.67 | 0.02 | - | 24 B | - // PixelOperations_Specialized | Core | 2048 | 1,126.13 ns | 79.192 ns | 4.4745 ns |!! 0.28 | 0.00 | - | 0 B | <--- ExtendedIntrinsics rock! - } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs new file mode 100644 index 000000000..028bfe46f --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs @@ -0,0 +1,20 @@ +using BenchmarkDotNet.Attributes; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk +{ + [Config(typeof(Config.ShortClr))] + public class ToVector4_Bgra32 : ToVector4 + { + [Benchmark(Baseline = true)] + public void PixelOperations_Base() + { + new PixelOperations().ToVector4( + this.Configuration, + this.source.GetSpan(), + this.destination.GetSpan()); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs new file mode 100644 index 000000000..ab05a1407 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs @@ -0,0 +1,164 @@ +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using BenchmarkDotNet.Attributes; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk +{ + [Config(typeof(Config.ShortClr))] + public class ToVector4_Rgba32 : ToVector4 + { + [Benchmark] + public void FallbackIntrinsics128() + { + Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); + Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); + + SimdUtils.FallbackIntrinsics128.BulkConvertByteToNormalizedFloat(sBytes, dFloats); + } + + [Benchmark] + public void PixelOperations_Base() + { + new PixelOperations().ToVector4( + this.Configuration, + this.source.GetSpan(), + this.destination.GetSpan()); + } + + [Benchmark(Baseline = true)] + public void BasicIntrinsics256() + { + Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); + Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); + + SimdUtils.BasicIntrinsics256.BulkConvertByteToNormalizedFloat(sBytes, dFloats); + } + + [Benchmark] + public void ExtendedIntrinsics() + { + Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); + Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); + + SimdUtils.ExtendedIntrinsics.BulkConvertByteToNormalizedFloat(sBytes, dFloats); + } + + //[Benchmark] + public void ExtendedIntrinsics_BulkConvertByteToNormalizedFloat_2Loops() + { + Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); + Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); + + int n = dFloats.Length / Vector.Count; + + ref Vector sourceBase = ref Unsafe.As>(ref MemoryMarshal.GetReference((ReadOnlySpan)sBytes)); + ref Vector destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dFloats)); + ref Vector destBaseU = ref Unsafe.As, Vector>(ref destBase); + + for (int i = 0; i < n; i++) + { + Vector b = Unsafe.Add(ref sourceBase, i); + + Vector.Widen(b, out Vector s0, out Vector s1); + Vector.Widen(s0, out Vector w0, out Vector w1); + Vector.Widen(s1, out Vector w2, out Vector w3); + + ref Vector d = ref Unsafe.Add(ref destBaseU, i * 4); + d = w0; + Unsafe.Add(ref d, 1) = w1; + Unsafe.Add(ref d, 2) = w2; + Unsafe.Add(ref d, 3) = w3; + } + + n = dFloats.Length / Vector.Count; + var scale = new Vector(1f / 255f); + + for (int i = 0; i < n; i++) + { + ref Vector dRef = ref Unsafe.Add(ref destBase, i); + + Vector du = Vector.AsVectorInt32(dRef); + Vector v = Vector.ConvertToSingle(du); + v *= scale; + + dRef = v; + } + } + + //[Benchmark] + public void ExtendedIntrinsics_BulkConvertByteToNormalizedFloat_ConvertInSameLoop() + { + Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); + Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); + + int n = dFloats.Length / Vector.Count; + + ref Vector sourceBase = ref Unsafe.As>(ref MemoryMarshal.GetReference((ReadOnlySpan)sBytes)); + ref Vector destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dFloats)); + var scale = new Vector(1f / 255f); + + for (int i = 0; i < n; i++) + { + Vector b = Unsafe.Add(ref sourceBase, i); + + Vector.Widen(b, out Vector s0, out Vector s1); + Vector.Widen(s0, out Vector w0, out Vector w1); + Vector.Widen(s1, out Vector w2, out Vector w3); + + Vector f0 = ConvertToNormalizedSingle(w0, scale); + Vector f1 = ConvertToNormalizedSingle(w1, scale); + Vector f2 = ConvertToNormalizedSingle(w2, scale); + Vector f3 = ConvertToNormalizedSingle(w3, scale); + + ref Vector d = ref Unsafe.Add(ref destBase, i * 4); + d = f0; + Unsafe.Add(ref d, 1) = f1; + Unsafe.Add(ref d, 2) = f2; + Unsafe.Add(ref d, 3) = f3; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector ConvertToNormalizedSingle(Vector u, Vector scale) + { + Vector vi = Vector.AsVectorInt32(u); + Vector v = Vector.ConvertToSingle(vi); + v *= scale; + return v; + } + + // RESULTS (2018 October): + // + // Method | Runtime | Count | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated | + // ---------------------------- |-------- |------ |------------:|-------------:|------------:|-------:|---------:|-------:|----------:| + // FallbackIntrinsics128 | Clr | 64 | 287.62 ns | 6.026 ns | 0.3405 ns | 1.19 | 0.00 | - | 0 B | + // BasicIntrinsics256 | Clr | 64 | 240.83 ns | 10.585 ns | 0.5981 ns | 1.00 | 0.00 | - | 0 B | + // ExtendedIntrinsics | Clr | 64 | 168.28 ns | 11.478 ns | 0.6485 ns | 0.70 | 0.00 | - | 0 B | + // PixelOperations_Base | Clr | 64 | 334.08 ns | 38.048 ns | 2.1498 ns | 1.39 | 0.01 | 0.0072 | 24 B | + // PixelOperations_Specialized | Clr | 64 | 255.41 ns | 10.939 ns | 0.6181 ns | 1.06 | 0.00 | - | 0 B | <--- ceremonial overhead has been minimized! + // | | | | | | | | | | + // FallbackIntrinsics128 | Core | 64 | 183.29 ns | 8.931 ns | 0.5046 ns | 1.32 | 0.00 | - | 0 B | + // BasicIntrinsics256 | Core | 64 | 139.18 ns | 7.633 ns | 0.4313 ns | 1.00 | 0.00 | - | 0 B | + // ExtendedIntrinsics | Core | 64 | 66.29 ns | 16.366 ns | 0.9247 ns | 0.48 | 0.01 | - | 0 B | + // PixelOperations_Base | Core | 64 | 257.75 ns | 16.959 ns | 0.9582 ns | 1.85 | 0.01 | 0.0072 | 24 B | + // PixelOperations_Specialized | Core | 64 | 90.14 ns | 9.955 ns | 0.5625 ns | 0.65 | 0.00 | - | 0 B | + // | | | | | | | | | | + // FallbackIntrinsics128 | Clr | 2048 | 5,011.84 ns | 347.991 ns | 19.6621 ns | 1.22 | 0.01 | - | 0 B | + // BasicIntrinsics256 | Clr | 2048 | 4,119.35 ns | 720.153 ns | 40.6900 ns | 1.00 | 0.00 | - | 0 B | + // ExtendedIntrinsics | Clr | 2048 | 1,195.29 ns | 164.389 ns | 9.2883 ns |!! 0.29 | 0.00 | - | 0 B | <--- ExtendedIntrinsics rock! + // PixelOperations_Base | Clr | 2048 | 6,820.58 ns | 823.433 ns | 46.5255 ns | 1.66 | 0.02 | - | 24 B | + // PixelOperations_Specialized | Clr | 2048 | 4,203.53 ns | 176.714 ns | 9.9847 ns | 1.02 | 0.01 | - | 0 B | <--- can't yet detect whether ExtendedIntrinsics are available :( + // | | | | | | | | | | + // FallbackIntrinsics128 | Core | 2048 | 5,017.89 ns | 4,021.533 ns | 227.2241 ns | 1.24 | 0.05 | - | 0 B | + // BasicIntrinsics256 | Core | 2048 | 4,046.51 ns | 1,150.390 ns | 64.9992 ns | 1.00 | 0.00 | - | 0 B | + // ExtendedIntrinsics | Core | 2048 | 1,130.59 ns | 832.588 ns | 47.0427 ns |!! 0.28 | 0.01 | - | 0 B | <--- ExtendedIntrinsics rock! + // PixelOperations_Base | Core | 2048 | 6,752.68 ns | 272.820 ns | 15.4148 ns | 1.67 | 0.02 | - | 24 B | + // PixelOperations_Specialized | Core | 2048 | 1,126.13 ns | 79.192 ns | 4.4745 ns |!! 0.28 | 0.00 | - | 0 B | <--- ExtendedIntrinsics rock! + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs index 9cf16ea19..a8fea6866 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs @@ -12,7 +12,7 @@ using SixLabors.ImageSharp.Tuples; namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion { //[MonoJob] - [RyuJitX64Job] + //[RyuJitX64Job] public class PixelConversion_Rgba32_To_Bgra32 { private Rgba32[] source; @@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion for (int i = 0; i < this.Count; i++) { - Rgba32 s = Unsafe.Add(ref sBase, i); + ref Rgba32 s = ref Unsafe.Add(ref sBase, i); Unsafe.Add(ref dBase, i).FromRgba32(s); } } @@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion for (int i = 0; i < source.Length; i++) { - Rgba32 s = Unsafe.Add(ref sBase, i); + ref Rgba32 s = ref Unsafe.Add(ref sBase, i); Unsafe.Add(ref dBase, i).FromRgba32(s); } } @@ -379,14 +379,14 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion // RESULTS: - // Method | Count | Mean | Error | StdDev | Scaled | - // -------------------- |------ |----------:|----------:|----------:|-------:| - // Default | 64 | 106.84 ns | 0.4042 ns | 0.3583 ns | 1.00 | - // Default_Generic | 64 | 113.11 ns | 0.6998 ns | 0.6203 ns | 1.06 | - // Default_Group2 | 64 | 86.81 ns | 0.4976 ns | 0.4654 ns | 0.81 | - // Default_Group4 | 64 | 83.53 ns | 1.3826 ns | 1.2933 ns | 0.78 | - // BitOps | 64 | 54.23 ns | 0.1920 ns | 0.1796 ns | 0.51 | - // Bitops_Tuple | 64 | 73.45 ns | 0.5475 ns | 0.4853 ns | 0.69 | - // BitOps_GroupAsULong | 64 | 64.28 ns | 0.4046 ns | 0.3785 ns | 0.60 | + // Method | Count | Mean | Error | StdDev | Scaled | ScaledSD | + // -------------------- |------ |---------:|----------:|----------:|-------:|---------:| + // Default | 64 | 82.67 ns | 0.6737 ns | 0.5625 ns | 1.00 | 0.00 | + // Default_Generic | 64 | 88.73 ns | 1.7959 ns | 1.7638 ns | 1.07 | 0.02 | + // Default_Group2 | 64 | 91.03 ns | 1.5237 ns | 1.3508 ns | 1.10 | 0.02 | + // Default_Group4 | 64 | 86.62 ns | 1.5737 ns | 1.4720 ns | 1.05 | 0.02 | + // BitOps | 64 | 57.45 ns | 0.6067 ns | 0.5066 ns | 0.69 | 0.01 | + // Bitops_Tuple | 64 | 75.47 ns | 1.1824 ns | 1.1060 ns | 0.91 | 0.01 | + // BitOps_GroupAsULong | 64 | 65.42 ns | 0.7157 ns | 0.6695 ns | 0.79 | 0.01 | } } \ No newline at end of file From 9fa08b22574dbb0cfb041d72b0de49758e899cfd Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 26 Oct 2018 15:18:40 +0200 Subject: [PATCH 11/17] Vector4ConversionThreshold --- .../PixelFormats/PixelOperations{TPixel}.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index c3d8e23b9..668b2d031 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -17,6 +17,12 @@ namespace SixLabors.ImageSharp.PixelFormats public partial class PixelOperations where TPixel : struct, IPixel { + /// + /// It's not worth to bother the transitive pixel conversion method below this limit. + /// The value depends on the actual gain brought by the SIMD characteristics of the executing CPU and JIT. + /// + private static readonly int Vector4ConversionThreshold = CalculateVector4ConversionThreshold(); + /// /// Gets the global instance for the pixel type /// @@ -183,7 +189,7 @@ namespace SixLabors.ImageSharp.PixelFormats int count = sourcePixels.Length; // Not worth for small buffers: - if (count < 128) + if (count < Vector4ConversionThreshold) { ToVector4DefaultImpl(sourcePixels, destVectors); return; @@ -218,7 +224,7 @@ namespace SixLabors.ImageSharp.PixelFormats int count = sourceVectors.Length; // Not worth for small buffers: - if (count < 128) + if (count < Vector4ConversionThreshold) { FromVector4DefaultImpl(sourceVectors, destPixels); return; @@ -263,5 +269,15 @@ namespace SixLabors.ImageSharp.PixelFormats dp = sp.ToVector4(); } } + + private static int CalculateVector4ConversionThreshold() + { + if (!Vector.IsHardwareAccelerated) + { + return int.MaxValue; + } + + return SimdUtils.ExtendedIntrinsics.IsAvailable && SimdUtils.IsAvx2CompatibleArchitecture ? 256 : 128; + } } } \ No newline at end of file From 5a1cd3ade47a999f2711e2abe44f42d04e0405d6 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 26 Oct 2018 15:51:53 +0200 Subject: [PATCH 12/17] avoid allocation in RunRgba32CompatibleToVector4Conversion --- .../PixelFormats/PixelOperations{TPixel}.cs | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 668b2d031..9238e1b47 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -171,6 +171,8 @@ namespace SixLabors.ImageSharp.PixelFormats } } + // TODO: The Vector4 helpers should be moved to a utility class. + /// /// Provides an efficient default implementation for and /// which is applicable for -compatible pixel types where @@ -195,15 +197,19 @@ namespace SixLabors.ImageSharp.PixelFormats return; } - using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(count)) - { - Span tempSpan = tempBuffer.Memory.Span; - this.ToRgba32(configuration, sourcePixels, tempSpan); + // Using the last quarter of 'destVectors' as a temporary buffer to avoid allocation: + int countWithoutLastItem = count - 1; + ReadOnlySpan reducedSource = sourcePixels.Slice(0, countWithoutLastItem); + Span lastQuarterOfDestBuffer = MemoryMarshal.Cast(destVectors).Slice((3 * count) + 1, countWithoutLastItem); + this.ToRgba32(configuration, reducedSource, lastQuarterOfDestBuffer); - SimdUtils.BulkConvertByteToNormalizedFloat( - MemoryMarshal.Cast(tempSpan), - MemoryMarshal.Cast(destVectors)); - } + // 'destVectors' and 'lastQuarterOfDestBuffer' are ovelapping buffers, + // but we are always reading/writing at different positions: + SimdUtils.BulkConvertByteToNormalizedFloat( + MemoryMarshal.Cast(lastQuarterOfDestBuffer), + MemoryMarshal.Cast(destVectors.Slice(0, countWithoutLastItem))); + + destVectors[countWithoutLastItem] = sourcePixels[countWithoutLastItem].ToVector4(); } /// @@ -230,6 +236,8 @@ namespace SixLabors.ImageSharp.PixelFormats return; } + // For the opposite direction it's not easy to implement the trick used in RunRgba32CompatibleToVector4Conversion, + // so let's allocate a temporary buffer as usually: using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(count)) { Span tempSpan = tempBuffer.Memory.Span; From 31369c7435dae33a9578e991208bcfb480c2ecdc Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 26 Oct 2018 16:35:02 +0200 Subject: [PATCH 13/17] refactor Vector4 implementation code from PixelOperation to Vector4Converters --- .../Argb32.PixelOperations.Generated.cs | 9 +- .../Bgr24.PixelOperations.Generated.cs | 9 +- .../Bgra32.PixelOperations.Generated.cs | 9 +- .../Gray16.PixelOperations.Generated.cs | 1 + .../Gray8.PixelOperations.Generated.cs | 1 + .../Rgb24.PixelOperations.Generated.cs | 9 +- .../Rgb48.PixelOperations.Generated.cs | 1 + .../Rgba32.PixelOperations.Generated.cs | 1 + .../Rgba64.PixelOperations.Generated.cs | 1 + .../Generated/_Common.ttinclude | 9 +- .../PixelFormats/PixelOperations{TPixel}.cs | 147 +---------------- .../{ => Utils}/PixelConverter.cs | 3 +- .../{ => Utils}/PixelExtensions.cs | 2 +- .../Utils/Vector4Converters.Default.cs | 89 ++++++++++ .../Utils/Vector4Converters.RgbaCompatible.cs | 154 ++++++++++++++++++ .../Color/Bulk/ToVector4_Bgra32.cs | 21 +++ .../PixelConversion_ConvertFromRgba32.cs | 1 + .../PixelFormats/PixelConverterTests.cs | 1 + 18 files changed, 302 insertions(+), 166 deletions(-) rename src/ImageSharp/PixelFormats/{ => Utils}/PixelConverter.cs (98%) rename src/ImageSharp/PixelFormats/{ => Utils}/PixelExtensions.cs (93%) create mode 100644 src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs create mode 100644 src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs index e6b8922e9..6449351cc 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs @@ -3,6 +3,7 @@ // +using SixLabors.ImageSharp.PixelFormats.Utils; using System; using System.Buffers; using System.Numerics; @@ -45,25 +46,25 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) { - this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) { - this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); } /// internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) { - this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); } /// internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) { - this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true); } /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs index 9b1740013..9232cf454 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs @@ -3,6 +3,7 @@ // +using SixLabors.ImageSharp.PixelFormats.Utils; using System; using System.Buffers; using System.Numerics; @@ -45,25 +46,25 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) { - this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) { - this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); } /// internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) { - this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); } /// internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) { - this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs index 37d6b72d7..4f56b75c5 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs @@ -3,6 +3,7 @@ // +using SixLabors.ImageSharp.PixelFormats.Utils; using System; using System.Buffers; using System.Numerics; @@ -45,25 +46,25 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) { - this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) { - this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); } /// internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) { - this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); } /// internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) { - this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true); } /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs index 638db1d0d..81882185d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs @@ -3,6 +3,7 @@ // +using SixLabors.ImageSharp.PixelFormats.Utils; using System; using System.Buffers; using System.Numerics; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs index 6bf0693c2..f6678a4f8 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs @@ -3,6 +3,7 @@ // +using SixLabors.ImageSharp.PixelFormats.Utils; using System; using System.Buffers; using System.Numerics; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs index 6ff87eb38..aae8b2f63 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs @@ -3,6 +3,7 @@ // +using SixLabors.ImageSharp.PixelFormats.Utils; using System; using System.Buffers; using System.Numerics; @@ -45,25 +46,25 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) { - this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) { - this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); } /// internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) { - this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); } /// internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) { - this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs index 9b4584d76..c828053a4 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs @@ -3,6 +3,7 @@ // +using SixLabors.ImageSharp.PixelFormats.Utils; using System; using System.Buffers; using System.Numerics; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs index 8e15ca1f4..9c29bd044 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs @@ -3,6 +3,7 @@ // +using SixLabors.ImageSharp.PixelFormats.Utils; using System; using System.Buffers; using System.Numerics; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs index caaba7809..db9cb84be 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs @@ -3,6 +3,7 @@ // +using SixLabors.ImageSharp.PixelFormats.Utils; using System; using System.Buffers; using System.Numerics; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude index 4501f4972..cc8cb0e2f 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude @@ -8,6 +8,7 @@ // +using SixLabors.ImageSharp.PixelFormats.Utils; using System; using System.Buffers; using System.Numerics; @@ -114,25 +115,25 @@ using System.Runtime.InteropServices; /// internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span<<#=pixelType#>> destPixels) { - this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors) { - this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); } /// internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span<<#=pixelType#>> destPixels) { - this.RunRgba32CompatibleFromVector4Conversion(configuration, sourceVectors, destPixels); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); } /// internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors) { - this.RunRgba32CompatibleToVector4Conversion(configuration, sourcePixels, destVectors); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true); } <#+ diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 9238e1b47..f4eb19be3 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -17,12 +17,6 @@ namespace SixLabors.ImageSharp.PixelFormats public partial class PixelOperations where TPixel : struct, IPixel { - /// - /// It's not worth to bother the transitive pixel conversion method below this limit. - /// The value depends on the actual gain brought by the SIMD characteristics of the executing CPU and JIT. - /// - private static readonly int Vector4ConversionThreshold = CalculateVector4ConversionThreshold(); - /// /// Gets the global instance for the pixel type /// @@ -42,7 +36,7 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); - FromVector4DefaultImpl(sourceVectors, destPixels); + Utils.Vector4Converters.Default.DangerousFromVector4(sourceVectors, destPixels); } /// @@ -59,7 +53,7 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); - ToVector4DefaultImpl(sourcePixels, destVectors); + Utils.Vector4Converters.Default.DangerousToVector4(sourcePixels, destVectors); } /// @@ -76,15 +70,7 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors)); - ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); - ref TPixel destRef = ref MemoryMarshal.GetReference(destinationColors); - - for (int i = 0; i < sourceVectors.Length; i++) - { - ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i); - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - dp.FromScaledVector4(sp); - } + Utils.Vector4Converters.Default.DangerousFromScaledVector4(sourceVectors, destinationColors); } /// @@ -101,15 +87,7 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors)); - ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors); - ref Vector4 destRef = ref MemoryMarshal.GetReference(destinationVectors); - - for (int i = 0; i < sourceColors.Length; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - ref Vector4 dp = ref Unsafe.Add(ref destRef, i); - dp = sp.ToScaledVector4(); - } + Utils.Vector4Converters.Default.DangerousToScaledVector4(sourceColors, destinationVectors); } /// @@ -170,122 +148,5 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromScaledVector4(sp.ToScaledVector4()); } } - - // TODO: The Vector4 helpers should be moved to a utility class. - - /// - /// Provides an efficient default implementation for and - /// which is applicable for -compatible pixel types where - /// returns the same scaled result as . - /// The method is works by internally converting to a therefore it's not applicable for that type! - /// - [MethodImpl(InliningOptions.ShortMethod)] - internal void RunRgba32CompatibleToVector4Conversion( - Configuration configuration, - ReadOnlySpan sourcePixels, - Span destVectors) - { - Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); - - int count = sourcePixels.Length; - - // Not worth for small buffers: - if (count < Vector4ConversionThreshold) - { - ToVector4DefaultImpl(sourcePixels, destVectors); - return; - } - - // Using the last quarter of 'destVectors' as a temporary buffer to avoid allocation: - int countWithoutLastItem = count - 1; - ReadOnlySpan reducedSource = sourcePixels.Slice(0, countWithoutLastItem); - Span lastQuarterOfDestBuffer = MemoryMarshal.Cast(destVectors).Slice((3 * count) + 1, countWithoutLastItem); - this.ToRgba32(configuration, reducedSource, lastQuarterOfDestBuffer); - - // 'destVectors' and 'lastQuarterOfDestBuffer' are ovelapping buffers, - // but we are always reading/writing at different positions: - SimdUtils.BulkConvertByteToNormalizedFloat( - MemoryMarshal.Cast(lastQuarterOfDestBuffer), - MemoryMarshal.Cast(destVectors.Slice(0, countWithoutLastItem))); - - destVectors[countWithoutLastItem] = sourcePixels[countWithoutLastItem].ToVector4(); - } - - /// - /// Provides an efficient default implementation for and - /// which is applicable for -compatible pixel types where - /// returns the same scaled result as . - /// The method is works by internally converting to a therefore it's not applicable for that type! - /// - [MethodImpl(InliningOptions.ShortMethod)] - internal void RunRgba32CompatibleFromVector4Conversion( - Configuration configuration, - ReadOnlySpan sourceVectors, - Span destPixels) - { - Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); - - int count = sourceVectors.Length; - - // Not worth for small buffers: - if (count < Vector4ConversionThreshold) - { - FromVector4DefaultImpl(sourceVectors, destPixels); - return; - } - - // For the opposite direction it's not easy to implement the trick used in RunRgba32CompatibleToVector4Conversion, - // so let's allocate a temporary buffer as usually: - using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(count)) - { - Span tempSpan = tempBuffer.Memory.Span; - - SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows( - MemoryMarshal.Cast(sourceVectors), - MemoryMarshal.Cast(tempSpan)); - - this.FromRgba32(configuration, tempSpan, destPixels); - } - } - - [MethodImpl(InliningOptions.ShortMethod)] - private static void FromVector4DefaultImpl(ReadOnlySpan sourceVectors, Span destPixels) - { - ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); - ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels); - - for (int i = 0; i < sourceVectors.Length; i++) - { - ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i); - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - dp.FromVector4(sp); - } - } - - [MethodImpl(InliningOptions.ShortMethod)] - private static void ToVector4DefaultImpl(ReadOnlySpan sourcePixels, Span destVectors) - { - ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Vector4 destRef = ref MemoryMarshal.GetReference(destVectors); - - for (int i = 0; i < sourcePixels.Length; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - ref Vector4 dp = ref Unsafe.Add(ref destRef, i); - dp = sp.ToVector4(); - } - } - - private static int CalculateVector4ConversionThreshold() - { - if (!Vector.IsHardwareAccelerated) - { - return int.MaxValue; - } - - return SimdUtils.ExtendedIntrinsics.IsAvailable && SimdUtils.IsAvx2CompatibleArchitecture ? 256 : 128; - } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelConverter.cs b/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs similarity index 98% rename from src/ImageSharp/PixelFormats/PixelConverter.cs rename to src/ImageSharp/PixelFormats/Utils/PixelConverter.cs index 8fde490fd..2336dbee7 100644 --- a/src/ImageSharp/PixelFormats/PixelConverter.cs +++ b/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs @@ -1,11 +1,10 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Buffers.Binary; using System.Runtime.CompilerServices; -namespace SixLabors.ImageSharp.PixelFormats +namespace SixLabors.ImageSharp.PixelFormats.Utils { /// /// Contains optimized implementations for conversion between pixel formats. diff --git a/src/ImageSharp/PixelFormats/PixelExtensions.cs b/src/ImageSharp/PixelFormats/Utils/PixelExtensions.cs similarity index 93% rename from src/ImageSharp/PixelFormats/PixelExtensions.cs rename to src/ImageSharp/PixelFormats/Utils/PixelExtensions.cs index 175696ab6..2284b8fc2 100644 --- a/src/ImageSharp/PixelFormats/PixelExtensions.cs +++ b/src/ImageSharp/PixelFormats/Utils/PixelExtensions.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.PixelFormats +namespace SixLabors.ImageSharp.PixelFormats.Utils { /// /// Low-performance extension methods to help conversion syntax, suitable for testing purposes. diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs new file mode 100644 index 000000000..139dbfa10 --- /dev/null +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs @@ -0,0 +1,89 @@ +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace SixLabors.ImageSharp.PixelFormats.Utils +{ + /// + /// Helper class for (bulk) conversion of buffers to/from other buffer types. + /// + internal static partial class Vector4Converters + { + /// + /// Provides default implementations for batched to/from conversion. + /// WARNING: The methods are operating without bounds checking and input validation! + /// Input validation is the responsibility of the caller! + /// + public static class Default + { + [MethodImpl(InliningOptions.ShortMethod)] + internal static void DangerousFromVector4( + ReadOnlySpan sourceVectors, + Span destPixels) + where TPixel : struct, IPixel + { + ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); + ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels); + + for (int i = 0; i < sourceVectors.Length; i++) + { + ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i); + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + dp.FromVector4(sp); + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + internal static void DangerousToVector4( + ReadOnlySpan sourcePixels, + Span destVectors) + where TPixel : struct, IPixel + { + ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourcePixels); + ref Vector4 destRef = ref MemoryMarshal.GetReference(destVectors); + + for (int i = 0; i < sourcePixels.Length; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); + ref Vector4 dp = ref Unsafe.Add(ref destRef, i); + dp = sp.ToVector4(); + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + internal static void DangerousFromScaledVector4( + ReadOnlySpan sourceVectors, + Span destinationColors) + where TPixel : struct, IPixel + { + ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); + ref TPixel destRef = ref MemoryMarshal.GetReference(destinationColors); + + for (int i = 0; i < sourceVectors.Length; i++) + { + ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i); + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + dp.FromScaledVector4(sp); + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + internal static void DangerousToScaledVector4( + ReadOnlySpan sourceColors, + Span destinationVectors) + where TPixel : struct, IPixel + { + ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors); + ref Vector4 destRef = ref MemoryMarshal.GetReference(destinationVectors); + + for (int i = 0; i < sourceColors.Length; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); + ref Vector4 dp = ref Unsafe.Add(ref destRef, i); + dp = sp.ToScaledVector4(); + } + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs new file mode 100644 index 000000000..7c57fe4fb --- /dev/null +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs @@ -0,0 +1,154 @@ +using System; +using System.Buffers; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace SixLabors.ImageSharp.PixelFormats.Utils +{ + /// + /// Contains + /// + internal static partial class Vector4Converters + { + /// + /// Provides efficient implementations for batched to/from conversion. + /// which is applicable for -compatible pixel types where + /// returns the same scaled result as . + /// The method is works by internally converting to a therefore it's not applicable for that type! + /// + public static class RgbaCompatible + { + /// + /// It's not worth to bother the transitive pixel conversion method below this limit. + /// The value depends on the actual gain brought by the SIMD characteristics of the executing CPU and JIT. + /// + private static readonly int Vector4ConversionThreshold = CalculateVector4ConversionThreshold(); + + /// + /// Provides an efficient default implementation for + /// and + /// which is applicable for -compatible pixel types where + /// returns the same scaled result as . + /// The method is works by internally converting to a therefore it's not applicable for that type! + /// + [MethodImpl(InliningOptions.ShortMethod)] + internal static void ToVector4( + Configuration configuration, + PixelOperations pixelOperations, + ReadOnlySpan sourcePixels, + Span destVectors, + bool scaled) + where TPixel : struct, IPixel + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); + + int count = sourcePixels.Length; + + // Not worth for small buffers: + if (count < Vector4ConversionThreshold) + { + ToVector4Fallback(sourcePixels, destVectors, scaled); + + return; + } + + // Using the last quarter of 'destVectors' as a temporary buffer to avoid allocation: + int countWithoutLastItem = count - 1; + ReadOnlySpan reducedSource = sourcePixels.Slice(0, countWithoutLastItem); + Span lastQuarterOfDestBuffer = MemoryMarshal.Cast(destVectors).Slice((3 * count) + 1, countWithoutLastItem); + pixelOperations.ToRgba32(configuration, reducedSource, lastQuarterOfDestBuffer); + + // 'destVectors' and 'lastQuarterOfDestBuffer' are ovelapping buffers, + // but we are always reading/writing at different positions: + SimdUtils.BulkConvertByteToNormalizedFloat( + MemoryMarshal.Cast(lastQuarterOfDestBuffer), + MemoryMarshal.Cast(destVectors.Slice(0, countWithoutLastItem))); + + destVectors[countWithoutLastItem] = sourcePixels[countWithoutLastItem].ToVector4(); + } + + /// + /// Provides an efficient default implementation for + /// and + /// which is applicable for -compatible pixel types where + /// returns the same scaled result as . + /// The method is works by internally converting to a therefore it's not applicable for that type! + /// + [MethodImpl(InliningOptions.ShortMethod)] + internal static void FromVector4( + Configuration configuration, + PixelOperations pixelOperations, + ReadOnlySpan sourceVectors, + Span destPixels, + bool scaled) + where TPixel : struct, IPixel + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); + + int count = sourceVectors.Length; + + // Not worth for small buffers: + if (count < Vector4ConversionThreshold) + { + FromVector4Fallback(sourceVectors, destPixels, scaled); + + return; + } + + // For the opposite direction it's not easy to implement the trick used in RunRgba32CompatibleToVector4Conversion, + // so let's allocate a temporary buffer as usually: + using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(count)) + { + Span tempSpan = tempBuffer.Memory.Span; + + SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows( + MemoryMarshal.Cast(sourceVectors), + MemoryMarshal.Cast(tempSpan)); + + pixelOperations.FromRgba32(configuration, tempSpan, destPixels); + } + } + + [MethodImpl(InliningOptions.ColdPath)] + private static void ToVector4Fallback(ReadOnlySpan sourcePixels, Span destVectors, bool scaled) + where TPixel : struct, IPixel + { + if (scaled) + { + Default.DangerousToScaledVector4(sourcePixels, destVectors); + } + else + { + Default.DangerousToVector4(sourcePixels, destVectors); + } + } + + [MethodImpl(InliningOptions.ColdPath)] + private static void FromVector4Fallback(ReadOnlySpan sourceVectors, Span destPixels, bool scaled) + where TPixel : struct, IPixel + { + if (scaled) + { + Default.DangerousFromScaledVector4(sourceVectors, destPixels); + } + else + { + Default.DangerousFromVector4(sourceVectors, destPixels); + } + } + + private static int CalculateVector4ConversionThreshold() + { + if (!Vector.IsHardwareAccelerated) + { + return int.MaxValue; + } + + return SimdUtils.ExtendedIntrinsics.IsAvailable && SimdUtils.IsAvx2CompatibleArchitecture ? 256 : 128; + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs index 028bfe46f..39702d525 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs @@ -16,5 +16,26 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk this.source.GetSpan(), this.destination.GetSpan()); } + + // RESULTS: + // Method | Runtime | Count | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated | + // ---------------------------- |-------- |------ |-----------:|------------:|-----------:|-------:|---------:|-------:|----------:| + // PixelOperations_Base | Clr | 64 | 339.9 ns | 138.30 ns | 7.8144 ns | 1.00 | 0.00 | 0.0072 | 24 B | + // PixelOperations_Specialized | Clr | 64 | 338.1 ns | 13.30 ns | 0.7515 ns | 0.99 | 0.02 | - | 0 B | + // | | | | | | | | | | + // PixelOperations_Base | Core | 64 | 245.6 ns | 29.05 ns | 1.6413 ns | 1.00 | 0.00 | 0.0072 | 24 B | + // PixelOperations_Specialized | Core | 64 | 257.1 ns | 37.89 ns | 2.1407 ns | 1.05 | 0.01 | - | 0 B | + // | | | | | | | | | | + // PixelOperations_Base | Clr | 256 | 972.7 ns | 61.98 ns | 3.5020 ns | 1.00 | 0.00 | 0.0057 | 24 B | + // PixelOperations_Specialized | Clr | 256 | 882.9 ns | 126.21 ns | 7.1312 ns | 0.91 | 0.01 | - | 0 B | + // | | | | | | | | | | + // PixelOperations_Base | Core | 256 | 910.0 ns | 90.87 ns | 5.1346 ns | 1.00 | 0.00 | 0.0067 | 24 B | + // PixelOperations_Specialized | Core | 256 | 448.4 ns | 15.77 ns | 0.8910 ns | 0.49 | 0.00 | - | 0 B | + // | | | | | | | | | | + // PixelOperations_Base | Clr | 2048 | 6,951.8 ns | 1,299.01 ns | 73.3963 ns | 1.00 | 0.00 | - | 24 B | + // PixelOperations_Specialized | Clr | 2048 | 5,852.3 ns | 630.56 ns | 35.6279 ns | 0.84 | 0.01 | - | 0 B | + // | | | | | | | | | | + // PixelOperations_Base | Core | 2048 | 6,937.5 ns | 1,692.19 ns | 95.6121 ns | 1.00 | 0.00 | - | 24 B | + // PixelOperations_Specialized | Core | 2048 | 2,994.5 ns | 1,126.65 ns | 63.6578 ns | 0.43 | 0.01 | - | 0 B | } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs index 424020e2f..9f1b2721b 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion { diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs index 9b32f7aee..c539e9dcf 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs @@ -1,4 +1,5 @@ using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.PixelFormats.Utils; using Xunit; From 09de1b1cde7a43d35a3759699539b31a27349b67 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 26 Oct 2018 19:43:00 +0200 Subject: [PATCH 14/17] better docs, drop PixelExtensions, fix tests --- .../PixelFormats/Utils/PixelConverter.cs | 12 +++++----- .../PixelFormats/Utils/PixelExtensions.cs | 22 ------------------- .../Drawing/FillLinearGradientBrushTests.cs | 4 +++- .../PixelFormats/Alpha8Tests.cs | 3 ++- .../PixelFormats/Gray16Tests.cs | 3 ++- .../PixelFormats/Gray8Tests.cs | 5 +++-- .../PixelFormats/Rgb24Tests.cs | 3 ++- .../PixelFormats/Rgb48Tests.cs | 3 ++- .../PixelFormats/Rgba1010102Tests.cs | 3 ++- .../PixelFormats/Rgba64Tests.cs | 2 +- .../PixelFormats/Short2Tests.cs | 4 ++-- .../PixelFormats/Short4Tests.cs | 12 ++++++---- .../PixelFormats/UnPackedPixelTests.cs | 6 +++-- .../Quantization/QuantizedImageTests.cs | 3 ++- .../TestUtilities/TestUtils.cs | 7 ++++-- .../Tests/TestImageProviderTests.cs | 3 ++- 16 files changed, 47 insertions(+), 48 deletions(-) delete mode 100644 src/ImageSharp/PixelFormats/Utils/PixelExtensions.cs diff --git a/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs b/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs index 2336dbee7..55a94fc81 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 2284b8fc2..000000000 --- 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 9121649f4..556ec9c9c 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 148b928fa..8f68c9d03 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 220ca2899..cb19c031d 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 988002c09..6a7b20cbe 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 a60509146..92e8d302d 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 a7f0e5edf..d30e49860 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 ad7df3076..a897dd4cd 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 564c26b8b..3e5d7a56e 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 725e1a0d1..c9a3b33c9 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 b19917f34..247342a05 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 29c97ce35..bd8c64742 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 fa855aef7..577dc83c5 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 e6a5ffc84..d7755ff7a 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 1d284af15..a8140e39d 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); From 16018e5c6a44c3038d70797469e2c8eca43e2f0a Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 26 Oct 2018 20:04:19 +0200 Subject: [PATCH 15/17] refactor PixelOperationsTests --- tests/ImageSharp.Tests/ConfigurationTests.cs | 1 + .../ImageSharp.Tests/GraphicsOptionsTests.cs | 21 + ...elOperationsTests.Argb32OperationsTests.cs | 22 + ...xelOperationsTests.Bgr24OperationsTests.cs | 21 + ...elOperationsTests.Bgra32OperationsTests.cs | 21 + ...elOperationsTests.Gray16OperationsTests.cs | 111 +++++ ...xelOperationsTests.Gray8OperationsTests.cs | 111 +++++ ...xelOperationsTests.Rgb48OperationsTests.cs | 21 + ...elOperationsTests.Rgba32OperationsTests.cs | 43 ++ ...elOperationsTests.Rgba64OperationsTests.cs | 21 + ...erationsTests.RgbaVectorOperationsTests.cs | 21 + .../PixelOperationsTests.cs | 394 +++--------------- 12 files changed, 476 insertions(+), 332 deletions(-) create mode 100644 tests/ImageSharp.Tests/GraphicsOptionsTests.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Argb32OperationsTests.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra32OperationsTests.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray16OperationsTests.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray8OperationsTests.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb48OperationsTests.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba32OperationsTests.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba64OperationsTests.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.RgbaVectorOperationsTests.cs rename tests/ImageSharp.Tests/PixelFormats/{ => PixelOperations}/PixelOperationsTests.cs (63%) diff --git a/tests/ImageSharp.Tests/ConfigurationTests.cs b/tests/ImageSharp.Tests/ConfigurationTests.cs index 963d67446..208387e6d 100644 --- a/tests/ImageSharp.Tests/ConfigurationTests.cs +++ b/tests/ImageSharp.Tests/ConfigurationTests.cs @@ -6,6 +6,7 @@ using System.Linq; using Moq; using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.IO; + using Xunit; // ReSharper disable InconsistentNaming diff --git a/tests/ImageSharp.Tests/GraphicsOptionsTests.cs b/tests/ImageSharp.Tests/GraphicsOptionsTests.cs new file mode 100644 index 000000000..6ff38626d --- /dev/null +++ b/tests/ImageSharp.Tests/GraphicsOptionsTests.cs @@ -0,0 +1,21 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public class GraphicsOptionsTests + { + [Fact] + public void IsOpaqueColor() + { + Assert.True(new GraphicsOptions(true).IsOpaqueColorWithoutBlending(Rgba32.Red)); + Assert.False(new GraphicsOptions(true, 0.5f).IsOpaqueColorWithoutBlending(Rgba32.Red)); + Assert.False(new GraphicsOptions(true).IsOpaqueColorWithoutBlending(Rgba32.Transparent)); + Assert.False(new GraphicsOptions(true, PixelColorBlendingMode.Lighten, 1).IsOpaqueColorWithoutBlending(Rgba32.Red)); + Assert.False(new GraphicsOptions(true, PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.DestOver, 1).IsOpaqueColorWithoutBlending(Rgba32.Red)); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Argb32OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Argb32OperationsTests.cs new file mode 100644 index 000000000..875ba0cba --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Argb32OperationsTests.cs @@ -0,0 +1,22 @@ +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + public class Argb32OperationsTests : PixelOperationsTests + { + + public Argb32OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs new file mode 100644 index 000000000..879712a3e --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs @@ -0,0 +1,21 @@ +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + public class Bgr24OperationsTests : PixelOperationsTests + { + public Bgr24OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra32OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra32OperationsTests.cs new file mode 100644 index 000000000..963a9dae6 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra32OperationsTests.cs @@ -0,0 +1,21 @@ +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + public class Bgra32OperationsTests : PixelOperationsTests + { + public Bgra32OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray16OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray16OperationsTests.cs new file mode 100644 index 000000000..1afa65240 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray16OperationsTests.cs @@ -0,0 +1,111 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + public class Gray16OperationsTests : PixelOperationsTests + { + public Gray16OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void FromGray8Bytes(int count) + { + byte[] source = CreateByteTestData(count); + var expected = new Gray16[count]; + + for (int i = 0; i < count; i++) + { + expected[i].FromGray8(new Gray8(source[i])); + } + + TestOperation( + source, + expected, + (s, d) => Operations.FromGray8Bytes(this.Configuration, s, d.GetSpan(), count) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void ToGray8Bytes(int count) + { + Gray16[] source = CreatePixelTestData(count); + byte[] expected = new byte[count]; + var gray = default(Gray8); + + for (int i = 0; i < count; i++) + { + gray.FromScaledVector4(source[i].ToScaledVector4()); + expected[i] = gray.PackedValue; + } + + TestOperation( + source, + expected, + (s, d) => Operations.ToGray8Bytes(this.Configuration, s, d.GetSpan(), count) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void FromGray16Bytes(int count) + { + byte[] source = CreateByteTestData(count * 2); + Span sourceSpan = source.AsSpan(); + var expected = new Gray16[count]; + + for (int i = 0; i < count; i++) + { + int i2 = i * 2; + expected[i].FromGray16(MemoryMarshal.Cast(sourceSpan.Slice(i2, 2))[0]); + } + + TestOperation( + source, + expected, + (s, d) => Operations.FromGray16Bytes(this.Configuration, s, d.GetSpan(), count) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void ToGray16Bytes(int count) + { + Gray16[] source = CreatePixelTestData(count); + byte[] expected = new byte[count * 2]; + Gray16 gray = default; + + for (int i = 0; i < count; i++) + { + int i2 = i * 2; + gray.FromScaledVector4(source[i].ToScaledVector4()); + OctetBytes bytes = Unsafe.As(ref gray); + expected[i2] = bytes[0]; + expected[i2 + 1] = bytes[1]; + } + + TestOperation( + source, + expected, + (s, d) => Operations.ToGray16Bytes(this.Configuration, s, d.GetSpan(), count) + ); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray8OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray8OperationsTests.cs new file mode 100644 index 000000000..4112d201b --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray8OperationsTests.cs @@ -0,0 +1,111 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + public class Gray8OperationsTests : PixelOperationsTests + { + public Gray8OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void FromGray8Bytes(int count) + { + byte[] source = CreateByteTestData(count); + var expected = new Gray8[count]; + + for (int i = 0; i < count; i++) + { + expected[i].FromGray8(new Gray8(source[i])); + } + + TestOperation( + source, + expected, + (s, d) => Operations.FromGray8Bytes(this.Configuration, s, d.GetSpan(), count) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void ToGray8Bytes(int count) + { + Gray8[] source = CreatePixelTestData(count); + byte[] expected = new byte[count]; + var gray = default(Gray8); + + for (int i = 0; i < count; i++) + { + gray.FromScaledVector4(source[i].ToScaledVector4()); + expected[i] = gray.PackedValue; + } + + TestOperation( + source, + expected, + (s, d) => Operations.ToGray8Bytes(this.Configuration, s, d.GetSpan(), count) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void FromGray16Bytes(int count) + { + byte[] source = CreateByteTestData(count * 2); + Span sourceSpan = source.AsSpan(); + var expected = new Gray8[count]; + + for (int i = 0; i < count; i++) + { + int i2 = i * 2; + expected[i].FromGray16(MemoryMarshal.Cast(sourceSpan.Slice(i2, 2))[0]); + } + + TestOperation( + source, + expected, + (s, d) => Operations.FromGray16Bytes(this.Configuration, s, d.GetSpan(), count) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void ToGray16Bytes(int count) + { + Gray8[] source = CreatePixelTestData(count); + byte[] expected = new byte[count * 2]; + Gray16 gray = default; + + for (int i = 0; i < count; i++) + { + int i2 = i * 2; + gray.FromScaledVector4(source[i].ToScaledVector4()); + OctetBytes bytes = Unsafe.As(ref gray); + expected[i2] = bytes[0]; + expected[i2 + 1] = bytes[1]; + } + + TestOperation( + source, + expected, + (s, d) => Operations.ToGray16Bytes(this.Configuration, s, d.GetSpan(), count) + ); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb48OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb48OperationsTests.cs new file mode 100644 index 000000000..68b67fce2 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb48OperationsTests.cs @@ -0,0 +1,21 @@ +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + public class Rgb48OperationsTests : PixelOperationsTests + { + public Rgb48OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba32OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba32OperationsTests.cs new file mode 100644 index 000000000..38cc97893 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba32OperationsTests.cs @@ -0,0 +1,43 @@ +using System.Buffers; +using System.Numerics; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + public class Rgba32OperationsTests : PixelOperationsTests + { + public Rgba32OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact(Skip = SkipProfilingBenchmarks)] + public void Benchmark_ToVector4() + { + const int times = 200000; + const int count = 1024; + + using (IMemoryOwner source = Configuration.Default.MemoryAllocator.Allocate(count)) + using (IMemoryOwner dest = Configuration.Default.MemoryAllocator.Allocate(count)) + { + this.Measure( + times, + () => PixelOperations.Instance.ToVector4( + this.Configuration, + source.GetSpan(), + dest.GetSpan())); + } + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba64OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba64OperationsTests.cs new file mode 100644 index 000000000..47738ac60 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba64OperationsTests.cs @@ -0,0 +1,21 @@ +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + public class Rgba64OperationsTests : PixelOperationsTests + { + public Rgba64OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.RgbaVectorOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.RgbaVectorOperationsTests.cs new file mode 100644 index 000000000..7272dfb78 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.RgbaVectorOperationsTests.cs @@ -0,0 +1,21 @@ +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + public class RgbaVectorOperationsTests : PixelOperationsTests + { + public RgbaVectorOperationsTests(ITestOutputHelper output) + : base(output) + { + } + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs similarity index 63% rename from tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs rename to tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs index e66ca9a71..d9845e474 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs @@ -6,335 +6,65 @@ using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; + using Xunit; using Xunit.Abstractions; -namespace SixLabors.ImageSharp.Tests.PixelFormats +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { - public class PixelOperationsTests + public partial class PixelOperationsTests { - public const string SkipProfilingBenchmarks = -#if true - "Profiling benchmark - enable manually!"; -#else - null; -#endif - - public class Argb32OperationsTests : PixelOperationsTests - { - - public Argb32OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - - public class Bgr24OperationsTests : PixelOperationsTests - { - public Bgr24OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - - public class Bgra32OperationsTests : PixelOperationsTests - { - public Bgra32OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - - public class Gray8OperationsTests : PixelOperationsTests - { - public Gray8OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void FromGray8Bytes(int count) - { - byte[] source = CreateByteTestData(count); - var expected = new Gray8[count]; - - for (int i = 0; i < count; i++) - { - expected[i].FromGray8(new Gray8(source[i])); - } - - TestOperation( - source, - expected, - (s, d) => Operations.FromGray8Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void ToGray8Bytes(int count) - { - Gray8[] source = CreatePixelTestData(count); - byte[] expected = new byte[count]; - var gray = default(Gray8); - - for (int i = 0; i < count; i++) - { - gray.FromScaledVector4(source[i].ToScaledVector4()); - expected[i] = gray.PackedValue; - } - - TestOperation( - source, - expected, - (s, d) => Operations.ToGray8Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void FromGray16Bytes(int count) - { - byte[] source = CreateByteTestData(count * 2); - Span sourceSpan = source.AsSpan(); - var expected = new Gray8[count]; - - for (int i = 0; i < count; i++) - { - int i2 = i * 2; - expected[i].FromGray16(MemoryMarshal.Cast(sourceSpan.Slice(i2, 2))[0]); - } - - TestOperation( - source, - expected, - (s, d) => Operations.FromGray16Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void ToGray16Bytes(int count) - { - Gray8[] source = CreatePixelTestData(count); - byte[] expected = new byte[count * 2]; - Gray16 gray = default; - - for (int i = 0; i < count; i++) - { - int i2 = i * 2; - gray.FromScaledVector4(source[i].ToScaledVector4()); - OctetBytes bytes = Unsafe.As(ref gray); - expected[i2] = bytes[0]; - expected[i2 + 1] = bytes[1]; - } - - TestOperation( - source, - expected, - (s, d) => Operations.ToGray16Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - } - - public class Gray16OperationsTests : PixelOperationsTests - { - public Gray16OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void FromGray8Bytes(int count) - { - byte[] source = CreateByteTestData(count); - var expected = new Gray16[count]; - - for (int i = 0; i < count; i++) - { - expected[i].FromGray8(new Gray8(source[i])); - } - - TestOperation( - source, - expected, - (s, d) => Operations.FromGray8Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void ToGray8Bytes(int count) - { - Gray16[] source = CreatePixelTestData(count); - byte[] expected = new byte[count]; - var gray = default(Gray8); - - for (int i = 0; i < count; i++) - { - gray.FromScaledVector4(source[i].ToScaledVector4()); - expected[i] = gray.PackedValue; - } - - TestOperation( - source, - expected, - (s, d) => Operations.ToGray8Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void FromGray16Bytes(int count) - { - byte[] source = CreateByteTestData(count * 2); - Span sourceSpan = source.AsSpan(); - var expected = new Gray16[count]; - - for (int i = 0; i < count; i++) - { - int i2 = i * 2; - expected[i].FromGray16(MemoryMarshal.Cast(sourceSpan.Slice(i2, 2))[0]); - } - - TestOperation( - source, - expected, - (s, d) => Operations.FromGray16Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void ToGray16Bytes(int count) - { - Gray16[] source = CreatePixelTestData(count); - byte[] expected = new byte[count * 2]; - Gray16 gray = default; - - for (int i = 0; i < count; i++) - { - int i2 = i * 2; - gray.FromScaledVector4(source[i].ToScaledVector4()); - OctetBytes bytes = Unsafe.As(ref gray); - expected[i2] = bytes[0]; - expected[i2 + 1] = bytes[1]; - } - - TestOperation( - source, - expected, - (s, d) => Operations.ToGray16Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - } - - public class Rgba32OperationsTests : PixelOperationsTests - { - public Rgba32OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - - [Fact(Skip = SkipProfilingBenchmarks)] - public void Benchmark_ToVector4() - { - const int times = 200000; - const int count = 1024; - - using (IMemoryOwner source = Configuration.Default.MemoryAllocator.Allocate(count)) - using (IMemoryOwner dest = Configuration.Default.MemoryAllocator.Allocate(count)) - { - this.Measure( - times, - () => PixelOperations.Instance.ToVector4( - this.Configuration, - source.GetSpan(), - dest.GetSpan())); - } - } - } - - public class Rgb48OperationsTests : PixelOperationsTests - { - public Rgb48OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - - public class Rgba64OperationsTests : PixelOperationsTests - { - public Rgba64OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - - public class RgbaVectorOperationsTests : PixelOperationsTests - { - public RgbaVectorOperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - [Theory] [WithBlankImages(1, 1, PixelTypes.All)] - public void GetGlobalInstance(TestImageProvider _) - where TPixel : struct, IPixel => Assert.NotNull(PixelOperations.Instance); - - [Fact] - public void IsOpaqueColor() - { - Assert.True(new GraphicsOptions(true).IsOpaqueColorWithoutBlending(Rgba32.Red)); - Assert.False(new GraphicsOptions(true, 0.5f).IsOpaqueColorWithoutBlending(Rgba32.Red)); - Assert.False(new GraphicsOptions(true).IsOpaqueColorWithoutBlending(Rgba32.Transparent)); - Assert.False(new GraphicsOptions(true, PixelColorBlendingMode.Lighten, 1).IsOpaqueColorWithoutBlending(Rgba32.Red)); - Assert.False(new GraphicsOptions(true, PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.DestOver, 1).IsOpaqueColorWithoutBlending(Rgba32.Red)); - } + public void GetGlobalInstance(TestImageProvider _) + where T : struct, IPixel => Assert.NotNull(PixelOperations.Instance); } public abstract class PixelOperationsTests : MeasureFixture where TPixel : struct, IPixel { + public const string SkipProfilingBenchmarks = +#if true + "Profiling benchmark - enable manually!"; +#else + null; +#endif + protected PixelOperationsTests(ITestOutputHelper output) : base(output) { } - public static TheoryData ArraySizesData => new TheoryData { 0, 1, 2, 7, 16, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 1111 }; + public static TheoryData ArraySizesData => + new TheoryData + { + 0, + 1, + 2, + 7, + 16, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 1111 + }; protected Configuration Configuration => Configuration.Default; @@ -390,28 +120,6 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats ); } - internal static Vector4[] CreateExpectedVector4Data(TPixel[] source) - { - var expected = new Vector4[source.Length]; - - for (int i = 0; i < expected.Length; i++) - { - expected[i] = source[i].ToVector4(); - } - return expected; - } - - internal static Vector4[] CreateExpectedScaledVector4Data(TPixel[] source) - { - var expected = new Vector4[source.Length]; - - for (int i = 0; i < expected.Length; i++) - { - expected[i] = source[i].ToScaledVector4(); - } - return expected; - } - [Theory] [MemberData(nameof(ArraySizesData))] public void ToVector4(int count) @@ -769,6 +477,28 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats ); } + internal static Vector4[] CreateExpectedVector4Data(TPixel[] source) + { + var expected = new Vector4[source.Length]; + + for (int i = 0; i < expected.Length; i++) + { + expected[i] = source[i].ToVector4(); + } + return expected; + } + + internal static Vector4[] CreateExpectedScaledVector4Data(TPixel[] source) + { + var expected = new Vector4[source.Length]; + + for (int i = 0; i < expected.Length; i++) + { + expected[i] = source[i].ToScaledVector4(); + } + return expected; + } + internal static void TestOperation( TSource[] source, TDest[] expected, From 633c212bdd45e083f4c4fd2b5de38cd02b95ddd9 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 26 Oct 2018 20:30:48 +0200 Subject: [PATCH 16/17] add header --- .../PixelOperationsTests.Argb32OperationsTests.cs | 5 ++++- .../PixelOperationsTests.Bgr24OperationsTests.cs | 5 ++++- .../PixelOperationsTests.Bgra32OperationsTests.cs | 5 ++++- .../PixelOperationsTests.Gray16OperationsTests.cs | 5 ++++- .../PixelOperationsTests.Gray8OperationsTests.cs | 5 ++++- .../PixelOperationsTests.Rgb48OperationsTests.cs | 5 ++++- .../PixelOperationsTests.Rgba32OperationsTests.cs | 5 ++++- .../PixelOperationsTests.Rgba64OperationsTests.cs | 5 ++++- .../PixelOperationsTests.RgbaVectorOperationsTests.cs | 5 ++++- 9 files changed, 36 insertions(+), 9 deletions(-) diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Argb32OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Argb32OperationsTests.cs index 875ba0cba..c881ae96b 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Argb32OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Argb32OperationsTests.cs @@ -1,4 +1,7 @@ -using SixLabors.ImageSharp.PixelFormats; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; using Xunit; using Xunit.Abstractions; diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs index 879712a3e..323d3914c 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs @@ -1,4 +1,7 @@ -using SixLabors.ImageSharp.PixelFormats; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; using Xunit; using Xunit.Abstractions; diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra32OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra32OperationsTests.cs index 963a9dae6..1c966951f 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra32OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra32OperationsTests.cs @@ -1,4 +1,7 @@ -using SixLabors.ImageSharp.PixelFormats; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; using Xunit; using Xunit.Abstractions; diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray16OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray16OperationsTests.cs index 1afa65240..c3de33547 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray16OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray16OperationsTests.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray8OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray8OperationsTests.cs index 4112d201b..acd6ef23a 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray8OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray8OperationsTests.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb48OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb48OperationsTests.cs index 68b67fce2..0a28db6b0 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb48OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb48OperationsTests.cs @@ -1,4 +1,7 @@ -using SixLabors.ImageSharp.PixelFormats; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; using Xunit; using Xunit.Abstractions; diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba32OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba32OperationsTests.cs index 38cc97893..1ecbaf361 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba32OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba32OperationsTests.cs @@ -1,4 +1,7 @@ -using System.Buffers; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Buffers; using System.Numerics; using SixLabors.ImageSharp.Memory; diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba64OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba64OperationsTests.cs index 47738ac60..6787602bb 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba64OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba64OperationsTests.cs @@ -1,4 +1,7 @@ -using SixLabors.ImageSharp.PixelFormats; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; using Xunit; using Xunit.Abstractions; diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.RgbaVectorOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.RgbaVectorOperationsTests.cs index 7272dfb78..f9cc042a7 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.RgbaVectorOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.RgbaVectorOperationsTests.cs @@ -1,4 +1,7 @@ -using SixLabors.ImageSharp.PixelFormats; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; using Xunit; using Xunit.Abstractions; From cf7af016bec905f2e7399c57fe638d4dc45b097c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 26 Oct 2018 20:33:25 +0200 Subject: [PATCH 17/17] fix Sandbox46 build --- tests/ImageSharp.Sandbox46/Program.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ImageSharp.Sandbox46/Program.cs b/tests/ImageSharp.Sandbox46/Program.cs index 4d89929a0..3a3a7d31c 100644 --- a/tests/ImageSharp.Sandbox46/Program.cs +++ b/tests/ImageSharp.Sandbox46/Program.cs @@ -3,6 +3,8 @@ // Licensed under the Apache License, Version 2.0. // +using SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations; + namespace SixLabors.ImageSharp.Sandbox46 { using System;