/// <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);
        }
예제 #2
0
        /// <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);
                            }
                        });
                    }
            }
        }