/// <inheritdoc/> protected override void OnFrameApply(ImageFrame <TPixel> source) { var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); if (interest.Width == 0 || interest.Height == 0) { return; } Configuration configuration = this.Configuration; IBrush brush = this.definition.Brush; GraphicsOptions options = this.definition.Options; // If there's no reason for blending, then avoid it. if (this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush)) { ParallelExecutionSettings parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration) .MultiplyMinimumPixelsPerTask(4); TPixel colorPixel = solidBrush.Color.ToPixel <TPixel>(); var solidOperation = new SolidBrushRowIntervalOperation(interest, source, colorPixel); ParallelRowIterator.IterateRowIntervals( interest, parallelSettings, in solidOperation); return; } using IMemoryOwner <float> amount = configuration.MemoryAllocator.Allocate <float>(interest.Width); using BrushApplicator <TPixel> applicator = brush.CreateApplicator( configuration, options, source, interest); amount.Memory.Span.Fill(1F); var operation = new RowIntervalOperation(interest, applicator, amount.Memory); ParallelRowIterator.IterateRowIntervals( configuration, interest, in operation); }
/// <inheritdoc/> protected override void OnFrameApply(ImageFrame <TPixel> source) { Rectangle sourceRectangle = this.SourceRectangle; Configuration configuration = this.Configuration; int startX = sourceRectangle.X; int endX = sourceRectangle.Right; int startY = sourceRectangle.Y; int endY = sourceRectangle.Bottom; // Align start/end positions. int minX = Math.Max(0, startX); int maxX = Math.Min(source.Width, endX); int minY = Math.Max(0, startY); int maxY = Math.Min(source.Height, endY); int width = maxX - minX; var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); IBrush brush = this.definition.Brush; GraphicsOptions options = this.definition.Options; // If there's no reason for blending, then avoid it. if (this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush)) { ParallelExecutionSettings parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration) .MultiplyMinimumPixelsPerTask(4); TPixel colorPixel = solidBrush.Color.ToPixel <TPixel>(); ParallelHelper.IterateRows( workingRect, parallelSettings, rows => { for (int y = rows.Min; y < rows.Max; y++) { source.GetPixelRowSpan(y).Slice(minX, width).Fill(colorPixel); } }); } else { // Reset offset if necessary. if (minX > 0) { startX = 0; } if (minY > 0) { startY = 0; } using (IMemoryOwner <float> amount = source.MemoryAllocator.Allocate <float>(width)) using (BrushApplicator <TPixel> applicator = brush.CreateApplicator( configuration, options, source, sourceRectangle)) { amount.Memory.Span.Fill(1f); ParallelHelper.IterateRows( workingRect, configuration, rows => { for (int y = rows.Min; y < rows.Max; y++) { int offsetY = y - startY; int offsetX = minX - startX; applicator.Apply(amount.Memory.Span, offsetX, offsetY); } }); } } }