diff --git a/src/ImageSharp/Advanced/ParallelRowIterator.Wrappers.cs b/src/ImageSharp/Advanced/ParallelRowIterator.Wrappers.cs index 4abcd1a3ec..9413cf4671 100644 --- a/src/ImageSharp/Advanced/ParallelRowIterator.Wrappers.cs +++ b/src/ImageSharp/Advanced/ParallelRowIterator.Wrappers.cs @@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Advanced var rows = new RowInterval(yMin, yMax); // Skip the safety copy when invoking a potentially impure method on a readonly field - Unsafe.AsRef(this.operation).Invoke(in rows); + Unsafe.AsRef(in this.operation).Invoke(in rows); } } @@ -103,7 +103,7 @@ namespace SixLabors.ImageSharp.Advanced using IMemoryOwner buffer = this.allocator.Allocate(this.info.MaxX); - Unsafe.AsRef(this.operation).Invoke(in rows, buffer.Memory.Span); + Unsafe.AsRef(in this.operation).Invoke(in rows, buffer.Memory.Span); } } } diff --git a/src/ImageSharp/Advanced/ParallelRowIterator.cs b/src/ImageSharp/Advanced/ParallelRowIterator.cs index 5119190f39..b2e7f523f1 100644 --- a/src/ImageSharp/Advanced/ParallelRowIterator.cs +++ b/src/ImageSharp/Advanced/ParallelRowIterator.cs @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Advanced if (numOfSteps == 1) { var rows = new RowInterval(top, bottom); - Unsafe.AsRef(operation).Invoke(in rows); + Unsafe.AsRef(in operation).Invoke(in rows); return; } @@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.Advanced var rows = new RowInterval(top, bottom); using (IMemoryOwner buffer = allocator.Allocate(width)) { - Unsafe.AsRef(operation).Invoke(rows, buffer.Memory.Span); + Unsafe.AsRef(operation).Invoke(in rows, buffer.Memory.Span); } return; diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index bcbfda2ba2..69a80e024e 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -554,14 +554,8 @@ namespace SixLabors.ImageSharp.Formats.Png return; } - /* Grab the palette and write it to the stream. - * Here the palette is reinterpreted as a mutable Memory value, - * which is possible because the two memory types have the same layout. - * This is done so that the Span we're working on is mutable, - * so that we can skip the safety copies done by the compiler when we - * invoke the IPixel.ToRgba32 method below, which is not marked as readonly. */ - ReadOnlyMemory paletteMemory = quantized.Palette; - Span palette = Unsafe.As, Memory>(ref paletteMemory).Span; + // Grab the palette and write it to the stream. + ReadOnlySpan palette = quantized.Palette.Span; int paletteLength = Math.Min(palette.Length, 256); int colorTableLength = paletteLength * 3; bool anyAlpha = false; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs index d71f7bca43..56bc6f4559 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs @@ -218,7 +218,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public readonly Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / Max; + public Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / Max; /// [MethodImpl(InliningOptions.ShortMethod)] @@ -343,7 +343,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// The . [MethodImpl(InliningOptions.ShortMethod)] - public readonly Rgba32 ToRgba32() + public Rgba32 ToRgba32() { byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); @@ -357,7 +357,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// The . [MethodImpl(InliningOptions.ShortMethod)] - public readonly Bgra32 ToBgra32() + public Bgra32 ToBgra32() { byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); @@ -371,7 +371,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// The . [MethodImpl(InliningOptions.ShortMethod)] - public readonly Argb32 ToArgb32() + public Argb32 ToArgb32() { byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); @@ -385,7 +385,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// The . [MethodImpl(InliningOptions.ShortMethod)] - public readonly Rgb24 ToRgb24() + public Rgb24 ToRgb24() { byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); @@ -398,7 +398,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// The . [MethodImpl(InliningOptions.ShortMethod)] - public readonly Bgr24 ToBgr24() + public Bgr24 ToBgr24() { byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs index 79574e4426..9c3a592d71 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs @@ -66,8 +66,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils MemoryMarshal.Cast(lastQuarterOfDestBuffer), MemoryMarshal.Cast(destVectors.Slice(0, countWithoutLastItem))); - // Reinterpret as a mutable reference to skip the safety copy of the readonly value - destVectors[countWithoutLastItem] = Unsafe.AsRef(sourcePixels[countWithoutLastItem]).ToVector4(); + destVectors[countWithoutLastItem] = sourcePixels[countWithoutLastItem].ToVector4(); // TODO: Investigate optimized 1-pass approach! ApplyForwardConversionModifiers(destVectors, modifiers); diff --git a/src/ImageSharp/Primitives/Rectangle.cs b/src/ImageSharp/Primitives/Rectangle.cs index 5b2e9411cc..d391057a9b 100644 --- a/src/ImageSharp/Primitives/Rectangle.cs +++ b/src/ImageSharp/Primitives/Rectangle.cs @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp public Point Location { [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get => new Point(this.X, this.Y); + get => new Point(this.X, this.Y); [MethodImpl(MethodImplOptions.AggressiveInlining)] set @@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp public Size Size { [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get => new Size(this.Width, this.Height); + get => new Size(this.Width, this.Height); [MethodImpl(MethodImplOptions.AggressiveInlining)] set @@ -112,17 +112,17 @@ namespace SixLabors.ImageSharp /// Gets a value indicating whether this is empty. /// [EditorBrowsable(EditorBrowsableState.Never)] - public readonly bool IsEmpty => this.Equals(Empty); + public bool IsEmpty => this.Equals(Empty); /// /// Gets the y-coordinate of the top edge of this . /// - public readonly int Top => this.Y; + public int Top => this.Y; /// /// Gets the x-coordinate of the right edge of this . /// - public readonly int Right + public int Right { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => unchecked(this.X + this.Width); @@ -131,7 +131,7 @@ namespace SixLabors.ImageSharp /// /// Gets the y-coordinate of the bottom edge of this . /// - public readonly int Bottom + public int Bottom { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => unchecked(this.Y + this.Height); @@ -140,7 +140,7 @@ namespace SixLabors.ImageSharp /// /// Gets the x-coordinate of the left edge of this . /// - public readonly int Left => this.X; + public int Left => this.X; /// /// Creates a with the coordinates of the specified . @@ -327,7 +327,7 @@ namespace SixLabors.ImageSharp /// The out value for Y. /// The out value for the width. /// The out value for the height. - public readonly void Deconstruct(out int x, out int y, out int width, out int height) + public void Deconstruct(out int x, out int y, out int width, out int height) { x = this.X; y = this.Y; @@ -383,7 +383,7 @@ namespace SixLabors.ImageSharp /// The y-coordinate of the given point. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Contains(int x, int y) => this.X <= x && x < this.Right && this.Y <= y && y < this.Bottom; + public bool Contains(int x, int y) => this.X <= x && x < this.Right && this.Y <= y && y < this.Bottom; /// /// Determines if the specified point is contained within the rectangular region defined by this . @@ -391,7 +391,7 @@ namespace SixLabors.ImageSharp /// The point. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Contains(Point point) => this.Contains(point.X, point.Y); + public bool Contains(Point point) => this.Contains(point.X, point.Y); /// /// Determines if the rectangular region represented by is entirely contained @@ -400,7 +400,7 @@ namespace SixLabors.ImageSharp /// The rectangle. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Contains(Rectangle rectangle) => + public bool Contains(Rectangle rectangle) => (this.X <= rectangle.X) && (rectangle.Right <= this.Right) && (this.Y <= rectangle.Y) && (rectangle.Bottom <= this.Bottom); @@ -411,7 +411,7 @@ namespace SixLabors.ImageSharp /// The other Rectange. /// The . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool IntersectsWith(Rectangle rectangle) => + public bool IntersectsWith(Rectangle rectangle) => (rectangle.X < this.Right) && (this.X < rectangle.Right) && (rectangle.Y < this.Bottom) && (this.Y < rectangle.Bottom); @@ -438,13 +438,13 @@ namespace SixLabors.ImageSharp } /// - public override readonly int GetHashCode() + public override int GetHashCode() { return HashCode.Combine(this.X, this.Y, this.Width, this.Height); } /// - public override readonly string ToString() + public override string ToString() { return $"Rectangle [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; } @@ -454,7 +454,7 @@ namespace SixLabors.ImageSharp /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Equals(Rectangle other) => + public bool Equals(Rectangle other) => this.X.Equals(other.X) && this.Y.Equals(other.Y) && this.Width.Equals(other.Width) && diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs index e388fdaad3..1ebd6476e0 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs @@ -316,14 +316,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution Vector4 parameters = Unsafe.Add(ref paramsRef, i); // Compute the vertical 1D convolution - var verticalOperation = new ApplyVerticalConvolutionRowIntervalOperation(ref sourceRectangle, firstPassBuffer, source.PixelBuffer, kernel); + var verticalOperation = new ApplyVerticalConvolutionRowIntervalOperation(sourceRectangle, firstPassBuffer, source.PixelBuffer, kernel); ParallelRowIterator.IterateRows( configuration, sourceRectangle, in verticalOperation); // Compute the horizontal 1D convolutions and accumulate the partial results on the target buffer - var horizontalOperation = new ApplyHorizontalConvolutionRowIntervalOperation(ref sourceRectangle, processingBuffer, firstPassBuffer, kernel, parameters.Z, parameters.W); + var horizontalOperation = new ApplyHorizontalConvolutionRowIntervalOperation(sourceRectangle, processingBuffer, firstPassBuffer, kernel, parameters.Z, parameters.W); ParallelRowIterator.IterateRows( configuration, sourceRectangle, @@ -345,7 +345,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution [MethodImpl(InliningOptions.ShortMethod)] public ApplyVerticalConvolutionRowIntervalOperation( - ref Rectangle bounds, + Rectangle bounds, Buffer2D targetValues, Buffer2D sourcePixels, Complex64[] kernel) @@ -390,7 +390,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution [MethodImpl(InliningOptions.ShortMethod)] public ApplyHorizontalConvolutionRowIntervalOperation( - ref Rectangle bounds, + Rectangle bounds, Buffer2D targetValues, Buffer2D sourceValues, Complex64[] kernel, diff --git a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs index d7ea807373..07fa55c5d0 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs @@ -47,15 +47,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization { MemoryAllocator memoryAllocator = this.Configuration.MemoryAllocator; int numberOfPixels = source.Width * source.Height; - var workingRect = new Rectangle(0, 0, source.Width, source.Height); + var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); using IMemoryOwner histogramBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean); // Build the histogram of the grayscale levels - var grayscaleOperation = new GrayscaleLevelsRowIntervalOperation(workingRect, histogramBuffer, source, this.LuminanceLevels); + var grayscaleOperation = new GrayscaleLevelsRowIntervalOperation(interest, histogramBuffer, source, this.LuminanceLevels); ParallelRowIterator.IterateRows( this.Configuration, - workingRect, + interest, in grayscaleOperation); Span histogram = histogramBuffer.GetSpan(); @@ -75,10 +75,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization float numberOfPixelsMinusCdfMin = numberOfPixels - cdfMin; // Apply the cdf to each pixel of the image - var cdfOperation = new CdfApplicationRowIntervalOperation(workingRect, cdfBuffer, source, this.LuminanceLevels, numberOfPixelsMinusCdfMin); + var cdfOperation = new CdfApplicationRowIntervalOperation(interest, cdfBuffer, source, this.LuminanceLevels, numberOfPixelsMinusCdfMin); ParallelRowIterator.IterateRows( this.Configuration, - workingRect, + interest, in cdfOperation); } @@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization [MethodImpl(InliningOptions.ShortMethod)] public GrayscaleLevelsRowIntervalOperation( - in Rectangle bounds, + Rectangle bounds, IMemoryOwner histogramBuffer, ImageFrame source, int luminanceLevels) @@ -136,7 +136,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization [MethodImpl(InliningOptions.ShortMethod)] public CdfApplicationRowIntervalOperation( - in Rectangle bounds, + Rectangle bounds, IMemoryOwner cdfBuffer, ImageFrame source, int luminanceLevels, diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs index 4fd35d3756..6ad7aa2a25 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs @@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms ParallelExecutionSettings parallelSettings = ParallelExecutionSettings.FromConfiguration(this.Configuration).MultiplyMinimumPixelsPerTask(4); - var operation = new RowIntervalOperation(ref bounds, source, destination); + var operation = new RowIntervalOperation(bounds, source, destination); ParallelRowIterator.IterateRows( bounds, @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The source for the current instance. /// The destination for the current instance. [MethodImpl(InliningOptions.ShortMethod)] - public RowIntervalOperation(ref Rectangle bounds, ImageFrame source, ImageFrame destination) + public RowIntervalOperation(Rectangle bounds, ImageFrame source, ImageFrame destination) { this.bounds = bounds; this.source = source; diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs index b241021aa2..da071e3f22 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs @@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { Rectangle sourceBounds = this.SourceRectangle; - var nnOperation = new NearestNeighborRowIntervalOperation(ref sourceBounds, ref matrix, width, source, destination); + var nnOperation = new NearestNeighborRowIntervalOperation(sourceBounds, ref matrix, width, source, destination); ParallelRowIterator.IterateRows( configuration, targetBounds, @@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(InliningOptions.ShortMethod)] public NearestNeighborRowIntervalOperation( - ref Rectangle bounds, + Rectangle bounds, ref Matrix4x4 matrix, int maxX, ImageFrame source, diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs index d3d59a5940..8e8eaceb05 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// public void Dispose() { - Unsafe.AsRef(this.pinHandle).Dispose(); + this.pinHandle.Dispose(); this.data.Dispose(); }