-
-
Notifications
You must be signed in to change notification settings - Fork 888
Issue 551 solidbrush blend performance #552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
5a1569f
08b033c
58384de
8995a73
a3a1556
02fc4ef
a38bb5a
2943df1
aa4a057
7e2fd11
7c70a5e
0d81089
d2bfaf2
24f6ff9
a9816fd
72cb50c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,7 +23,7 @@ internal ImageFrameCollection(Image<TPixel> parent, int width, int height) | |
| this.parent = parent; | ||
|
|
||
| // Frames are already cloned within the caller | ||
| this.frames.Add(new ImageFrame<TPixel>(parent.GetConfiguration().MemoryManager, width, height)); | ||
| this.frames.Add(new ImageFrame<TPixel>(parent.GetConfiguration(), width, height, parent.ClearColor)); | ||
| } | ||
|
|
||
| internal ImageFrameCollection(Image<TPixel> parent, IEnumerable<ImageFrame<TPixel>> frames) | ||
|
|
@@ -143,7 +143,7 @@ public Image<TPixel> CloneFrame(int index) | |
| /// <inheritdoc/> | ||
| public ImageFrame<TPixel> CreateFrame() | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's create an overload for this that accepts a color, then we cover all bases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see the method implements a member from interface IImageFrameCollection, wouldn't it be nice to change it to: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we don’t actually need the interface. I can’t see why someone would need to implement it themselves. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @JimBobSquarePants I remember having a conversation about optional arguments, with the conclusion that we should prefer overloads instead because of better binary compatibility. Is this still a thing we should follow? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, always choose overloads. |
||
| { | ||
| var frame = new ImageFrame<TPixel>(this.parent.GetConfiguration().MemoryManager, this.RootFrame.Width, this.RootFrame.Height); | ||
| ImageFrame<TPixel> frame = new ImageFrame<TPixel>(this.parent.GetConfiguration(), this.RootFrame.Width, this.RootFrame.Height, this.parent.ClearColor); | ||
| this.frames.Add(frame); | ||
| return frame; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
| 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; | ||
|
|
@@ -52,6 +53,39 @@ internal ImageFrame(MemoryManager memoryManager, int width, int height, ImageFra | |
| this.MetaData = metaData; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class. | ||
| /// </summary> | ||
| /// <param name="configuration">The <see cref="Configuration"/> to use for buffer allocation and parallel options to clear the buffer with.</param> | ||
| /// <param name="width">The width of the image in pixels.</param> | ||
| /// <param name="height">The height of the image in pixels.</param> | ||
| /// <param name="clearColor">The color to clear the image with.</param> | ||
| internal ImageFrame(Configuration configuration, int width, int height, TPixel clearColor) | ||
|
||
| : this(configuration, width, height, clearColor, new ImageFrameMetaData()) | ||
| { | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class. | ||
| /// </summary> | ||
| /// <param name="configuration">The <see cref="Configuration"/> to use for buffer allocation and parallel options to clear the buffer with.</param> | ||
| /// <param name="width">The width of the image in pixels.</param> | ||
| /// <param name="height">The height of the image in pixels.</param> | ||
| /// <param name="clearColor">The color to clear the image with.</param> | ||
| /// <param name="metaData">The meta data.</param> | ||
| internal ImageFrame(Configuration configuration, int width, int height, TPixel clearColor, ImageFrameMetaData metaData) | ||
| { | ||
| Guard.NotNull(configuration, nameof(configuration)); | ||
| Guard.MustBeGreaterThan(width, 0, nameof(width)); | ||
| Guard.MustBeGreaterThan(height, 0, nameof(height)); | ||
| Guard.NotNull(metaData, nameof(metaData)); | ||
|
|
||
| this.MemoryManager = configuration.MemoryManager; | ||
| this.PixelBuffer = this.MemoryManager.Allocate2D<TPixel>(width, height, false); | ||
| this.Clear(configuration.ParallelOptions, clearColor); | ||
|
||
| this.MetaData = metaData; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class. | ||
| /// </summary> | ||
|
|
@@ -267,6 +301,23 @@ internal ImageFrame<TPixel2> CloneAs<TPixel2>() | |
| return target; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Clears the bitmap. | ||
| /// </summary> | ||
| /// <param name="parallelOptions">The parallel options.</param> | ||
| /// <param name="value">The value to initialize the bitmap with.</param> | ||
| public void Clear(ParallelOptions parallelOptions, TPixel value) { | ||
|
||
| Parallel.For( | ||
| 0, | ||
| this.Height, | ||
| parallelOptions, | ||
| (int y) => | ||
| { | ||
| Span<TPixel> targetRow = this.GetPixelRowSpan(y); | ||
| targetRow.Fill(value); | ||
| }); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Clones the current instance. | ||
| /// </summary> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,7 @@ public sealed class Image<TPixel> : IImage, IConfigurable | |
| { | ||
| private readonly Configuration configuration; | ||
| private readonly ImageFrameCollection<TPixel> frames; | ||
| private readonly TPixel clearColor; | ||
|
||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="Image{TPixel}"/> class | ||
|
|
@@ -37,6 +38,21 @@ public Image(Configuration configuration, int width, int height) | |
| { | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="Image{TPixel}"/> class | ||
| /// with the height and the width of the image. | ||
| /// </summary> | ||
| /// <param name="configuration"> | ||
| /// The configuration providing initialization code which allows extending the library. | ||
| /// </param> | ||
| /// <param name="width">The width of the image in pixels.</param> | ||
| /// <param name="height">The height of the image in pixels.</param> | ||
| /// <param name="clearColor">The color to initialize the pixels with.</param> | ||
| public Image(Configuration configuration, int width, int height, TPixel clearColor) | ||
|
||
| : this(configuration, width, height, clearColor, new ImageMetaData()) | ||
| { | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="Image{TPixel}"/> class | ||
| /// with the height and the width of the image. | ||
|
|
@@ -66,6 +82,25 @@ internal Image(Configuration configuration, int width, int height, ImageMetaData | |
| this.frames = new ImageFrameCollection<TPixel>(this, width, height); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="Image{TPixel}"/> class | ||
| /// with the height and the width of the image. | ||
| /// </summary> | ||
| /// <param name="configuration"> | ||
| /// The configuration providing initialization code which allows extending the library. | ||
| /// </param> | ||
| /// <param name="width">The width of the image in pixels.</param> | ||
| /// <param name="height">The height of the image in pixels.</param> | ||
| /// <param name="clearColor">The clear color.</param> | ||
| /// <param name="metadata">The images metadata.</param> | ||
| internal Image(Configuration configuration, int width, int height, TPixel clearColor, ImageMetaData metadata) { | ||
| this.configuration = configuration ?? Configuration.Default; | ||
| this.PixelType = new PixelTypeInfo(Unsafe.SizeOf<TPixel>() * 8); | ||
| this.MetaData = metadata ?? new ImageMetaData(); | ||
| this.clearColor = clearColor; | ||
| this.frames = new ImageFrameCollection<TPixel>(this, width, height); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="Image{TPixel}" /> class | ||
| /// with the height and the width of the image. | ||
|
|
@@ -104,6 +139,11 @@ internal Image(Configuration configuration, ImageMetaData metadata, IEnumerable< | |
| /// </summary> | ||
| public IImageFrameCollection<TPixel> Frames => this.frames; | ||
|
|
||
| /// <summary> | ||
| /// Gets the clear color to initialize the image frame pixels with. | ||
| /// </summary> | ||
| internal TPixel ClearColor => this.clearColor; | ||
|
||
|
|
||
| /// <summary> | ||
| /// Gets the root frame. | ||
| /// </summary> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,6 +52,18 @@ public static void Clear<T>(this IBuffer<T> buffer) | |
| buffer.Span.Clear(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Fills the contents of this buffer. | ||
| /// </summary> | ||
| /// <param name="buffer">The buffer</param> | ||
| /// <param name="value">The value to fill the buffer with.</param> | ||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| public static void Fill<T>(this IBuffer<T> buffer, T value) | ||
|
||
| where T : struct | ||
| { | ||
| buffer.Span.Fill(value); | ||
| } | ||
|
|
||
| public static ref T DangerousGetPinnableReference<T>(this IBuffer<T> buffer) | ||
| where T : struct => | ||
| ref MemoryMarshal.GetReference(buffer.Span); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I refactor this logic into an
IsSolidBrushWithoutBlendingproperty or similar for better readability.