Exemple #1
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TColor> source, Rectangle sourceRectangle)
        {
            using (PixelAccessor <TColor> sourcePixels = source.Lock())
                using (PenApplicator <TColor> applicator = this.Pen.CreateApplicator(sourcePixels, this.Path.Bounds))
                {
                    Rectangle rect = RectangleF.Ceiling(applicator.RequiredRegion);

                    int polyStartY = rect.Y - PaddingFactor;
                    int polyEndY   = rect.Bottom + PaddingFactor;
                    int startX     = rect.X - PaddingFactor;
                    int endX       = rect.Right + PaddingFactor;

                    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;
                    }

                    Parallel.For(
                        minY,
                        maxY,
                        this.ParallelOptions,
                        y =>
                    {
                        int offsetY = y - polyStartY;

                        for (int x = minX; x < maxX; x++)
                        {
                            // TODO add find intersections code to skip and scan large regions of this.
                            int offsetX    = x - startX;
                            PointInfo info = this.Path.GetPointInfo(offsetX, offsetY);

                            ColoredPointInfo <TColor> color = applicator.GetColor(offsetX, offsetY, info);

                            float opacity = this.Opacity(color.DistanceFromElement);

                            if (opacity > Constants.Epsilon)
                            {
                                Vector4 backgroundVector = sourcePixels[offsetX, offsetY].ToVector4();
                                Vector4 sourceVector     = color.Color.ToVector4();

                                Vector4 finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, opacity);
                                finalColor.W       = backgroundVector.W;

                                TColor packed = default(TColor);
                                packed.PackFromVector4(finalColor);
                                sourcePixels[offsetX, offsetY] = packed;
                            }
                        }
                    });
                }
        }
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TPixel> source, Rectangle sourceRectangle)
        {
            using (PixelAccessor <TPixel> sourcePixels = source.Lock())
                using (PenApplicator <TPixel> applicator = this.Pen.CreateApplicator(sourcePixels, this.Path.Bounds, this.Options))
                {
                    Rectangle rect = RectangleF.Ceiling(applicator.RequiredRegion);

                    int polyStartY = rect.Y - PaddingFactor;
                    int polyEndY   = rect.Bottom + PaddingFactor;
                    int startX     = rect.X - PaddingFactor;
                    int endX       = rect.Right + PaddingFactor;

                    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;
                    }

                    int width = maxX - minX;
                    PixelBlender <TPixel> blender = PixelOperations <TPixel> .Instance.GetPixelBlender(this.Options.BlenderMode);

                    Parallel.For(
                        minY,
                        maxY,
                        this.ParallelOptions,
                        y =>
                    {
                        int offsetY = y - polyStartY;

                        using (Buffer <float> amount = new Buffer <float>(width))
                            using (Buffer <TPixel> colors = new Buffer <TPixel>(width))
                            {
                                for (int i = 0; i < width; i++)
                                {
                                    int x          = i + minX;
                                    int offsetX    = x - startX;
                                    PointInfo info = this.Path.GetPointInfo(offsetX, offsetY);
                                    ColoredPointInfo <TPixel> color = applicator.GetColor(offsetX, offsetY, info);
                                    amount[i] = (this.Opacity(color.DistanceFromElement) * this.Options.BlendPercentage).Clamp(0, 1);
                                    colors[i] = color.Color;
                                }

                                BufferSpan <TPixel> destination = sourcePixels.GetRowSpan(offsetY).Slice(minX - startX, width);
                                blender.Blend(destination, destination, colors, amount);
                            }
                    });
                }
        }