/// <inheritdoc/> protected override void OnApply(ImageBase <TColor, TPacked> 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<TColor, TPacked> then we could just get the color upfront // and skip using the IBrushApplicator<TColor, TPacked>?. using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock()) using (IBrushApplicator <TColor, TPacked> applicator = this.brush.CreateApplicator(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; } }); } }
public PatternPenApplicator(IBrush <TColor, TPacked> brush, RectangleF region, float width, float[] pattern) { this.brush = brush.CreateApplicator(region); this.halfWidth = width / 2; this.totalLength = 0; this.pattern = new float[pattern.Length + 1]; this.pattern[0] = 0; for (var i = 0; i < pattern.Length; i++) { this.totalLength += pattern[i] * width; this.pattern[i + 1] = this.totalLength; } this.RequiredRegion = RectangleF.Outset(region, width); }
public SolidPenApplicator(IBrush <TColor, TPacked> brush, RectangleF region, float width) { this.brush = brush.CreateApplicator(region); this.halfWidth = width / 2; this.RequiredRegion = RectangleF.Outset(region, width); }
/// <inheritdoc/> protected override void OnApply(ImageBase <TColor, TPacked> source, Rectangle sourceRectangle) { var rect = RectangleF.Ceiling(this.poly.Bounds); // rounds the points out away from the center int polyStartY = rect.Y - DrawPadding; int polyEndY = rect.Bottom + DrawPadding; int startX = rect.X - DrawPadding; int endX = rect.Right + DrawPadding; int minX = Math.Max(sourceRectangle.Left, startX); int maxX = Math.Min(sourceRectangle.Right, endX); int minY = Math.Max(sourceRectangle.Top, polyStartY); int maxY = Math.Min(sourceRectangle.Bottom, polyEndY); // Align start/end positions. minX = Math.Max(0, minX); maxX = Math.Min(source.Width, maxX); minY = Math.Max(0, minY); maxY = Math.Min(source.Height, maxY); // Reset offset if necessary. if (minX > 0) { startX = 0; } if (minY > 0) { polyStartY = 0; } using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock()) using (IBrushApplicator <TColor, TPacked> applicator = this.fillColor.CreateApplicator(rect)) { Parallel.For( minY, maxY, this.ParallelOptions, y => { int offsetY = y - polyStartY; Vector2 currentPoint = default(Vector2); Vector2 currentPointOffset = default(Vector2); for (int x = minX; x < maxX; x++) { int offsetX = x - startX; currentPoint.X = offsetX; currentPoint.Y = offsetY; var dist = this.poly.Distance(currentPoint); var opacity = this.Opacity(dist); if (opacity > Epsilon) { int offsetColorX = x - minX; Vector4 backgroundVector = sourcePixels[offsetX, offsetY].ToVector4(); Vector4 sourceVector = applicator.GetColor(currentPoint).ToVector4(); var finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, opacity); finalColor.W = backgroundVector.W; TColor packed = default(TColor); packed.PackFromVector4(finalColor); sourcePixels[offsetX, offsetY] = packed; } } }); } }