diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 4f8ab3462..dfef69b75 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -37,8 +37,8 @@ - - + + All diff --git a/src/ImageSharp.Drawing/Paths/ShapeRegion.cs b/src/ImageSharp.Drawing/Paths/ShapeRegion.cs index a303179e8..1965a7433 100644 --- a/src/ImageSharp.Drawing/Paths/ShapeRegion.cs +++ b/src/ImageSharp.Drawing/Paths/ShapeRegion.cs @@ -42,18 +42,18 @@ namespace SixLabors.ImageSharp.Drawing public override Rectangle Bounds { get; } /// - public override int Scan(float y, Span buffer) + public override int Scan(float y, float[] buffer, int offset) { var start = new PointF(this.Bounds.Left - 1, y); var end = new PointF(this.Bounds.Right + 1, y); using (var innerBuffer = new Buffer(buffer.Length)) { - var span = innerBuffer.Span; - int count = this.Shape.FindIntersections(start, end, span); + PointF[] array = innerBuffer.Array; + int count = this.Shape.FindIntersections(start, end, array, offset); for (int i = 0; i < count; i++) { - buffer[i] = span[i].X; + buffer[i] = array[i].X; } return count; diff --git a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs index 3e0dedb3b..78231d29a 100644 --- a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs +++ b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs @@ -93,7 +93,6 @@ namespace SixLabors.ImageSharp.Drawing.Processors using (BrushApplicator applicator = this.Brush.CreateApplicator(source, rect, this.Options)) { float[] buffer = arrayPool.Rent(maxIntersections); - Span bufferSpan = buffer.AsSpan().Slice(0, maxIntersections); int scanlineWidth = maxX - minX; using (var scanline = new Buffer(scanlineWidth)) { @@ -117,14 +116,14 @@ namespace SixLabors.ImageSharp.Drawing.Processors float subpixelFractionPoint = subpixelFraction / subpixelCount; for (float subPixel = (float)y; subPixel < y + 1; subPixel += subpixelFraction) { - int pointsFound = region.Scan(subPixel, bufferSpan); + int pointsFound = region.Scan(subPixel, buffer, 0); if (pointsFound == 0) { // nothing on this line skip continue; } - QuickSort(bufferSpan.Slice(0, pointsFound)); + QuickSort(buffer.AsSpan().Slice(0, pointsFound)); for (int point = 0; point < pointsFound; point += 2) { diff --git a/src/ImageSharp.Drawing/Region.cs b/src/ImageSharp.Drawing/Region.cs index 5d4d471f1..c5e7c1cfd 100644 --- a/src/ImageSharp.Drawing/Region.cs +++ b/src/ImageSharp.Drawing/Region.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Drawing /// Gets the bounding box that entirely surrounds this region. /// /// - /// This should always contains all possible points returned from . + /// This should always contains all possible points returned from . /// public abstract Rectangle Bounds { get; } @@ -29,7 +29,8 @@ namespace SixLabors.ImageSharp.Drawing /// /// The position along the y axis to find intersections. /// The buffer. + /// The point in the buffer to start setting offset. /// The number of intersections found. - public abstract int Scan(float y, Span buffer); + public abstract int Scan(float y, float[] buffer, int offset); } } \ No newline at end of file diff --git a/src/ImageSharp/Advanced/ImageExtensions.cs b/src/ImageSharp/Advanced/ImageExtensions.cs index 7377e6ca0..ca2e522f5 100644 --- a/src/ImageSharp/Advanced/ImageExtensions.cs +++ b/src/ImageSharp/Advanced/ImageExtensions.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Advanced /// /// Extension methods over Image{TPixel} /// - public static partial class ImageExtensions + internal static partial class ImageExtensions { /// /// Gets the representation of the pixels as an area of contiguous memory in the given pixel format. diff --git a/src/ImageSharp/Image/Image.LoadPixelData.cs b/src/ImageSharp/Image/Image.LoadPixelData.cs index 6302eb66b..d6ed4fcde 100644 --- a/src/ImageSharp/Image/Image.LoadPixelData.cs +++ b/src/ImageSharp/Image/Image.LoadPixelData.cs @@ -25,7 +25,19 @@ namespace SixLabors.ImageSharp /// The height of the final image. /// The pixel format. /// A new . - public static Image LoadPixelData(Span data, int width, int height) + public static Image LoadPixelData(TPixel[] data, int width, int height) + where TPixel : struct, IPixel + => LoadPixelData(Configuration.Default, data, width, height); + + /// + /// Create a new instance of the class from the raw data. + /// + /// The byte array containing image data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + private static Image LoadPixelData(Span data, int width, int height) where TPixel : struct, IPixel => LoadPixelData(Configuration.Default, data, width, height); @@ -37,7 +49,19 @@ namespace SixLabors.ImageSharp /// The height of the final image. /// The pixel format. /// A new . - public static Image LoadPixelData(Span data, int width, int height) + public static Image LoadPixelData(byte[] data, int width, int height) + where TPixel : struct, IPixel + => LoadPixelData(Configuration.Default, data, width, height); + + /// + /// Create a new instance of the class from the given byte array in format. + /// + /// The byte array containing image data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + private static Image LoadPixelData(Span data, int width, int height) where TPixel : struct, IPixel => LoadPixelData(Configuration.Default, data, width, height); @@ -50,7 +74,20 @@ namespace SixLabors.ImageSharp /// The height of the final image. /// The pixel format. /// A new . - public static Image LoadPixelData(Configuration config, Span data, int width, int height) + public static Image LoadPixelData(Configuration config, byte[] data, int width, int height) + where TPixel : struct, IPixel + => LoadPixelData(config, new Span(data).NonPortableCast(), width, height); + + /// + /// Create a new instance of the class from the given byte array in format. + /// + /// The config for the decoder. + /// The byte array containing image data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + private static Image LoadPixelData(Configuration config, Span data, int width, int height) where TPixel : struct, IPixel => LoadPixelData(config, data.NonPortableCast(), width, height); @@ -63,7 +100,28 @@ namespace SixLabors.ImageSharp /// The height of the final image. /// The pixel format. /// A new . - public static Image LoadPixelData(Configuration config, Span data, int width, int height) + public static Image LoadPixelData(Configuration config, TPixel[] data, int width, int height) + where TPixel : struct, IPixel + { + int count = width * height; + Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data)); + + var image = new Image(config, width, height); + SpanHelper.Copy(data, image.GetPixelSpan(), count); + + return image; + } + + /// + /// Create a new instance of the class from the raw data. + /// + /// The config for the decoder. + /// The Span containing the image Pixel data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + private static Image LoadPixelData(Configuration config, Span data, int width, int height) where TPixel : struct, IPixel { int count = width * height; diff --git a/src/ImageSharp/Image/ImageExtensions.cs b/src/ImageSharp/Image/ImageExtensions.cs index 6844bdc81..afd434381 100644 --- a/src/ImageSharp/Image/ImageExtensions.cs +++ b/src/ImageSharp/Image/ImageExtensions.cs @@ -138,7 +138,7 @@ namespace SixLabors.ImageSharp /// The source image /// The buffer to save the raw pixel data to. /// Thrown if the stream is null. - public static void SavePixelData(this Image source, Span buffer) + internal static void SavePixelData(this Image source, byte[] buffer) where TPixel : struct, IPixel { Span byteBuffer = source.GetPixelSpan().AsBytes(); diff --git a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs index 9540ee81b..db6c1157c 100644 --- a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing Image img = new Image(1, 1); processor.Apply(img, bounds); - region.Verify(x => x.Scan(It.IsAny(), It.IsAny>()), Times.Exactly(4)); + region.Verify(x => x.Scan(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(4)); } [Fact] @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing region.Setup(x => x.Bounds).Returns(bounds); region.Setup(x => x.MaxIntersections).Returns(10); - region.Setup(x => x.Scan(It.IsAny(), It.IsAny>())) + region.Setup(x => x.Scan(It.IsAny(), It.IsAny(), It.IsAny())) .Returns>((y, span) => { if (y < 5) diff --git a/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs b/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs index 41fb5643f..f5950a6ef 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths int yToScan = 10; ShapeRegion region = new ShapeRegion(pathMock.Object); - pathMock.Setup(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny>())) + pathMock.Setup(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback>((s, e, b) => { Assert.Equal(yToScan, s.Y); Assert.Equal(yToScan, e.Y); @@ -84,9 +84,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Assert.True(e.X > bounds.Right); }).Returns(0); - int i = region.Scan(yToScan, new float[0]); + int i = region.Scan(yToScan, new float[0], 0); - pathMock.Verify(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny>()), Times.Once); + pathMock.Verify(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); } [Fact] @@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths int yToScan = 10; ShapeRegion region = new ShapeRegion(pathMock.Object); - pathMock.Setup(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny>())) + pathMock.Setup(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback>((s, e, b) => { Assert.Equal(yToScan, s.Y); Assert.Equal(yToScan, e.Y); @@ -103,9 +103,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Assert.True(e.X > bounds.Right); }).Returns(0); - int i = region.Scan(yToScan, new float[0]); + int i = region.Scan(yToScan, new float[0], 0); - pathMock.Verify(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny>()), Times.Once); + pathMock.Verify(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); } [Fact]