// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // namespace ImageSharp.Drawing.Processors { using System; using System.Numerics; using System.Threading.Tasks; using Drawing; using ImageSharp.Processing; /// /// Using the bursh as a source of pixels colors blends the brush color with source. /// /// The pixel format. public class FillProcessor : ImageProcessor where TColor : struct, IPackedPixel, IEquatable { /// /// The brush. /// private readonly IBrush brush; /// /// Initializes a new instance of the class. /// /// The brush to source pixel colors from. public FillProcessor(IBrush brush) { this.brush = brush; } /// protected override void OnApply(ImageBase source, Rectangle sourceRectangle) { 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); // Reset offset if necessary. if (minX > 0) { startX = 0; } if (minY > 0) { startY = 0; } // we could possibly do some optermising by having knowledge about the individual brushes operate // for example If brush is SolidBrush then we could just get the color upfront // and skip using the IBrushApplicator?. using (PixelAccessor sourcePixels = source.Lock()) using (IBrushApplicator applicator = this.brush.CreateApplicator(sourcePixels, sourceRectangle)) { Parallel.For( minY, maxY, this.ParallelOptions, y => { int offsetY = y - startY; Vector2 currentPoint = default(Vector2); for (int x = minX; x < maxX; x++) { int offsetX = x - startX; int offsetColorX = x - minX; currentPoint.X = offsetX; currentPoint.Y = offsetY; Vector4 backgroundVector = sourcePixels[offsetX, offsetY].ToVector4(); Vector4 sourceVector = applicator.GetColor(currentPoint).ToVector4(); var finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, 1); TColor packed = default(TColor); packed.PackFromVector4(finalColor); sourcePixels[offsetX, offsetY] = packed; } }); } } } }