diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs index 06c588af3..eb08bc579 100644 --- a/src/ImageSharp/Configuration.cs +++ b/src/ImageSharp/Configuration.cs @@ -18,7 +18,7 @@ using SixLabors.ImageSharp.Processing; namespace SixLabors.ImageSharp { /// - /// Provides initialization code which allows extending the library. + /// Provides configuration code which allows altering default behaviour or extending the library. /// public sealed class Configuration { diff --git a/src/ImageSharp/ImageFrame.LoadPixelData.cs b/src/ImageSharp/ImageFrame.LoadPixelData.cs index 4639a104b..33dbe31df 100644 --- a/src/ImageSharp/ImageFrame.LoadPixelData.cs +++ b/src/ImageSharp/ImageFrame.LoadPixelData.cs @@ -4,7 +4,6 @@ using System; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp @@ -12,37 +11,37 @@ namespace SixLabors.ImageSharp /// /// Adds static methods allowing the creation of new image from raw pixel data. /// - internal static partial class ImageFrame + internal static class ImageFrame { /// /// Create a new instance of the class from the given byte array in format. /// - /// The memory manager to use for allocations + /// The configuration which allows altering default behaviour or extending the library. /// The byte array containing image data. /// The width of the final image. /// The height of the final image. /// The pixel format. /// A new . - public static ImageFrame LoadPixelData(MemoryManager memoryManager, ReadOnlySpan data, int width, int height) + public static ImageFrame LoadPixelData(Configuration configuration, ReadOnlySpan data, int width, int height) where TPixel : struct, IPixel - => LoadPixelData(memoryManager, MemoryMarshal.Cast(data), width, height); + => LoadPixelData(configuration, MemoryMarshal.Cast(data), width, height); /// /// Create a new instance of the class from the raw data. /// - /// The memory manager to use for allocations + /// The configuration which allows altering default behaviour or extending the library. /// The Span containing the image Pixel data. /// The width of the final image. /// The height of the final image. /// The pixel format. /// A new . - public static ImageFrame LoadPixelData(MemoryManager memoryManager, ReadOnlySpan data, int width, int height) + public static ImageFrame LoadPixelData(Configuration configuration, ReadOnlySpan data, int width, int height) where TPixel : struct, IPixel { int count = width * height; Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data)); - var image = new ImageFrame(memoryManager, width, height); + var image = new ImageFrame(configuration, width, height); data.Slice(0, count).CopyTo(image.GetPixelSpan()); diff --git a/src/ImageSharp/ImageFrameCollection.cs b/src/ImageSharp/ImageFrameCollection.cs index be15a6527..c101b48d3 100644 --- a/src/ImageSharp/ImageFrameCollection.cs +++ b/src/ImageSharp/ImageFrameCollection.cs @@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp Guard.NotNull(source, nameof(source)); var frame = ImageFrame.LoadPixelData( - this.parent.GetMemoryManager(), + this.parent.GetConfiguration(), new ReadOnlySpan(source), this.RootFrame.Width, this.RootFrame.Height); diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs index c3955c132..f1fff473e 100644 --- a/src/ImageSharp/ImageFrame{TPixel}.cs +++ b/src/ImageSharp/ImageFrame{TPixel}.cs @@ -4,7 +4,6 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; @@ -19,53 +18,61 @@ namespace SixLabors.ImageSharp /// /// The pixel format. public sealed class ImageFrame : IPixelSource, IDisposable - where TPixel : struct, IPixel { + where TPixel : struct, IPixel + { + private readonly Configuration configuration; private bool isDisposed; /// /// Initializes a new instance of the class. /// - /// The to use for buffer allocations. + /// The configuration which allows altering default behaviour or extending the library. /// The width of the image in pixels. /// The height of the image in pixels. - internal ImageFrame(MemoryManager memoryManager, int width, int height) - : this(memoryManager, width, height, new ImageFrameMetaData()) { + internal ImageFrame(Configuration configuration, int width, int height) + : this(configuration, width, height, new ImageFrameMetaData()) + { } /// /// Initializes a new instance of the class. /// - /// The to use for buffer allocations. + /// The configuration which allows altering default behaviour or extending the library. + /// The of the frame. + /// The meta data. + internal ImageFrame(Configuration configuration, Size size, ImageFrameMetaData metaData) + : this(configuration, size.Width, size.Height, metaData) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The configuration which allows altering default behaviour or extending the library. /// The width of the image in pixels. /// The height of the image in pixels. /// The meta data. - internal ImageFrame(MemoryManager memoryManager, int width, int height, ImageFrameMetaData metaData) + internal ImageFrame(Configuration configuration, int width, int height, ImageFrameMetaData metaData) + : this(configuration, width, height, default, metaData) { - Guard.NotNull(memoryManager, nameof(memoryManager)); - Guard.MustBeGreaterThan(width, 0, nameof(width)); - Guard.MustBeGreaterThan(height, 0, nameof(height)); - Guard.NotNull(metaData, nameof(metaData)); - - this.MemoryManager = memoryManager; - this.PixelBuffer = memoryManager.AllocateClean2D(width, height); - this.MetaData = metaData; } /// /// Initializes a new instance of the class. /// - /// The to use for buffer allocation and parallel options to clear the buffer with. + /// The configuration which allows altering default behaviour or extending the library. /// The width of the image in pixels. /// The height of the image in pixels. /// The color to clear the image with. internal ImageFrame(Configuration configuration, int width, int height, TPixel backgroundColor) - : this(configuration, width, height, backgroundColor, new ImageFrameMetaData()) { + : this(configuration, width, height, backgroundColor, new ImageFrameMetaData()) + { } /// /// Initializes a new instance of the class. /// - /// The to use for buffer allocation and parallel options to clear the buffer with. + /// The configuration which allows altering default behaviour or extending the library. /// The width of the image in pixels. /// The height of the image in pixels. /// The color to clear the image with. @@ -77,31 +84,31 @@ namespace SixLabors.ImageSharp Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.NotNull(metaData, nameof(metaData)); + this.configuration = configuration; this.MemoryManager = configuration.MemoryManager; this.PixelBuffer = this.MemoryManager.Allocate2D(width, height, false); - this.Clear(configuration.ParallelOptions, backgroundColor); - this.MetaData = metaData; - } - /// - /// Initializes a new instance of the class. - /// - /// The to use for buffer allocations. - /// The of the frame. - /// The meta data. - internal ImageFrame(MemoryManager memoryManager, Size size, ImageFrameMetaData metaData) - : this(memoryManager, size.Width, size.Height, metaData) { + if (!default(TPixel).Equals(backgroundColor)) + { + this.Clear(configuration.ParallelOptions, backgroundColor); + } + + this.MetaData = metaData; } /// /// Initializes a new instance of the class. /// - /// The to use for buffer allocations. + /// The configuration which allows altering default behaviour or extending the library. /// The source. - internal ImageFrame(MemoryManager memoryManager, ImageFrame source) + internal ImageFrame(Configuration configuration, ImageFrame source) { - this.MemoryManager = memoryManager; - this.PixelBuffer = memoryManager.Allocate2D(source.PixelBuffer.Width, source.PixelBuffer.Height); + Guard.NotNull(configuration, nameof(configuration)); + Guard.NotNull(source, nameof(source)); + + this.configuration = configuration; + this.MemoryManager = configuration.MemoryManager; + this.PixelBuffer = this.MemoryManager.Allocate2D(source.PixelBuffer.Width, source.PixelBuffer.Height); source.PixelBuffer.Span.CopyTo(this.PixelBuffer.Span); this.MetaData = source.MetaData.Clone(); } @@ -276,13 +283,12 @@ namespace SixLabors.ImageSharp return this.Clone() as ImageFrame; } - var target = new ImageFrame(this.MemoryManager, this.Width, this.Height, this.MetaData.Clone()); + var target = new ImageFrame(this.configuration, this.Width, this.Height, this.MetaData.Clone()); - // TODO: ImageFrame has no visibility of the current configuration. It should have. ParallelFor.WithTemporaryBuffer( 0, this.Height, - Configuration.Default, + this.configuration, this.Width, (int y, IBuffer tempRowBuffer) => { @@ -302,12 +308,13 @@ namespace SixLabors.ImageSharp /// /// The parallel options. /// The value to initialize the bitmap with. - internal void Clear(ParallelOptions parallelOptions, TPixel value) { + internal void Clear(ParallelOptions parallelOptions, TPixel value) + { Parallel.For( 0, this.Height, parallelOptions, - (int y) => + y => { Span targetRow = this.GetPixelRowSpan(y); targetRow.Fill(value); @@ -320,7 +327,7 @@ namespace SixLabors.ImageSharp /// The internal ImageFrame Clone() { - return new ImageFrame(this.MemoryManager, this); + return new ImageFrame(this.configuration, this); } /// diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index 596dc9bcd..324385601 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp this.configuration = configuration ?? Configuration.Default; this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); this.MetaData = metadata ?? new ImageMetaData(); - this.frames = new ImageFrameCollection(this, width, height, default(TPixel)); + this.frames = new ImageFrameCollection(this, width, height, default); } /// diff --git a/src/ImageSharp/Processing/Transforms/Processors/AffineTransformProcessor.cs b/src/ImageSharp/Processing/Transforms/Processors/AffineTransformProcessor.cs index 2d6083e55..7c1a581b0 100644 --- a/src/ImageSharp/Processing/Transforms/Processors/AffineTransformProcessor.cs +++ b/src/ImageSharp/Processing/Transforms/Processors/AffineTransformProcessor.cs @@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Processing.Transforms.Processors { // We will always be creating the clone even for mutate because we may need to resize the canvas IEnumerable> frames = - source.Frames.Select(x => new ImageFrame(source.GetMemoryManager(), this.TargetDimensions, x.MetaData.Clone())); + source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions, x.MetaData.Clone())); // Use the overload to prevent an extra frame being added return new Image(source.GetConfiguration(), source.MetaData.Clone(), frames); diff --git a/src/ImageSharp/Processing/Transforms/Processors/CropProcessor.cs b/src/ImageSharp/Processing/Transforms/Processors/CropProcessor.cs index bfbf349b5..848ea7b62 100644 --- a/src/ImageSharp/Processing/Transforms/Processors/CropProcessor.cs +++ b/src/ImageSharp/Processing/Transforms/Processors/CropProcessor.cs @@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Processing.Transforms.Processors protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetMemoryManager(), this.CropRectangle.Width, this.CropRectangle.Height, x.MetaData.Clone())); + IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.CropRectangle.Width, this.CropRectangle.Height, x.MetaData.Clone())); // Use the overload to prevent an extra frame being added return new Image(source.GetConfiguration(), source.MetaData.Clone(), frames); diff --git a/src/ImageSharp/Processing/Transforms/Processors/ProjectiveTransformProcessor.cs b/src/ImageSharp/Processing/Transforms/Processors/ProjectiveTransformProcessor.cs index 9f7654037..a55613dec 100644 --- a/src/ImageSharp/Processing/Transforms/Processors/ProjectiveTransformProcessor.cs +++ b/src/ImageSharp/Processing/Transforms/Processors/ProjectiveTransformProcessor.cs @@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Transforms.Processors { // We will always be creating the clone even for mutate because we may need to resize the canvas IEnumerable> frames = - source.Frames.Select(x => new ImageFrame(source.GetMemoryManager(), this.TargetDimensions.Width, this.TargetDimensions.Height, x.MetaData.Clone())); + source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions.Width, this.TargetDimensions.Height, x.MetaData.Clone())); // Use the overload to prevent an extra frame being added return new Image(source.GetConfiguration(), source.MetaData.Clone(), frames); diff --git a/src/ImageSharp/Processing/Transforms/Processors/ResizeProcessor.cs b/src/ImageSharp/Processing/Transforms/Processors/ResizeProcessor.cs index 27dc39ef1..b8df67658 100644 --- a/src/ImageSharp/Processing/Transforms/Processors/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Transforms/Processors/ResizeProcessor.cs @@ -214,7 +214,7 @@ namespace SixLabors.ImageSharp.Processing.Transforms.Processors protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetMemoryManager(), this.Width, this.Height, x.MetaData.Clone())); + IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.Width, this.Height, x.MetaData.Clone())); // Use the overload to prevent an extra frame being added return new Image(source.GetConfiguration(), source.MetaData.Clone(), frames); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs index 7e7518fd4..45ee64cb4 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg string imageFile = provider.SourceFileOrDescription; using (PdfJsJpegDecoderCore decoder = JpegFixture.ParsePdfJsStream(imageFile)) using (var pp = new JpegImagePostProcessor(Configuration.Default.MemoryManager, decoder)) - using (var imageFrame = new ImageFrame(Configuration.Default.MemoryManager, decoder.ImageWidth, decoder.ImageHeight)) + using (var imageFrame = new ImageFrame(Configuration.Default, decoder.ImageWidth, decoder.ImageHeight)) { pp.DoPostProcessorStep(imageFrame); diff --git a/tests/ImageSharp.Tests/Image/ImageFramesCollectionTests.cs b/tests/ImageSharp.Tests/Image/ImageFramesCollectionTests.cs index c2ebf83ba..a26d88720 100644 --- a/tests/ImageSharp.Tests/Image/ImageFramesCollectionTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageFramesCollectionTests.cs @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests { ArgumentException ex = Assert.Throws(() => { - this.collection.AddFrame(new ImageFrame(Configuration.Default.MemoryManager, 1, 1)); + this.collection.AddFrame(new ImageFrame(Configuration.Default, 1, 1)); }); Assert.StartsWith("Frame must have the same dimensions as the image.", ex.Message); @@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Tests { ArgumentException ex = Assert.Throws(() => { - this.collection.InsertFrame(1, new ImageFrame(Configuration.Default.MemoryManager, 1, 1)); + this.collection.InsertFrame(1, new ImageFrame(Configuration.Default, 1, 1)); }); Assert.StartsWith("Frame must have the same dimensions as the image.", ex.Message); @@ -102,8 +102,8 @@ namespace SixLabors.ImageSharp.Tests ArgumentException ex = Assert.Throws(() => { var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default.MemoryManager,10,10), - new ImageFrame(Configuration.Default.MemoryManager,1,1), + new ImageFrame(Configuration.Default,10,10), + new ImageFrame(Configuration.Default,1,1) }); }); @@ -114,7 +114,7 @@ namespace SixLabors.ImageSharp.Tests public void RemoveAtFrame_ThrowIfRemovingLastFrame() { var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default.MemoryManager,10,10) + new ImageFrame(Configuration.Default,10,10) }); InvalidOperationException ex = Assert.Throws(() => @@ -129,8 +129,8 @@ namespace SixLabors.ImageSharp.Tests { var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default.MemoryManager,10,10), - new ImageFrame(Configuration.Default.MemoryManager,10,10), + new ImageFrame(Configuration.Default,10,10), + new ImageFrame(Configuration.Default,10,10) }); collection.RemoveFrame(0); @@ -141,8 +141,8 @@ namespace SixLabors.ImageSharp.Tests public void RootFrameIsFrameAtIndexZero() { var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default.MemoryManager,10,10), - new ImageFrame(Configuration.Default.MemoryManager,10,10), + new ImageFrame(Configuration.Default,10,10), + new ImageFrame(Configuration.Default,10,10) }); Assert.Equal(collection.RootFrame, collection[0]); @@ -152,8 +152,8 @@ namespace SixLabors.ImageSharp.Tests public void ConstructorPopulatesFrames() { var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default.MemoryManager,10,10), - new ImageFrame(Configuration.Default.MemoryManager,10,10), + new ImageFrame(Configuration.Default,10,10), + new ImageFrame(Configuration.Default,10,10) }); Assert.Equal(2, collection.Count); @@ -163,8 +163,8 @@ namespace SixLabors.ImageSharp.Tests public void DisposeClearsCollection() { var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default.MemoryManager,10,10), - new ImageFrame(Configuration.Default.MemoryManager,10,10), + new ImageFrame(Configuration.Default,10,10), + new ImageFrame(Configuration.Default,10,10) }); collection.Dispose(); @@ -176,8 +176,8 @@ namespace SixLabors.ImageSharp.Tests public void Dispose_DisposesAllInnerFrames() { var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default.MemoryManager,10,10), - new ImageFrame(Configuration.Default.MemoryManager,10,10), + new ImageFrame(Configuration.Default,10,10), + new ImageFrame(Configuration.Default,10,10) }); IPixelSource[] framesSnapShot = collection.OfType>().ToArray(); @@ -197,7 +197,7 @@ namespace SixLabors.ImageSharp.Tests { using (Image img = provider.GetImage()) { - img.Frames.AddFrame(new ImageFrame(Configuration.Default.MemoryManager, 10, 10));// add a frame anyway + img.Frames.AddFrame(new ImageFrame(Configuration.Default, 10, 10));// add a frame anyway using (Image cloned = img.Frames.CloneFrame(0)) { Assert.Equal(2, img.Frames.Count); @@ -215,7 +215,7 @@ namespace SixLabors.ImageSharp.Tests { var sourcePixelData = img.GetPixelSpan().ToArray(); - img.Frames.AddFrame(new ImageFrame(Configuration.Default.MemoryManager, 10, 10)); + img.Frames.AddFrame(new ImageFrame(Configuration.Default, 10, 10)); using (Image cloned = img.Frames.ExportFrame(0)) { Assert.Equal(1, img.Frames.Count); @@ -254,7 +254,7 @@ namespace SixLabors.ImageSharp.Tests public void AddFrame_clones_sourceFrame() { var pixelData = this.image.Frames.RootFrame.GetPixelSpan().ToArray(); - var otherFRame = new ImageFrame(Configuration.Default.MemoryManager, 10, 10); + var otherFRame = new ImageFrame(Configuration.Default, 10, 10); var addedFrame = this.image.Frames.AddFrame(otherFRame); addedFrame.ComparePixelBufferTo(otherFRame.GetPixelSpan()); Assert.NotEqual(otherFRame, addedFrame); @@ -264,7 +264,7 @@ namespace SixLabors.ImageSharp.Tests public void InsertFrame_clones_sourceFrame() { var pixelData = this.image.Frames.RootFrame.GetPixelSpan().ToArray(); - var otherFRame = new ImageFrame(Configuration.Default.MemoryManager, 10, 10); + var otherFRame = new ImageFrame(Configuration.Default, 10, 10); var addedFrame = this.image.Frames.InsertFrame(0, otherFRame); addedFrame.ComparePixelBufferTo(otherFRame.GetPixelSpan()); Assert.NotEqual(otherFRame, addedFrame); @@ -318,7 +318,7 @@ namespace SixLabors.ImageSharp.Tests this.image.Frames.CreateFrame(); } - var frame = new ImageFrame(Configuration.Default.MemoryManager, 10, 10); + var frame = new ImageFrame(Configuration.Default, 10, 10); Assert.False(this.image.Frames.Contains(frame)); }